【问题标题】:What will happen to a var type when code block ends?当代码块结束时,var 类型会发生什么?
【发布时间】:2011-07-12 08:47:27
【问题描述】:

这两个代码示例有什么区别?

  public Test(int x)
  {
        List<int> list= new List<int>();
        List<int> list1 = new List<int>();

        list= CreateList(x);
        list1 = CreateList(x + 1);

        DoStuff(list, list1);

        list.Clear();
        list = null;
        list1.Clear();
        list1 = null;
    } 

这是编码的方式吗?

    public Test(int nCount)
    {
        var list = CreateList(nCount);
        var list1 = CreateList(nCount + 1);

        DoStuff(list, list1);
    }

【问题讨论】:

  • 您避免在两个场合输入List&lt;int&gt;
  • 在第一个示例中,我清除列表并通过将元素设置为 null 来处理这些元素。使用 var 类型,我不再需要这样做了吗?
  • 没有必要将其设置为null,这不叫处置..Read further

标签: c# .net memory-management codeblocks var


【解决方案1】:

您实际上并没有将like 与like 进行比较,因为所有var 的意思是“让编译器决定这是什么类型”。它将编译为相同的代码(假设CreateList 返回List&lt;int&gt;)。因此,虽然您的代码在功能上相同,但您在第一个示例中做了额外的工作,而在第二个示例中没有复制。

在第一种情况下,您创建了不必要的列表,因为从CreateList(x) 返回列表的行为将覆盖您刚刚创建的内容。一个更准确的问题是询问以下之间的区别:

public Test(int x)
{
    List<int> list= CreateList(x);
    List<int> list1 = CreateList(x + 1);

    DoStuff(list, list1);

    list.Clear();
    list = null;
    list1.Clear();
    list1 = null;
}

public Test(int nCount)
{
    var list = CreateList(nCount);
    var list1 = CreateList(nCount + 1);

    DoStuff(list, list1);
}

在这两种情况下,由于列表超出范围,它们将被标记为符合垃圾回收条件。您不需要调用Clear() 或将变量设置为null

【讨论】:

    【解决方案2】:

    什么都没有。

    出于可读性和未来维护的原因,请使用第二个。它显然更容易理解,并且由于 C# 和 CLR 的设计,您的第一个示例中的大部分代码都不需要。

    我会尽力解释我的意思。您不需要清除或设置对局部变量的任何引用(垃圾收集器将为您执行此操作)。您只需要对类级别的字段执行此操作,而且通常甚至不需要(同样,当您的类超出范围时,垃圾收集器会收集它们)。

    考虑更多地关注对象disposable 的概念,不要担心内存使用/垃圾收集方面。清空列表或将列表的引用设置为 null 实际上不会回收内存;内存仍然被分配,直到垃圾收集器在未来某个不确定的时间回收它。

    有一些方法可以强制进行垃圾回收,但通常这意味着如果你需要走那么远,你就做错了。有人会说,如果您需要非常详细地担心内存问题,那么 .NET 可能不是您的问题领域的正确语言选择。

    另外,使用var 或明确指定类型没有任何区别。

    【讨论】:

    • 在第一个例子中,是否需要清除列表并将其设置为空?
    • 一点也不,不。请参阅我的答案以获得更详细的解释,但如果您的列表是类上的字段而不是方法级别的局部变量,并且您担心其中的值被意外重用或用于另一种共享字段的方法。无论如何,这通常是一个错误,所以我只是为了完整性而提及它。
    【解决方案3】:

    唯一值得一提的区别是,当您手动清除列表时,您会在此时释放对对象的引用。在另一个版本中,列表将在垃圾收集器处理它的过程中清除引用,这可能随时发生。

    这是一个微小的区别,因为释放的引用只会在 GC 收集时自行处理。

    【讨论】:

      【解决方案4】:

      这取决于你用“DoStuff”做什么。如果您创建对列表的另一个引用,则垃圾收集器不会在第二个示例中清除它们。所以第一个例子保证列表被清除,第二个例子依赖于“DoStuff”。

      我会使用以下代码:

      DoStuff(CreateList(nCount), CreateList(nCount + 1));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-25
        • 1970-01-01
        • 1970-01-01
        • 2011-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-07
        相关资源
        最近更新 更多