2010-10-28 28 views
4

我的問題是爲什麼我需要IDisposable?我有一個類需要釋放一些資源 。我有兩個選擇關於IDisposable的問題

沒有了IDisposable

class SomeUtilityClass 
{ 
public Stop() 
{ 
    // free resources 
} 
} 

隨着IDisposable的

class SomeUtilityClass, IDisposable 
    { 
    public void Dispose() 
    { 
     // free resources 
    } 
    } 

那麼,爲什麼我需要IDisposable的嗎?它不會如何命名該函數。

class Program 
{ 

public Main(..) 
{ 
    SomeUtilityClass _class = new SomeUtilityClass(); 

    // clean up when we've done 

    _class.Stop(); 

    // OR 
    _class.Dispose(); 

} 
} 
+0

可能重複:http://stackoverflow.com/questions/3845542/writing-our-own-dispose-method-而不是使用一次性使用 – Patrick 2010-10-28 11:55:10

回答

5

因爲IDisposable的是C#的支持,你可以使用酷using語法:

using (IDisposable someDisposable = new ...) 
{ 
    // your code with someDisposable 
} 

這是由編譯器實際上轉化爲類似:

IDisposable someDisposable = new ... 
IDisposable someDisposable2 = someDisposable ; 
try 
{ 
    // your code with someDisposable 
} 
finally 
{ 
    if (someDisposable2 != null) 
    { 
     someDisposable2.Dispose(); 
    } 
} 

因此,如果任何異常情況裏面using阻止你的對象將被處置。

+0

所以使用IDisposable的唯一理由是'只是在你要使用'的情況下'使用'' – 2010-10-28 11:47:02

+0

使用的主要優點是它用try/finally塊封裝你的代碼,所以你所有的資源都會如果發生異常,可以正確發佈。 – 2010-10-28 11:48:18

+0

沒錯,所以可以說IDisposable只是介紹「使用」包裝? – 2010-10-28 11:49:44

1

IDisposableusing關鍵字進行交互,以方便以後自己進行清理,如:

using (var file = new FileStream(...)) 
{ 
    file.Write(...); 
} 

在上面的代碼中,FileStream是隻要使用塊完成關閉,而不是等待各地被垃圾收集。

1

這是C#語言中使用的慣例。

您還可以獲得精美的using聲明供您使用。

using (SomeUtilityClass _class = new SomeUtilityClass()) { 

} // Dispose is automatically called 
1

除了作爲能夠使用使用語句時,它也給垃圾收集器的提示該對象可以從存儲器中刪除。

+0

你說的是public void Dispose()嗎? – 2010-10-28 11:54:10

+0

您的班級實施IDisposable將標記要由GC清除的程序集,而不僅僅是具有功能 – Iain 2010-10-28 13:12:37

2

那麼在你的情況下,實現IDisposable沒有太大的意義,因爲你可以手動處理你的資源。

IDisposable的一個常見用法是當您公開一個處理數據連接的接口,並且希望所有派生類在完成時處置。

考慮一下:

public interface IDataCtx 
{ 
    void CallDB(); 
} 

public class MyDataCtx : IDataCtx 
{ 
    private SqlConnection dc; 

    public MyDataCtx() { dc = new SqlConnection(); dc.Open(); } 

    public void CallDB(); 
    { 
     dc.Something(); 
    } 
} 

讓你做這樣的事情:

IDataCtx ctx = new MyDataCtx(); 
ctx.CallDB(); 

別急,怎麼樣打開連接?呃哦!

如果你做IDataCtx : IDisposable(並實現在派生CTX的代碼),你可以這樣做:

IDataCtx ctx; 
using (ctx = new MyDataCtx()) 
{ 
    ctx.CallDB(); 
} 

低保無論你使用IDataCtx的實現,它將始終即使在處置(例外情況)。

這就是我無論如何都使用它。 (加上這只是一個好習慣)。

+0

感謝您的示例代碼。但那需要我使用「使用」,否則保證書是無效的? – 2010-10-28 12:01:42

+1

正確。你當然可以試着/ catch/finally(並且最終明確地處理),但這是更好的做法。 – RPM1984 2010-10-28 21:06:37

3

當您的類使用非託管資源時,您應該只使用IDisposable,並且需要立即釋放它們(流,db等)。

它還提供了一種方法,當存在導致您的線程被卸載的未處理的異常時,CLR會「清除」。

調用IDisposable將對象標記爲立即可用於垃圾回收,但如果執行不正確,則可能導致您的對象被提升爲可能導致內存壓力的垃圾回收生成(如果您是通過c#3參考Jeffery Richters CLR想要一個完整的解釋)。

快速谷歌把這個了: http://kleahy-technical.blogspot.com/2009/01/idisposable-and-garbage-collection.html

我建議你讀入IDisposable模式,當使用它的時候不要及其對GC和狀態的影響。

編輯: 有計算器上的信息負荷過: Use of Garbage Collection?

1

如果你的類擁有非託管資源或您的類擁有管理IDisposable的資源,你應該在generel實現IDisposable接口。

何時實現IDisposable和終結一個簡單可讀的小文章可以在這裏找到:http://nitoprograms.blogspot.com/2009/08/how-to-implement-idisposable-and.html

+0

該文章省略了iDisposabe的一個關鍵用例:訂閱來自更長壽命對象的事件的對象。當你的對象不再有用時,你添加到長壽命對象的任何代表都必須被刪除,否則你的對象的生命週期以及你的對象所持有的任何其他對象將被固定爲更長壽的物體。 – supercat 2010-10-30 03:05:18