2009-01-19 52 views
4

沒有討論IDisposable模式的指南/註釋/文章暗示應該在Dispose(bool)方法中將內部成員設置爲null(尤其是如果它們是內存佔用的內存)。在Dispose(bool)方法實現中,不應該將成員設置爲null嗎?

我在調試內部基準測試工具時意識到了它的重要性。過去發生的事情是,這個緩衝區裏面包含一個大數組。我們過去爲整個基準測試程序使用了一個靜態緩衝區。一旦我們完成了緩衝區,我們就無法釋放這個內部數組,我們也不能使這個緩衝區可釋放(因爲它是靜態的)。

所以,我認爲,在Dispose()被調用後,類應該盡其所能,以便它釋放它正在使用的所有資源並使它們再次可用,即使該對象本身不被回收GC,而不是將成員設置爲null,從而不允許GC收集內部對象意味着Dispose實現並不完美。

您對此有何評論?

回答

6

解除時Dispose任何額外的引用是肯定是我嘗試做,有兩個原因:

  • 它允許垃圾收集的內部對象,即使釋放的對象仍處於範圍
  • 如果內部對象是一次性的,這意味着我們只處理過一次,即使Dispose()反覆調用外部對象上

例如,我傾向於使用了諸如:

if(someDisposableObject != null) 
{ 
    someDisposableObject.Dispose(); 
    someDisposableObject = null; 
} 
(for non-disposable, just set to null) 
someNonDisposableObject = null; // etc 

您可能還需要任何事件設置爲null:

someEventHandler = null; 

這可以在瞬間幫助的影響降到最低,如果主叫方不能完全釋放自己的參考(或乾脆忘了)。雖然您應該嘗試釋放外部對象(對於GC),但例如通過捕獲的變量(匿名方法/ lambda),事件等意外延長對象的使用期限相對容易。

如果你有一個終結器,那麼在GC過程中,這樣做沒有好處,你不應該真的在外部對象上調用方法(即使是Dispose()) - 簡而言之:在GC掃描過程中不要執行任何操作。

0

那麼,一般來說,它不會有所作爲。它唯一能夠改變的地方是當你有一個大對象堆上的對象的引用時,你已經看到了這個對象的行爲)。

上有LOH的好文章,其進入該在這裏更詳細:

http://msdn.microsoft.com/en-us/magazine/cc534993.aspx

+2

任何時候對釋放對象的引用都不會被釋放。 – 2009-01-19 05:03:20

1

也許我失去了你的觀點,但是一旦你的對象被設置,根或「子「根」代表它相對於它的成員已被分離。看起來像你正在考慮垃圾收集就像一個參考計數系統(可以完成,但是...通常不是)。

相反,把它看作是一個多根植樹,每個對象都有分支鏈接。在一天結束時,「最終根」是靜態的,任何從「主」循環實例化的東西。

當垃圾收集器運行時,最簡單的思考方法是考慮它將走過「真正的根」列表並將「顏色」應用到它可以「到達」的所有東西。

現在,假設收藏家可以訪問'一切',無論它是否是根源。任何沒有着色的東西都可以清理乾淨。

回到你原來的問題,當你的對象被丟棄時,你會假設(或者至少是希望)沒有人再引用它。如果是這樣的話,它就不再紮根,所以它不會對'觸及'的任何東西着色。如果在Dispose例程中清除成員正在修復某些內容 - 我將會遇到一個不同的,真實的問題,即有人持有指向已處理對象的鏈接,並保持其「可到達」狀態它不應該。

對於可能是我寫過的報價最多的消息,我表示抱歉,但我有點濫用標準條款。

+0

我認爲這可能是儘量減少釋放這些對象所需的掃描量。請記住,GC根據流程運行:免費彩色對象。 – 2009-01-19 06:07:26

+0

@Joe你寫道:「當你的對象被處置時,人們假設(或者至少是希望)沒有人再引用它」處置並不保證一個對象不被保留。也許一組對象在使用後釋放資源,但仍然保留在集合中以供稍後的過程移除它們?在Dispose()中用`resource = null`釋放大量資源不是簡單的好防禦性編程嗎?您無法知道編碼錯誤或錯誤操作可能會對某個對象產生什麼影響。因此,`resource = null`似乎是對於重資源的好做法,不是嗎? – 2011-07-20 12:34:30

相關問題