2010-09-16 17 views
1

假設我有一個MyObject對象,它有兩個接口:IMyContractIDisposable。我有一個方法中的代碼:如果使用接口,則需要處置

IMyContract blah = new MyObject(); 
blah.Blah(); 
return; 

這是一個潛在的內存泄漏,對嗎?它不需要是:

using (MyObject blah = new MyObject()) 
{ 
    blah.Blah(); 
} 
return; 

回答

6

那麼,如果它實現IDisposable你應該確實處置它。如果不這樣做 - 或者持續多久 - 沒有說什麼會泄漏,但是你應該有一個using聲明來避免它。

(只是爲了澄清:內存是被泄露的至少容易的事情,因爲IDisposable一般約爲非託管資源,如網絡連接等,這是可能的,當然 - 對象可能對分配一些內存句柄遠離GC的目光。任何實現IDisposable持有直接引用非託管資源,也應該有一個終結,所以泄漏應該只是暫時的......但是這可能仍然是痛苦的。)

+0

不是默認的對象。Finalize()檢查實例以查看它是否爲IDisposable,並調用Dispose()方法? – KeithS 2010-09-16 19:07:22

+0

@KeithS:「Object.Finalize默認不做任何事。」 http://msdn.microsoft.com/en-us/library/system.object.finalize(VS.71).aspx請注意,在C#中使用析構函數語法('〜ClassName()')來覆蓋Object。 Finalize()' – 2010-09-16 19:09:07

1

你可以請在您的第一個示例中進行處理:

IMyContract blah = new MyObject(); 
blah.Blah(); 
((IDisposable)blah).Dispose(); 
return; 

不太清潔,但有時您必須使用接口。

另一種可能性是您的接口本身繼承IDisposable。然後,你可以使用:

using (IMyContract blah = new MyObject()) 
{ 
    blah.Blah(); 
} 
return; 
+1

請注意,如果'Blah'引發異常,您將無法進入第一種情況的'Dispose'行。 – 2010-09-16 18:49:44

1

如果IDisposableimplemented properly(與調用Dispose()並沒有SuppressFinalize終結),垃圾收集器會得到它最終會。但是,using()try { ... } finally { object.Dispose(); }相同,它將確定性地(明確地儘快)處置。如果您依賴垃圾收集器,您可能會驚訝需要處理多久。如果存在非託管資源,則可能會因爲它們尚未被釋放而迅速耗盡。

編輯:我第一次錯過了這一點。是的,當您使用MyObject時,您應該Dispose()using()正確。如果你有一個使用該接口,那麼你可以有類似其他代碼:

public IMyContract GetInterface() 
{ 
    using (MyObject obj = new MyObject()) 
    { 
    obj.DoSomething(); 
    return (IMyContract)obj; 
    } 
} 

的代碼,然後可以使用IMyContract contract = GetInterface();,而不必擔心(或者甚至不知道),其餘的事情要處理。

+1

我不知道你的意思,但你的答案意味着調用'object.Dispose'將決定性地釋放內存。事實並非如此。調用'Dispose'確定性地釋放該對象使用的任何非託管對象(當然,提供了'Dispose'方法正確實現),但它不影響垃圾收集堆。 – 2010-09-16 18:57:58

+0

不,你說得對。 GC將調用終結器(如果它沒有被抑制),遵循標準的'IDisposable'模式會調用'Dispose(true)'來釋放非託管資源。 – 2010-09-16 19:05:24

0

從技術上講,你不能導致內存泄漏。但是,您最終可能會持有資源比必要的時間更長。

如果IMyContract的實現者通常是一次性的(或可能是一次性的),那麼IMyContract應繼承自IDisposable。否則,你可以從IDisposable繼承MyObject

無論哪種方式,該對象當然應該被處置。

相關問題