2012-07-12 63 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产生影响,并且它仍将包含值。