2009-04-20 49 views
7

我在.NET中編程了四年(主要是C#),並且我廣泛使用了IDiposable,但是我還沒有找到需要一個終結器。什麼是終結者?什麼是結局?

+5

順便說一句,我是英國人,我發現這是一個*真的* *真的*好主意,養成用z而不是s來拼寫「finalize」和「initialize」的習慣。否則,當您在文檔中搜索它們時,您永遠無法找到血腥的東西! – 2009-04-20 14:38:30

+1

@onebyone - 同上。同樣,色彩......它曾經引起我的憤怒,但現在我只是將它們視爲行業的技術術語,並完成工作; -p – 2009-04-20 14:49:43

+0

我一直在試圖訓練自己 - 我將它用於文檔和公共面臨的代碼,但我不能讓自己在「現實生活」中做到這一點。 – 2009-04-20 15:01:21

回答

10

終結器是確保正確清理內容的最後一次嘗試,並且通常保留用於包裝非託管資源的對象,例如非託管句柄等不會收集垃圾的對象。

編寫終結器確實很少見。幸運的是(不像IDisposable),終結器不需要傳播;所以如果你有一個帶終結符的ClassA和包含ClassAClassB,那麼ClassB不需要終結符 - 但很有可能ClassAClassB將實現IDisposable

對於託管代碼,IDisposable通常就足夠了。即使你沒有正確清理,最終管理對象也會被收集(假設它們被釋放)。

1

終結器是用於清理資源,如果他們沒有處置。

IE中,沒有任何東西強制您調用Dispose(),但終結器由垃圾回收器自動調用。

不應該依賴此功能,因爲無法保證何時(或如果)垃圾回收會到達您的對象。

2

終結器是指釋放不受垃圾回收器控制的資源的機制,如非託管句柄。雖然Dispose可能會這樣做,但並不保證消費者會給它打電話。

4

終結器僅用於釋放非託管資源,例如GDI位圖句柄。如果你不分配任何非託管資源,那麼你不需要終結器。一般來說,在終結器中觸摸任何對象都是不好的,因爲不能保證結束的順序。

使用終結器的另一個有用技巧是聲明當需要應用程序時調用Dispose。這可以幫助捕捉在調試版本編碼錯誤:

void Dispose() 
{ 
    GC.SuppressFinalize(this); 
} 
#if DEBUG 
~MyClass() 
{ 
    Debug.Fail("Dispose was not called."); 
} 
#endif 
1

維基百科says

...終結是一段代碼, 確保當獲取的某些必要的行動 採取資源...... 不再被使用的,因爲 所屬對象已被垃圾收集 ]

如果在編寫IDisposables時不使用終結器,則很可能會發生內存泄漏,因爲不能保證所有者實際上會調用Dispose()。

MS自己建議你寫類似這樣到你的實施者東西:

public void Dispose() 
    { 
     this.Dispose(true); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (!this.isDisposed) 
     { 
      if (disposing) 
      { 
       GC.SuppressFinalize(this); 
      } 
     } 
     //Dispose of resources here 
     this.isDisposed = true; 
    } 

    ~DisposableSafe() 
    { 
     this.Dispose(false); 
    } 

    private bool isDisposed = false; 

就個人而言,我不能忍受的複製粘貼,所以我傾向於包裹,在重用的抽象類。

+0

除非您的課程直接處理*非託管*資源,否則您可能不需要終結者。無論用戶是否調用Dispose,管理資源最終都應由GC處理。 – LukeH 2009-04-20 14:57:51

+0

這是讓我寫「可能」而不是「可能」,我擔心這一點。但無論如何它並不完全正確。如果你的類實現了一些其他的IDisposable,那麼你也有責任調用Dispose()。而且從MSDN開始「這個接口的主要用途是釋放非託管資源。」 – annakata 2009-04-20 15:29:49