2010-03-08 87 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