用于实现 Dispose() 方法的 MSDN's example pattern 描述了将对已处置托管资源的引用设置为 null (_resource = null
),但在 if (disposing)
之外执行此操作> 阻止:
protected virtual void Dispose(bool disposing)
{
// If you need thread safety, use a lock around these
// operations, as well as in your methods that use the resource.
if (!_disposed)
{
if (disposing) {
if (_resource != null)
_resource.Dispose();
Console.WriteLine("Object disposed.");
}
// Indicate that the instance has been disposed.
_resource = null;
_disposed = true;
}
}
_resource = null
不应该放在这个代码块中吗?如果调用 Dispose(false)
,则 _resource
将为 null 且随后无法处理! ??
当然,Dispose(false)
仅在终结期间由运行时调用(实际上)。但是如果_resource
之前没有被disposed,那么在这个对象(包括_resource
成员字段)即将成为垃圾的时候,为什么需要在此时将它设置为null收集到?
[原问题结束]
跟进:
经过大量阅读,似乎没有必要将引用设置为 null,但如果您有理由相信包含类(被处置的类)可能不会被垃圾收集,那么对于“重”成员对象来说可能是个好主意很快。
知道对象处置并不能保证对象已被消费代码“释放”。已处置的对象可能出于各种目的而被保留(在集合中或以其他方式),或者只是为了错误。我可以想象一个应用程序使用集合中的对象然后处理它们,但将它们保留在集合中以供以后执行删除和记录最终状态的过程(或类似的东西......谁知道......)
结论:
- 将对“重”成员对象的引用设置为 null 释放它们 用于垃圾回收,即使已处置的对象未被释放。
- 清除所有对象的引用是多余的。
- 因此,
_resource = null
语句(原始问题)的放置并不重要,原因有二:(A) 完全使用它只是阅读上述内容后需要考虑的事情; (B) 在 MSDN 示例中,它针对Dispose(true)
和Dispose(false)
执行,但后者仅在对象完成并即将执行时发生无论如何都要收集垃圾!
因此,我的偏好是将 _resource = null
放在最内部的 if
block 中:
if (disposing) {
if (_resource != null) {
_resource.Dispose();
_resource = null;
}
}
这将所有 _resource
代码放在一起。进一步的想法,有人吗?
更多阅读:
最佳答案
将其设置为 null 会删除指向堆中位置的引用或指针。这让 GC 可以通过并删除任何没有引用它的东西,而不必做很多猜测。 _resource 将是一些需要清理其引用的内部使用对象,因此假设您在关闭内部有一个套接字,您将关闭/处置该套接字或任何其他持久资源。一旦它被处置,你将它设置为 null 并删除所有引用(应该删除所有引用)以便 GC 可以完成它的工作。我回答的第二部分是一个例子,所以它重复了一些事情,但我希望你能理解。
将它设置为 null 两次没什么大不了的,因为没有任何效果。在清理任何资源时 Disposing 应该是正确的,并且只有在(如您所说)即将被垃圾收集时它才是错误的。
关于c# - MSDN Dispose() 示例错误? (何时将托管引用设置为空),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6757048/