3

我是 C# 的新手,想知道 list1 在 list1 = null 之后是否真的从内存中删除了;

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;

此代码仅用于文档,在我的真实案例中 list1 对象非常大,我需要将其从内存中删除,并且仅使用 list2 继续,它是原始 list1 的一小部分。

我假设 list1[0] 和 list2[0] 引用内存中的同一个对象,直到我用新值更新 list2[0] ......这是正确的吗?

4

7 回答 7

4

有几个问题。让我试着分别回答他们:

  1. 当对 list1 的引用设置为 null 时,是否会从内存中删除 list1?

    不,当垃圾收集器下次清理堆时,列表会从内存中删除。何时进行清理取决于垃圾收集器。

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

    对,他们是。

所以总而言之,这意味着您不必处理内存管理。这是由垃圾收集器完成的。垃圾收集器足够聪明,知道何时必须收集孤立对象。所以不要试图比GC做得更好。几乎在每一种情况下,情况都会变得更糟。

于 2012-07-12T09:12:25.343 回答
2

您必须考虑不同的问题:

于 2012-07-12T09:15:59.123 回答
2

C# 不是 C/C++ - 没有直接的内存管理。

列表对象将不再可访问(假设这是使用它的所有代码),因此将无法从对象根访问。这将允许 GC 将其标记为收集。

一旦 GC 收集,内存将被回收。

于 2012-07-12T09:08:22.720 回答
2

无法保证该列表将被删除。当您分配 null 时,它有资格进行垃圾收集,并且每当调用 GC 时,它都会收集它。

来自 MSDN:

一旦对象符合销毁条件,则在稍后的某个未指定的时间运行对象的析构函数(如果有)。除非被显式调用覆盖,否则对象的析构函数只运行一次。

一旦对象的析构函数运行,如果该对象或其任何部分不能被任何可能的继续执行访问,包括析构函数的运行,则该对象被视为不可访问并且该对象有资格被收集。

最后,在对象符合收集条件后的某个时间,垃圾收集器会释放与该对象关联的内存。

于 2012-07-12T09:09:48.053 回答
1

当垃圾回收发生时,它的内存将被回收。

有关详细信息,请参阅垃圾收集基础。(垃圾回收的条件)

于 2012-07-12T09:11:42.587 回答
1

保持对 null 的引用不会删除内存,但最终会被垃圾收集。

GC 神话:将对象的引用设置为 null 将强制 GC 立即收集它。

GC 真相:将对象的引用设置为 null 有时会允许 GC 更快地收集它。

你可以在这里阅读更多

于 2012-07-12T09:17:31.053 回答
0

在您的代码中, list1 和 list2 指向不同的位置。
只需更改该list1[1] = "Something different"行之前的值list1 = null并在即时窗口中检查该值list2[1]仍将保持“狐狸”。

但是,如果您使用

List<string> list2 = list1;

那么 list2[1] 将是“不同的东西”。

注意:在这两种情况下,使list1 = null不会对 list2 产生影响,它仍然会包含值。

于 2012-07-12T10:12:44.710 回答