应该为 Process.GetCurrentProcess() 调用 Dispose 吗?

Should one call Dispose for Process.GetCurrentProcess()?

例如,参见

How to get the current ProcessID?

没有人愿意为 System.Diagnostics.Process.GetCurrentProcess() 返回的对象调用 Dispose。它真的应该被调用吗?请解释原因。

是的,其实也很重要。如果你看到实际的 source,你会看到 Dispose 不仅继承自 Component,它也做了一些事情。

在我看来,查看该代码时,将 EnableRaisingEvents 设置为 true 时最为重要,因为这涉及创建等待句柄。需要释放该句柄以防止内存和句柄泄漏。

这是一个艰难的决定。

您可能不必为从 Process.GetCurrentProcess() 获得的 Process 实例调用 Dispose,以防您没有触及 Handle 属性以及其他一些敏感点。

让我们看看包含Dispose逻辑本质的Process.Close方法。

    public void Close()
    {
        if (this.Associated)
        {
            if (this.haveProcessHandle)
            {
                this.StopWatchingForExit();
                this.m_processHandle.Close();
                this.m_processHandle = null;
                this.haveProcessHandle = false;
            }
            this.haveProcessId = false;
            this.isRemoteMachine = false;
            this.machineName = ".";
            this.raisedOnExited = false;
            this.standardOutput = null;
            this.standardInput = null;
            this.standardError = null;
            this.Refresh();
        }
    }

您可以看到,只有当 Process 实例具有进程句柄时,这里才会发生一些真实的事情。 Refresh 方法与我们的主题无关。

如果进一步观察,您会发现当 Handle 属性 被访问时,进程句柄可以被 Process 实例获取(并因此持有)。不过这不是唯一的案例

    public IntPtr Handle
    {
        get
        {
            this.EnsureState(Process.State.Associated);
            return this.OpenProcessHandle().DangerousGetHandle();
        }
    }

作为一般规则:如果它实现了 IDisposable - 你应该调用 Dispose.

在您的特定情况下,如果您只触摸当前进程名称或无辜的东西,您可以省略 Dispose 调用并摆脱它。

这是一个例子:

        Process process = Process.GetCurrentProcess();

        var fieldInfo = typeof(Process).GetField("haveProcessHandle", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
        var v1 = fieldInfo.GetValue(process);
        //v1 is false. Explicit Dispose is not necessary.

        var processName = process.ProcessName;
        var v2 = fieldInfo.GetValue(process);
        //v2 is false. Explicit Dispose is not necessary.

        var processHandle = process.Handle;
        var v3 = fieldInfo.GetValue(process);
        //v3 is true. Bah. Explicit Dispose IS necessary from now on.

我使用反射的唯一原因是:如果您通过 Visual Studio 调试器监视 process 变量,它将遍历属性并读取可怕的 Handle 属性.

Process class 是“糟糕的设计模式”的完美示例,因为它在 get 访问器中彻底改变了对象状态。