2009-02-13 26 views
6

在下面的c#代碼中,當它不再有用時,我該如何擺脫這些對象?它會自動處理嗎,還是我需要做點什麼?如何擺脫c中的對象#

public void Test() 
{ 
    object MyObject = new object(); 

    ... code ... 
} 
+0

對不起編輯,我只是​​試圖在無意中開始之前制止麻煩 - 沒有任何意圖。 – 2009-02-13 02:03:38

+0

大聲笑,我*所以*想要有人告訴我如何刪除*特定*變量... – 2009-02-13 02:05:33

+0

@lc當然,沒有采取任何進攻:-) – 2009-02-13 02:06:17

回答

5

簡短的回答是:除非它有非託管資源(文件句柄等),你不必擔心。

漫長的答案有一點涉及。

當.NET決定釋放一些內存時,它運行垃圾回收器。這將查找所有仍在使用的對象,並將它們標記爲這樣。與靜態變量一樣,任何可能仍被讀取的局部變量(在任何線程的任何棧幀中)都被視爲。(事實上​​,我相信靜態變量是通過實時類型對象引用的,它們通過實時AppDomain對象引用,但大多數情況下,您可以將靜態變量視爲根。)

垃圾回收器查看每個引用的對象由一個根,然後根據這些對象內的實例變量找到更多的「實時」引用。它遞歸下來,發現並將越來越多的對象標記爲「現場」。一旦它完成了這個過程,它就可以查看對象的所有其餘的並釋放它們。

這是一個非常廣泛的概念圖片 - 但是當你認爲垃圾收集,終結,併發收集等的模型我強烈建議你讀它得到了很多更詳細的傑夫·裏希特的CLR via C#其進入該在很多細節。如果你不想購買這本書,他也有一個twopart文章(從2000年開始,但仍然非常相關)。

當然,這並不意味着您不需要擔心.NET中的內存使用情況和對象生命週期。特別是:

  • 創建對象毫無意義性價比。特別是垃圾收集器速度快,但不是免費的。尋找簡單方法來減少你的內存使用情況,但你知道你有問題之前的微優化也是不好的。
  • 通過讓對象可達到比預期更長的時間來「泄漏」內存是可能的。兩個合理的常見原因是靜態變量和事件訂閱。 (事件訂閱使得事件處理程序可以從事件發佈者到達,但不是相反的方式。)
  • 如果您使用的內存(以實時,可訪問的方式)比可用的更多,則您的應用程序將崩潰。 .NET沒有太多可以做到這一點!
  • 使用非內存資源的對象通常實現IDisposable。你應該調用Dispose來釋放這些資源,當你完成對象。請注意,這個不是釋放對象本身 - 只有垃圾收集器可以做到這一點。在C#中的using聲明是可靠地調用Dispose的最方便的方式,即使在例外情況下也是如此。
18

自動。當MyObject超出範圍時(在Test結束時),它被標記爲垃圾收集。在未來的某個時刻,.NET運行時會清理的內存,你

編輯: (我應該指出的完整性的考慮,如果你通過MyObject的地方,它就會按引用傳遞,而且會不是垃圾收集 - 只有當沒有更多的對象引用浮動時,GC可以自由收集它)

編輯:在發佈版本中,MyObject通常會在未使用時收集(請參閱我的回答更多細節-dp)

3

在經過優化的代碼中,有可能並有可能在方法結束之前收集MyObject。默認情況下,Visual Studio中的調試配置將在調試開關打開並且優化關閉的情況下生成,這意味着MyObject將保留在方法的末尾(以便您可以在調試時查看該值)。優化關閉構建(在這種情況下調試無關緊要)允許MyObject在確定未被使用後收集。一種強制方法結束時保持活力的方法是在方法結尾調用GC.KeepAlive(MyObject)。

4

其他答案是正確的,除非你的對象是一個實現了接口的類的實例,在這種情況下,你應該(明確地或暗示地通過using語句)調用對象的Dispose方法。

1

通常垃圾收集可以依靠清理,但是如果你的對象包含任何非託管資源(數據庫連接,打開文件等),你將需要顯式關閉這些資源和/或優化對象上的dispose方法(if它實現了IDisposable)。這可能會導致錯誤,所以您需要小心如何處理這些類型的對象。在使用它之後簡單地關閉文件並不總是足夠的,因爲在執行關閉之前的異常會使文件處於打開狀態。可以使用using塊或try-finally塊。

底線:「使用」是你的朋友。

2

這將強制垃圾收集器擺脫未使用的對象。

GC.Collect(); 
GC.WaitForPendingFinalizers(); 

如果您想要收集特定的對象。

object A = new Object(); 
... 
A = null; 
GC.collect(); 
GC.WaitForPendingFinalizers();