2011-12-01 114 views
1

我很困惑什麼時候以及如何實現IDisposable。IDisposable - 正確的方法實現(c#)

我看到它需要實現IDisposable只對持有非託管資源

因此類,如果我有「A」級持有unmanged和管理資源,我實現IDisposable非託管資源,包括GC.SuppressFinalize(這個),那麼如果GC現在不會爲我的班級調用finializer,管理資源將如何清理?

我真的會如並欣賞別人可以了IDisposable我更加清晰(何時以及如何使用)

+2

這裏的職位是非常明確的=> http://stackoverflow.com/questions/538060/proper-use-of-the-idisposable-interface – StuartLC

+0

感謝!我會讀這個 – Maya

回答

1

這是不正確。您也可以爲受管理類實施IDispose。如果您只有託管資源,並且您的客戶端不調用Dispose,則資源將在某個時刻被垃圾回收器釋放。但是,如果您希望更早釋放資源(例如關閉文件或數據庫連接),請在您自己的Dispose方法中執行此操作。

除非你有一個終結器,否則你不應該用GC.SuppressFinalize。如果你有一個終結者,儘量不要有 - 最好不要進入該地區,除非你絕對必須。

+0

我在MSDN看到GC對它的託管資源要好得多。即使我沒有終結器明確我的課程仍然有一個(如果不是如何GC調用終結?)。也是文件和數據庫他們不unmanged? – Maya

+0

@Maya - 對於您沒有花費昂貴資源的託管資源,GC更好。這幾乎意味着只有佔用相對少量內存的類。對於消耗昂貴或競爭資源的託管類,如文件或線程或網絡連接,即使該類是純粹管理的,您也會希望儘快釋放您確定性的用法。 – codekaizen

0

有關IDisposable接口的唯一的事情是,語言實際上提供了它的特殊結構:「使用」塊:

public void SomeMethod() 
{ 
    using(IDisposable myDisposable = new SomeClassThatImplementsIDisposable()) 
    { 
     //Do something with your disposable... 
    } 
    //And, it's out of scope here 
} 

這是一個有點語法糖哪裏有什麼實際發生的是這樣的:

public void SomeMethod() 
{ 
    IDisposable myDisposable = new SomeClassThatImplementsIDisposable(); 
    try 
    {  
     //Do something with your disposable... 
    } 
    finally 
    { 
     myDisposble.Dispose(); 
    } 
    //And, it's out of scope here 
} 

所以,當你實現IDisposable,你給你的類的客戶使用它,他們可以保證(大部分)的方式,你想讓你的類清理實際情況。

這在保存非託管資源的類中是最常見和最關鍵的。例如,如果你的類正在持有數據庫連接,那麼你不希望客戶端在沒有關閉連接的情況下讓它超出範圍,因爲這會導致內存泄漏。上面的IDisposable用法還可以確保,如果生成一些異常,「using()」暗示的「finally」將調用您的dispose,以便至少清理。

也就是說,在某些情況下您可能會將其用於受管資源。從頭開始考慮的一個例子是,如果您的類的實例正在聆聽比您的類更長的類的實例引發的事件。沒有處置,這也會造成內存泄漏(.NET中的一個常見問題)。

所以,一般來說,如果你的類的一個實例超出了範圍而沒有執行所有的清理代碼,那麼我會使用它。實施IDisposable廣告給您的班級的任何客戶,有資源,它認爲需要妥善處置。

+0

我會爲類對象保留術語「託管資源」,如果這些對象被拋棄並且它們的代碼被垃圾收集,它們將執行任何清理責任,但是如果處置完成,它們將更快地執行它們。我認爲長期出版商附帶的活動訂閱是非託管資源,因爲在放棄活動訂閱者之後可以執行任意數量的第2級集合,並且如果發佈者仍在範圍之內,訂閱者將永遠不符合資格採集。請注意...... – supercat

+0

...事件訂閱在一些現實和合理的情況下可以很容易地表示一個無限的內存泄漏。例如,IEnumerator可能會訂閱已更改集合的事件。如果集合在其生命週期中枚舉了10萬次(幾乎不可信),則可能導致附加100,000個訂閱。除了許多事件訂閱會扼殺系統之外,即使是一百萬枚枚舉也不會令人難以置信。 – supercat

1
  • 時的一部分,很簡單:你應該實現IDisposable時,你的類「擁有」(這是不那麼obviuos有時),這需要進行清除IDisposable的或者非託管資源
  • 如何部分:

    public class AClass : IDisposable 
    { 
    public void Dispose() 
    { 
        Dispose(true); 
        GC.SuppressFinalize(this); 
    } 
    
    protected virtual void Dispose(bool disposing) 
    { 
        if (disposing) 
        { 
        // Free managed objects. 
        } 
        // Free unmanaged objects. 
    } 
    
    ~AClass() 
    { 
    // Simply call Dispose(false). 
        Dispose (false); 
    } 
    

    }

進一步閱讀:
http://www.codeproject.com/KB/dotnet/IDisposable.aspx
http://blogs.msdn.com/b/kimhamil/archive/2008/11/05/when-to-call-dispose.aspx