2012-07-12 64 views
3

我是C#的新手,想知道list1是否真的在list1 = null之後從內存中移除;C#List and Memory

List<string> list1 = new List<string>() 
{ 
    "carrot", 
    "fox", 
    "explorer" 
}; 
List<string> list2 = new List<string>(); 
list2.Add(list1[0]); 
list2.Add(list1[1]); 
list2.Add(list1[2]); 

list1 = null; 

此代碼僅適用於文檔,在我的真實案例列表1對象是非常大的,我需要從內存中刪除它,只有用列表2,它是原始列表1的一小部分continu。

我假設list1 [0]和list2 [0]引用內存中的同一個對象,直到我用新值更新list2 [0] ...是否正確?

回答

2

C#不是C/C++ - 沒有直接的內存管理。

列表對象將不再可訪問(假設這是所有使用它的代碼),所以不能從對象根訪問。這將允許GC將其標記爲收集。

GC收集後將回收內存。

+0

但是你可以調用GC.Collect http://msdn.microsoft.com/en-us/library/xe0c2357.aspx。它可能會回收內存。 – 2012-07-12 09:09:16

+2

@AmiramKorach - 可能。它可能不會。直接調用它是不好的做法。無論如何,這不是問題所在。 – Oded 2012-07-12 09:09:57

+4

@AmiramKorach:是的,但是告訴那些現在只學習C#的人「你可以收集這樣的內存」並不是一個好主意。他們缺乏經驗會導致嚴重的虐待。好的建議不僅是關於所說的內容,還包括沒有說明的內容。 – Jon 2012-07-12 09:10:17

2

無法保證列表將被刪除。當您分配空值時,它有資格進行垃圾收集,並且每當調用GC時它都會收集它。

從MSDN:

一旦對象符合銷燬,在析構函數(如果有的話),用於將對象運行稍後某個時間。除非被顯式調用覆蓋,否則該對象的析構函數僅運行一次。

一旦運行了對象的析構函數,如果該對象或其任何部分無法通過任何可能的繼續執行(包括析構函數的運行)進行訪問,則該對象被視爲無法訪問,並且該對象變爲符合採集。

最後,在對象符合收集條件之後的某段時間,垃圾回收器釋放與該對象關聯的內存。

3

有幾個問題。讓我試着單獨回答他們:

  1. 當list1的引用設置爲null時,list1是否從內存中移除?

    不,當下次垃圾收集器正在清理堆時,列表將從內存中移除。當這種清理將發生在垃圾收集器。

  2. list1和list2是否引用相同的對象?

    是的,他們是。

所以最後這意味着你不必處理內存管理。這是由垃圾收集器完成的。垃圾收集器足夠聰明,知道何時收集孤立的對象。所以不要試圖比GC更好。在幾乎所有情況下,情況都變得更糟。

+0

記憶體保留是我最大的擔憂,因爲list1真的很大。我想我需要然後克隆list2中的對象,以確保list1不再被垃圾收集器引用和刪除。 – Chris 2012-07-12 11:01:30

+0

@Chris:不,你不需要克隆這些對象。至於你的對象是字符串,它們根本就不可複製。在引擎蓋下,他們仍然指向相同的物體。除此之外,對象不會以任何方式影響垃圾收集器。不要考慮記憶。 GC知道什麼時候應該清理。我建議你閱讀一些垃圾收集器HowTos,如其他答案中已經提到的那樣。 – PVitt 2012-07-12 12:19:50

+0

好的謝謝。需要跳過我的C/C++練習... – Chris 2012-07-12 12:51:16

1

保持爲空引用不會刪除存儲,但它最終會得到垃圾收集。

GC誤區:將對象的引用設置爲null將強制GC立即收集它。

GC真相:將對象的引用設置爲null有時會允許GC更快地收集它。

你可以閱讀更多關於here

0

在你的代碼在List1和List2都指向不同的位置。
只需在行list1 = null之前更改list1[1] = "Something different"的值,並立即檢查list2[1]的值是否仍然爲「狐狸」。

但是如果你使用

List<string> list2 = list1; 

然後列表2 [1]將是 「非常不同」。

注意:在這兩種情況下,使得list1 = null將不會對list2產生影響,並且它仍將包含值。