在 IDisposable 对象数组中使用 Dispose() 或不使用 Dispose() 元素?
To Dispose() or Not To Dispose() elements in an array of IDisposable objects?
有很多从 .NET 中的函数返回 IDisposable 对象数组或列表的示例。例如,Process.GetProcesses()
。
- 如果我调用该方法,我有责任在遍历数组的所有成员时对它们进行 Dispose() 吗?
- 为什么这应该是我的责任,因为我从未创建过对象,而我得到的数组只是指向在我的代码之外创建的对象的指针。
一直以为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
实例。
有很多从 .NET 中的函数返回 IDisposable 对象数组或列表的示例。例如,Process.GetProcesses()
。
- 如果我调用该方法,我有责任在遍历数组的所有成员时对它们进行 Dispose() 吗?
- 为什么这应该是我的责任,因为我从未创建过对象,而我得到的数组只是指向在我的代码之外创建的对象的指针。
一直以为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
实例。