2014-07-10 52 views
9

我正在爲我的公司清理一些C#代碼,並且我一直注意到的一件事是構建此應用程序的承包商將對象引用設置爲空。是否有任何理由在finally塊中將對象設置爲null?

例子:

get { 
    Object o = new Object(); // create a new object that is accessed by the reference 'o' 
    try { 
    // Do something with the object 
    } 
    finally { 
    o = null; // set the reference to null 
    } 
} 

據我瞭解,在創建對象仍然存在。根據是否有其他參考信息,現在有可能無法訪問它,但在GC出現並清理之前它仍然存在。

是否有任何理由在finally塊中有這個?有沒有可能導致內存泄露的情況?

謝謝!

+3

聽起來像是VB(經典)程序員,他們並沒有去研究.NET內存管理與VB的COM管理有什麼不同。 –

+0

我想這是一種很好的處理方法 –

+1

@MatiCicero:不,它不是。這是一個典型的貨物崇拜節目的例子,它揭示了缺乏理解。 –

回答

14

這取決於範圍。

在您給出的示例中,o僅在屬性的範圍內定義。所以這將是無用的。但是,說o在該範圍內。那麼它可能是有道理的,表示o的狀態。

因爲它目前是不需要的。

+0

但是,無論如何,創建的對象仍會佔用內存,對吧?它只是對被設置爲null的對象的引用。 GC不知道上次使用對象的時間,因此不需要通過將其所有引用都設置爲null來明確地告知它? – CodyEngel

+0

如果引用仍然在範圍內,它們應該設置爲null,這就是GC知道它沒有被使用的方式。 –

+0

@Russell,ahhh我以爲GC的工作方式不同。 – CodyEngel

6

如果意圖是讓GC儘快收集對象,那麼它是完全沒用的。

如果o引用的對象不是try塊之後的任何地方使用,將當選爲收集它最後一次使用後(即變量o之前超出範圍,和之前到達finally塊)。

在相關說明上,請參閱Lippert的Construction Destruction

+2

+1鏈接到Eric Lippert的文章。知道C#中「範圍」的概念與花括號的嵌套很少或根本沒有關係,這一點很重要。 – OldFart

0

我看到至少有兩個理由要做到這一點。首先,使用這種模式一貫有助於捕獲由重用變量引起的錯誤(即,如果這是更大的代碼序列的一部分,變量名稱'o'可能在執行過程中稍後保存不同的對象)。通過明確指定null,如果稍後嘗試使用同一對象(例如,如果更大的塊意外地將構造函數註釋爲部分),則可確保此類代碼導致錯誤。

其次,分配null確保該對象可能可供GC收集。雖然對於類變量更重要,但即使是局部變量也可能會受益。由於該對象不是通過分配讀取,所以任何現有的優化都不應該受到包含該分配的影響(不過我不必)。類似地,賦值本身可能會完全被優化(如果該對象從未被訪問),但由於這些優化都是編譯器的權限,所以使用這種結構允許更早地收集替代編譯模型的可能性,其不包括這樣的優化。

它需要比我擁有的C#語言規範更熟悉,但我懷疑他們沒有說明對象必須在最後一次訪問後立即被分配用於收集。當您嘗試移植到不遵循相同原則的環境時,基於單個編譯器或一組編譯器的當前操作進行這種假設可能會導致更多的工作。

至於潛在的內存泄漏,假設GC工作正常,並且該對象不需要特殊處理,應該沒有問題 - 事實上,您正在專門刪除對未使用內存的潛在引用,可能允許它被回收。對於有特殊處理要求的物體,我希望這些物體在同一地點處理。

+0

我不知道你在說什麼,因爲它只是一段文字。您可能需要考慮將答案的各個部分分成幾段。 –

相關問題