2013-07-07 35 views
4

我知道一個using塊可以確保IDisposable被「使用」的對象將被放置在該塊的末尾 - 但是保證該對象在此之前不會被處置嗎?使用塊是否保證該對象不會被丟棄,直到塊結束?

換句話說,如果我有:

using (new DisposableObject()) { 
    // blah blah 
} 

我可以肯定的是,DisposableObject不會被佈置直到塊結束,或者可能會在垃圾收集器檢測到我有沒有它的控制器在塊內,並立即處置它?

回答

4

您的對象只會被放置一次,在使用塊結束之前不會GC'd。

規範保證了當你有using (expression) statement和表達式的類型是可空類型(稱之爲ResourceType),那麼它擴展成:

{ 
    ResourceType resource = expression; 
    try { 
     statement; 
    } 
    finally { 
     if (resource != null) ((IDisposable)resource).Dispose(); 
    } 
} 

Dispose將在塊的末尾被調用一次並有一個本地生成的,保持對你的一次性對象的引用。本地防止在使用塊結束之前對象被GC'd。

+0

+1這是最明確的解釋,值得回答。謝謝! –

6

不,它不。沒有什麼從做阻止你:

using(var myObject = new DisposableObject()) 
{ 
    myObject.Dispose(); 
} 

究竟會在這種情況下發生取決於DisposableObject語義。它可能會拋出一個異常,或者可能對被調用兩次的Dispose非常滿意。

應該指出,對象處置和垃圾收集是完全不同的概念。僅僅因爲物體被丟棄並不意味着它會被垃圾收集,而只是因爲物體被垃圾收集並不意味着它會被丟棄。

一旦對象的所有引用被銷燬或無法訪問,對象就可能被垃圾回收。代碼在using -block內運行時不會發生這種情況,因爲塊本身具有對該對象的引用。

+0

我想你錯過了這個問題的關鍵。問題在於如果GC在使用塊結束之前調用終結器。 – CodesInChaos

+0

+1感謝您對垃圾收集和物體處理進行區分,這在我之前並不清楚。因此,重新翻譯我的問題:在我的問題的代碼中,我可以依賴'DisposableObject'在'using'塊的末尾之前不被*處理嗎? –

+0

@Shaul沒有辦法保證在使用塊結束之前不會放置變量myObject。在所有引用無法訪問之後,該對象可能會被釋放,但是當您在使用塊中時,不會發生這種情況,因爲您在那裏有一個引用。 –

2

我認爲你寧願想知道垃圾收集而不是處置。

垃圾收集器不會收集using塊內的對象。即使你專門調用Dispose方法,仍然有一個積極的參考,所以它不會被收集。

using塊生成的代碼以檢查對象是否可以丟棄結束,以便在using塊中使用該對象以保持活動狀態。

相關問題