MSDN Dispose()示例错误? (何时将托管引用设置为null)

MSDN用于实现Dispose()方法的示例模​​式描述了将对已处置的受管资源的引用设置为null( _resource = null ),但在if (disposing) _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没有处理_resource ,那么当对象(包括_resource成员字段)即将被垃圾收集时,需要将它设置为null?


[原始问题结束]

跟进:

经过多次阅读后,似乎没有必要将引用设置为null,但如果您有理由相信包含的类(被处理的类)可能不会很快被垃圾收集,那么对于“重”成员对象可能是一个好主意。

知道对象处理不能保证对象已被消费代码“释放”。 为了各种目的,处置的物体可能被保留在(在集合中或其他地方),或者只是错误地存在。 我可以想象一个应用程序使用集合中的对象然后处理它们,但是将它们保存在集合中以供稍后的进程执行删除和记录最终状态(或类似的东西……谁知道…)

结论:

  1. 将“重”成员对象的引用设置为null会释放它们以进行垃圾回收,即使未释放已处置的对象也是如此。
  2. 清除所有对象的引用是一种过度的做法。
  3. 因此, _resource = null语句(原始问题)的放置并不重要,原因有两个:(A)完全使用它只是在阅读上述内容后要考虑的事情; (B)在MSDN示例中,它对Dispose(true)Dispose(false) ,但后者仅在对象完成时才会发生,并且即将被垃圾收集!

因此,我的偏好是将_resource = null放在最内部的if块中:

 if (disposing) { if (_resource != null) { _resource.Dispose(); _resource = null; } } 

这将所有_resource代码保存在一起。 还有什么想法?

更多阅读:

  • 在Dispose(bool)方法实现中,是否应该将成员设置为null?
  • 你需要处理对象并将它们设置为null吗?
  • http://www.codeproject.com/KB/dotnet/idisposable.aspx (很好,很长!)

将其设置为null是删除指向堆中位置的引用或指针。 这让GC可以通过并删除任何没有引用它的东西,而不需要做太多的猜测。 _resource是一些内部使用对象,需要清理它的引用,所以假设你有一个内部的Socket,你将关闭/处置该套接字或任何其他持久资源。 处理完毕后,将其设置为null并删除所有引用(应删除所有引用),以便GC可以正常工作。 我的答案的下半部分是一个例子,所以它重复了一些事情,但我希望你能得到这个想法。

将它设置为null两次并不是什么大问题,因为没有效果。 在清理任何资源时处置应该是正确的,并且一旦它(如你所说)即将进行垃圾收集,它只是错误的。