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

Kev*_*ice 12 c#

MSDN用于实现Dispose()方法的示例模​​式描述了将对已处置的受管资源的引用设置为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;   
    }
}
Run Code Online (Sandbox Code Playgroud)

_resource = null应该放在这个代码块里面?如果进行了调用,Dispose(false)那么_resource将为null并且无法随后处理!??

当然,Dispose(false)仅在完成时由运行时调用(在实践中).但是如果_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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

更多阅读:

Jes*_*mos 7

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

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

  • 在完整模式(http://msdn.microsoft.com/en-us/library/b1yfkh5e.aspx)中,Dispose()调用Dispose(true)信令处理所有资源.终结器调用Dispose(false)来指示仅处理非托管资源(托管引用在最终确定发生时不安全使用).如果没有非托管资源,建议不要使用终结器.因此,如果不存在非托管资源,则不需要终结器OR Dispose(bool); 只有Dispose()是必要的.[最佳答案通常不会给你你想要的东西,它们会迫使你学习更多!] (4认同)
  • 哇!顿悟!你只是让我意识到,如果没有终结器(并且在大多数情况下不应该),则不需要`Dispose(bool)`!我一直专注于"模式"我没有意识到`IDisposable`只包括`Dispose()`.任何`dispos` bool标志都可以在`Dispose()`中实现,并且没有理由拥有`Dispose(bool)`方法!谢谢!获得最有价值的评论! (3认同)