代码块结束时var类型会发生什么?

时间:2011-07-12 08:47:28

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

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

  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);
    }

4 个答案:

答案 0 :(得分:3)

你实际上并没有比较像是喜欢所有var意味着“让编译器决定它是什么类型”。它将编译为相同的代码(假设CreateList返回List<int>)。因此,虽然您的代码在功能上完全相同,但您在第一个示例中正在执行额外的工作,而您在第二个示例中没有复制。

在第一种情况下,您不必要地创建列表,因为从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

答案 1 :(得分:2)

没有

为了便于阅读以及将来的维护原因,请使用第二个。它显然更容易理解,并且由于C#和CLR的设计,第一个示例中的大部分代码都不是必需的。

我会试着解释一下我的意思。您不需要清除或设置为null对本地变量的任何引用(垃圾收集器将为您执行此操作)。您只需要为类级别字段执行此操作,并且通常不会这样做(同样,当您的类超出范围时,垃圾收集器将收集它们。)

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

有办法强制垃圾收集,但通常这意味着如果你需要走得那么远,你做错了什么。有人会说如果你需要担心内存如此详细,那么.NET可能不是你问题领域的正确语言选择。

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

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

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

我会使用以下代码:

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