2010-03-08 91 views
3

下面的代码是从MSDN的Dispose()实现代码:Idisposable pattern帮助我理解从MSDN

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 (_resource != null) { 
      _resource.Dispose(); 
      _resource = null; 
      _disposed = true; 
      } 
     Console.WriteLine("Object disposed."); 
    } 

什么错我的版本?

回答

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方法,表明它是一个真正的部署和supresses进一步敲定。

这不是安全定稿过程中调用任何其它目的,所以这就是为什么要设置:

_resource = null; 
_disposed = true; 

,以防止任何进一步mishappenings。

这是good info关于在MSDN上定稿和IDisposable。

1

调用Dispose()后,资源应始终标记为已处理,否则可能会遇到问题。所以,即使_resource为空,您也需要将其标记为已处理。

运行

_resource = null; 

不伤就算是资源处为零首位。

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.");
}

是我会怎么写。

1

Dispose(bool)函数通常被称为从Dispose()和来自终结者(在C#中命名为〜类)。当由终结器调用时,垃圾收集已在进行中,并且未定义不同对象之间垃圾收集的顺序。垃圾收集器很可能会摧毁_resource了,所以只有当Dispose(bool)从我们要消灭“子资源” Dispose()叫(这是管理的资源真正的,非托管资源应始终会被释放)

+0

我不喜欢微软使用术语“垃圾回收”来包含终结和对象销毁。如果类Foo的可终结实例Zoo拥有一个名为'Bar'的类型为'Bar'的字段,该字段包含一个非空对象引用,那么该引用*的目标*在执行' Zoo.Finalize()'。目标可能已经运行了它的'Finalize()'方法,或者可能被调度来执行,或者可能仍然在某处使用,但是在任何情况下,如果'Zar'非空,则保证不会被垃圾收集器摧毁。 – supercat 2012-02-28 17:37:32

1

放置的问题在MSDN模式中是正确的

原因是,在正确的实现中,正如我在下面引用的博客中所提供的,Dispose(bool)的重载版本在调用中传递值为false终结者。请注意,如果您确实需要一个Finalizer,则只应实现一个Finalizer。也就是说,这些线的位置不应该根据您是否实施Finalizer而有所不同。

我在我的博客上写了一个改进版的IDisposable模式 - How do you properly implement the IDisposable pattern?。你会发现我提供的这种模式的实现与MSDN上发布的稍有不同。恕我直言,这是不够的。您必须同意MSDN上发布的大量示例和示例是“hacky”,不要像在“现实世界”中应该这样做。

+0

微软的模式中有一些我觉得不愉快的事情,而且你的代码似乎跟随它的前进。最值得注意的是,如果'Dispose'被多次调用,'Dispose(bool)'同样会被多次调用,并且由于'Disposed'是私有的,所有想要防止冗余处理的派生类都需要自己的'Disposed'旗。我认为有一个'int DisposeStatus'通过'IDisposable.Dispose'包装器方法(它应该只在调用Dispose(bool)''''时将'Interlocked.Exchange''d设置为1。 – supercat 2012-02-28 17:00:57