帮助我理解来自MSDN的Dispose()实现代码

时间:2010-03-08 09:52:32

标签: c# idisposable

以下代码来自MSDN:Idisposable pattern

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;  
_disposed = true; 

不包含在if(disposing)语句块中吗?

对我来说,我可能会这样写:

if (disposing) {
       if (_resource != null) {
            _resource.Dispose();
            _resource = null;
            _disposed = true;
           }
         Console.WriteLine("Object disposed.");
   }

我的版本出了什么问题?

5 个答案:

答案 0 :(得分:1)

在调用Dispose()之后,资源应始终标记为已丢弃,否则可能会遇到问题。因此,即使_resource为null,您也需要将其标记为已处置。

正在运行

_resource = null;
即使资源首先为空,

也不会受到伤害。

答案 1 :(得分:1)

是;)

好的,_resource = null - 正如你所说的那样有恕我直言。示例代码在这里很邋,抱歉;)我也喜欢你的方式。

但是,

_disposed = true,如果_resource存在则是独立的。如果_resource指针尚未初始化,则应该设置它,因此它应该直接位于Console.WriteLine之上。想象一下_resource是一个文件处理程序的情况,它在类中的方法调用期间打开 - 可能存在创建类的情况,但文件处理程序没有,在这种情况下,dispose也必须起作用。

if (disposing) {
if (_resource != null) {
_resource.Dispose();
_resource = null;
}
_disposed = true;
Console.WriteLine("Object disposed.");
}

是我写它的方式。

答案 2 :(得分:1)

MSDN概述的模式是实现IDisposable的唯一正确方法,因为它考虑了最终结果。您需要仔细查看IDisposable实现:

public void Dispose() 
{
    Dispose(true);

    // Use SupressFinalize in case a subclass
    // of this type implements a finalizer.
    GC.SuppressFinalize(this);      
}

这会调用你的dispose方法,表明它是一个真正的处理方法,并阻止进一步的最终确定。

在最终确定期间呼叫任何其他对象是不安全的,所以这就是你想要设置的原因:

 _resource = null;  
_disposed = true; 

以防止任何进一步的错误发生。

这是MSDN上的终结和IDisposable上的good info

答案 3 :(得分:1)

Dispose(bool)函数通常从Dispose()和Finalizer(在C#中命名为~Class)中调用。当终结器调用时,垃圾收集已经在进行中,并且没有定义不同对象之间的垃圾收集顺序。垃圾收集器可能已经很好地销毁了_resource,所以只有当Dispose(bool)Dispose()调用我们想要销毁“子资源”时才会这样做(对于托管资源,这是真的,不受管理应始终释放资源)

答案 4 :(得分:1)

有问题的2行的位置在MSDN模式中是正确的

原因是在正确的实现中,正如我在下面引用的博客中所提供的,Dispose(bool)的重载版本在Finalizer的调用中传递值false。请注意,如果您确实需要Finalizer,则应该只实现Finalizer。话虽如此,这些行的位置不应根据您是否实现Finalizer而有所不同。

我在博客上写了一个改进版的IDisposable模式 - How do you properly implement the IDisposable pattern?。您会发现我提供的此模式的实现与MSDN上发布的实现略有不同。恕我直言,这还不够。您必须同意MSDN上发布的大量示例和示例都是“hacky”,并且不会像在“现实世界”中那样完成它们。