在 IDisposable 对象数组中使用 Dispose() 或不使用 Dispose() 元素?

To Dispose() or Not To Dispose() elements in an array of IDisposable objects?

有很多从 .NET 中的函数返回 IDisposable 对象数组或列表的示例。例如,Process.GetProcesses()

一直以为Dispose()是创作者的负担。 那么这里的正确规则是什么?

规则很简单:如果您认为其他程序会使用您的 IDisposables,则不要破坏它们。否则,做。

例如:GetProcesses() returns 其他进程可能被其他程序使用,因此 您不应该处置 它们。

从另一方面来说,您打开的文件应该为 OS 中的其他进程释放,因此您应该关闭并在它们之上处理包装流(例如,您应该处理File.Open 方法返回的蒸汽)。

更新:
From MSDN:

  • DO implement the Basic Dispose Pattern on types containing instances of disposable types. See the Basic Dispose Pattern section for details on the basic pattern. If a type is responsible for the lifetime of other disposable objects, developers need a way to dispose of them, too. Using the container’s Dispose method is a convenient way to make this possible.
    • DO implement the Basic Dispose Pattern and provide a finalizer on types holding resources that need to be freed explicitly and that do not have finalizers.
      For example, the pattern should be implemented on types storing unmanaged memory buffers. The Finalizable Types section discusses guidelines related to implementing finalizers.
    • CONSIDER implementing the Basic Dispose Pattern on classes that themselves don’t hold unmanaged resources or disposable objects but are likely to have subtypes that do.

没有一般规则。 "you" 是否负责处理您有权访问的对象,这将取决于具体情况以及相关方法的设计方式。这就是文档对于帮助此类用户理解他们的职责通常很重要的地方。

I always thought it was the creator's burden to Dispose()

这不可能是严格意义上的。有时,一次性对象的生命周期会超过创建它的代码块的生命周期。虽然创建者 可以 处置对象是 最简单,但有时他们根本不可能做到。当从方法返回一次性对象时,创建一次性对象的代码通常不可能清理它,因为它的生命周期需要 小于 的生命周期一次性物品。

除了相对较少的例外(其中大多数可以被描述为处理设计不佳且无法更改的代码的最不邪恶的方法),每个 IDisposable 实例都应该在任何给定时刻及时有一个明确的所有者。在方法 returns 某种实现 IDisposable 的类型的情况下,该方法的契约将指定该方法是否放弃所有权(在这种情况下,调用者应确保对象被处置——通过处置对象本身或放弃对其他人的所有权),或者该方法是否仅返回对其他人.

所拥有的对象的引用

在正确编写的代码中,对象是否应该被释放的问题很少是判断调用。对象的所有者应该确保它被处置;没有其他人应该处理它。有时可能需要让一个方法接受一个参数,该参数指示该方法是否应该转移 IDisposable 的所有权。例如,如果代码想要创建一个声音,将它传递给 "start playing sound" 方法,并且不想再次处理该声音,那么让播放声音的代码接受并处理可能是最方便的完成时发出声音;但是,如果代码希望能够重复播放声音,并确保声音对象在需要时一直存在,则播放声音的代码 not 取得所有权。使用单独的方法在某些方面可能更简洁,但使用参数可以帮助封装。

通常,当代码 returns 实现 IDisposable 的对象列表时,代码的目的是 识别 对象而不传达任何所有权权益在他们中。在没有所有权权益的情况下,接收此类列表的代码应该对其调用Dispose

GetProcesses 方法不会在返回的 Process 个实例中分配任何句柄(或其他非托管资源)。

只有在返回的 Process 实例上调用某些方法时才会创建句柄,在几乎所有情况下,这些句柄都会在返回之前释放(例如 Process.Kill)。

因此,在大多数情况下完全没有必要处理每个返回的 Process 实例。