【问题标题】:Is there any technical reason to use or not to use var in C# when the type is known?当类型已知时,是否有任何技术理由在 C# 中使用或不使用 var?
【发布时间】:2009-12-15 09:07:18
【问题描述】:

看来我阅读的C#代码越来越多使用var类型标识符:

foreach (var itemChange in ItemChanges)
{
   //... 
}

而不是明确说明类型:

foreach (ItemChange itemChange in ItemChanges)
{
   //... 
}

即使类型已知。

我仍在使用 latter 显式版本,只是因为我认为稍后阅读它的人会比使用 var 更快地理解变量的类型。

但是是否有任何技术理由使用其中一种?

【问题讨论】:

标签: c# conventions var


【解决方案1】:

没有技术原因。如果在编译时无法推断类型,则代码将无法编译。

您说得对,在某些情况下使用显式类型来提高可读性可能会更好,例如

var obj = SomeMethod(); // what's the type? you'd have to inspect SomeMethod()
SomeClass obj = SomeMethod(); // the type is obvious

但在其他情况下使用 var 非常有意义,例如

var obj = new SomeClass(); // the type is obvious
SomeClass obj = new SomeClass(); // the duplication of type is unnecessary

【讨论】:

  • 但是(a)这只是证明SomeMethod 的名字很糟糕,而不是类型信息有用,以及(b)你为什么还要关心具体类型呢?我看到很多关于var 辩论的答案,它们假设具体类型信息有助于可读性,但没有引用任何证据。动态和函数式语言的用户往往会强烈反对内联类型信息是一件好事的断言。
  • 我知道您来自哪里,但是 a) 您可能无法控制 SomeMethod 的名称 b) 我并不特别在意,这只是一个可读性问题,有些人可能更愿意在阅读后续代码时能够知道变量的类型 c) “动态和函数式语言的用户” - 很公平。我也做了一些 IronPython 编码,我可以理解这个上下文。但是,这是一个 C# 问题
【解决方案2】:

不,只是可读性。

【讨论】:

  • 我喜欢这个答案。简短而甜蜜。
【解决方案3】:

一般没有技术原因。可读性——无论是哪个方向——是唯一真正的因素。

不过,有一点需要注意的是var 会推断出变量的static 类型。如果您想要子类或超类类型,则需要自己进行转换。在foreach 的情况下,就像在您的示例中一样,您通常可以通过使用子类类型声明循环变量来“免费”为您执行向下转换。

典型的例子是遍历一个 XML NodeList,你知道XmlElement 的列表,但Nodelist 被键入为XmlNodes 的集合。当然,您可以使用强制转换或 as 来取回您想要的类型,但这似乎违背了使用类型推断的目的 :-)

当然,只要您尝试使用仅对XmlElement 可用的节点成员,编译器就会通知您这一点 - 所以这仍然不是严格意义上的技术差异。


另一件有点烦人的事情是,如果你使用像 Resharper 这样的工具,它会非常激进地建议你在所有可能的情况下使用var。当它建议您将 int 声明更改为 var 时,尤其令人讨厌!

但是,除非您关闭该功能,否则您使用 var 的次数越多,来自 Resharper 的“噪音”就越少。

【讨论】:

    【解决方案4】:

    我知道的唯一技术原因是您可以在没有var 的情况下执行隐式转换,例如

    int i = 5;
    double a = i; // implicit cast with explicit types
    

    但在这里我更喜欢var,因为它使演员表明确;虽然我不太关心我在执行表示更改类型转换时关心的类型:

    var a = (double)i; // explicit cast with implicit types
    

    但实际上,正如您所说,一般原因是可读性。您需要问自己的问题是,为什么您认为确切的具体类型对可读性很重要?你是否总是编写 Linq 查询来调用具体类型,例如

    from ItemChange itemChange in ItemChanges
    
    // instead of
    
    from itemChange in ItemChanges
    

    同样,你是否总是调用泛型方法的类型参数而不是使用类型推断,例如

    ItemChanges.Select<ItemChange, ItemChange>((ItemChange itemChange) => ...);
    
    // instead of
    
    ItemChanges.Select(itemChange => ...);
    

    或者您是否乐意让编译器为您做一些工作并让它计算出类型,而代价是没有明确说明类型信息?

    如果您对 linq 和泛型方法中的类型推断感到满意,那么您已经决定可以不用在任何地方明确说明类型,并且您可能还没有发现您的代码是结果是可读性降低(事实上,您可能发现完全相反)。因此,使用var 只是在您已经走的同一条道路上又迈出了一步。

    【讨论】:

    • 显式转换在某些情况下可能很重要,例如,如果集合的枚举器返回“对象”而不是确切的类型。我认为 SPListItemCollection 就是这样一个例子,但我认为这适用于所有非通用集合。
    • @Michael - 同意。我应该更清楚表示改变和表示保留转换之间的区别(我更喜欢用转换运算符明确说明的是表示改变的转换)。是的,我认为使用类型名称比强制类型转换更清晰。
    【解决方案5】:

    var 是一个 C# 3.0 特性,仅在匿名类型中是必需的

    因为下面的代码

    var v = new { Amount = 108, Message = "Hello" };
    

    动态创建一个新的匿名类型,var 使用是强制性的。例如,var 在通常动态创建类型的 Linq 中特别有用。

    在任何其他情况下,这只是最终应用程序的喜好问题(在编译期间已解决)。但对于代码阅读器,我认为 'var' 提供的信息比类型本身少。

    【讨论】:

    • 有时我认为应该有类似anon 关键字的东西,而不是var
    【解决方案6】:

    没有。在提高可读性的地方使用var,反之亦然。

    【讨论】:

      【解决方案7】:

      var 是 C# 3.x+ 的一个特性,不是吗?如果不使用它,您的代码也与其他版本更兼容。

      当您搜索“var C#”时,SO 中有很多有趣的问题

      【讨论】:

      • 它实际上是一个 C# 3 功能,但如果您的目标是 .Net 2.0,它仍然可以正常工作
      • 嗯,var 是在 .Net 2.0 中作为编译器技巧实现的,我们偶尔会在 .Net2.0 应用程序中使用它。
      【解决方案8】:

      除了匿名类型之外,在程序的任何给定状态下都没有使用 var 的技术原因。

      但是,使用 var 可以让程序在您无需编辑的情况下进行更改。给定

      public int SomeMethod(){}
      public List<T> SomeOtherMethod<T>(T parameter);
      

      然后

      var x = SomeMethod();
      var y = SomeOtherMethod(x);
      

      会起作用(y 将是List&lt;int&gt;)。如果你用过

      int x = SomeMethod();
      List<int> y = SomeOtherMethod(x);
      

      那么如果将SomeMethod() 更改为返回long,那么您就必须更改y 的定义。

      我已经看到这种事情在整个程序中传播,需要进行数百次更改。特殊情况是更改数据访问代码以返回 ReadOnlyCollection&lt;T&gt; 而不是 List&lt;T&gt;。需要进行大量代码更改,我将所有明确提及 List&lt;T&gt; 的内容都更改为 var,并且再也不需要更改代码了。

      【讨论】:

        猜你喜欢
        • 2011-07-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多