【问题标题】:C# List and MemoryC# 列表和内存
【发布时间】:2017-06-27 23:04:21
【问题描述】:

我是 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]...这是正确的吗?

【问题讨论】:

    标签: c# memory


    【解决方案1】:

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

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

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

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

      是的,他们是。

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

    【讨论】:

    • 内存保留是我最关心的问题,因为 list1 真的很大。我想我需要克隆 list2 中的对象,以确保垃圾收集器不再引用和删除 list1。
    • @Chris:不,您不必克隆对象。只要您的对象是字符串,它们就根本不可克隆。在引擎盖下,它们仍将指向同一个对象。除此之外,克隆对象不会以任何方式影响垃圾收集器。不要考虑记忆。 GC 知道什么时候应该清理它。我建议您阅读其他答案中已经提到的一些垃圾收集器 HowTos。
    【解决方案2】:

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

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

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

    【讨论】:

    • 但您可以致电 GC.Collect msdn.microsoft.com/en-us/library/xe0c2357.aspx。它可能会回收内存。
    • @AmiramKorach - 可能。可能不会。直接调用它是不好的做法。无论如何,这不是问题所要问的。
    • @AmiramKorach:是的,但是告诉刚刚学习 C# 的人“你可以像这样收集内存”并不是一个好主意。他们缺乏经验会导致严重的虐待。好的建议不仅在于说了什么,还在于未说的内容。
    • 同意。在大多数情况下,调用 GC.Collect 的理由很少。克里斯,如果事实上你甚至不需要关心将你的列表实例设置为空,因为一旦它超出范围并且不再使用,它​​将可用于垃圾收集,这将释放该内存一次它需要。
    • @Chris GC 会照顾你的记忆。当 GC 认为清理有意义时,它会进行清理。
    【解决方案3】:

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

    来自 MSDN:

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

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

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

    【讨论】:

      【解决方案4】:

      你必须考虑不同的问题:

      【讨论】:

        【解决方案5】:

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

        有关详细信息,请参阅Fundamentals of Garbage Collection。 ( 垃圾回收的条件 )

        【讨论】:

          【解决方案6】:

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

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

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

          你可以阅读更多关于here

          【讨论】:

            【解决方案7】:

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

            但是如果你使用

            List<string> list2 = list1;
            

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

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

            【讨论】:

              猜你喜欢
              • 2013-06-10
              • 2020-09-22
              • 2020-07-17
              • 1970-01-01
              • 2013-04-18
              • 2021-08-19
              • 2014-10-03
              • 2012-07-03
              • 1970-01-01
              相关资源
              最近更新 更多