在与同事讨论了c# 3中var关键字的使用后,我想知道人们对通过var适当使用类型推断的看法是什么?

例如,我很懒地在有问题的情况下使用var,例如:-

foreach(var item in someList) { // ... } // Type of 'item' not clear.
var something = someObject.SomeProperty; // Type of 'something' not clear.
var something = someMethod(); // Type of 'something' not clear.

var更合法的用法如下:-

var l = new List<string>(); // Obvious what l will be.
var s = new SomeClass(); // Obvious what s will be.

有趣的是,LINQ似乎是一个灰色区域,例如:-

var results = from r in dataContext.SomeTable
              select r; // Not *entirely clear* what results will be here.

结果很明显,因为它将是一个实现IEnumerable的类型,但它并不完全明显,与var声明一个新对象的方式相同。

当涉及到对象的LINQ时,情况就更糟了,例如:-

var results = from item in someList
              where item != 3
              select item;

这并不比等价的foreach(var item in someList){//…}相当于。

这里有一个关于类型安全的真正问题——例如,如果我们将该查询的结果放在一个接受IEnumerable<int>和IEnumerable<double>的重载方法中,调用者可能会无意中传入错误的类型。

Var确实保持强类型,但问题是,在定义中不立即显示类型是否危险,当重载意味着当你无意中将错误的类型传递给方法时,编译器可能不会发出错误,这种情况会被放大。


当前回答

@aku:代码审查就是一个例子。另一个例子是重构场景。

基本上我不想用我的鼠标去打字。它可能不可用。

其他回答

埃里克的回答是……

c#中泛型类型的命名空间作用域别名

是相关的。

部分问题在于c#中没有强类型的混叠。因此许多开发人员使用var作为部分代理。

第一。

Var不是一个类型,也不是什么特殊的特性(比如c# 4.0的动态特性)。它只是一个语法糖。你要求编译器通过右边的表达式来推断类型。唯一需要的地方是匿名类型。

我不认为使用var既好又坏,这是一种编码风格。我个人不使用它,但我不介意其他团队成员使用它。

Var一点也不像变量。变量仍然是强类型的,只是你不需要按下键来得到它。您可以在Visual Studio中将鼠标悬停在它上以查看类型。如果您正在阅读打印的代码,则可能需要稍微考虑一下以确定类型是什么。但是只有一行声明了它,而有很多行使用它,所以给东西起个像样的名字仍然是让你的代码更容易理解的最好方法。

使用智能感知是懒惰吗?这比输入整个名字还少。或者有些事情不那么费力,但不值得批评?我认为有,var就是其中之一。

来自Essential LINQ:

除非绝对必要,否则最好不要显式声明范围变量的类型。例如,下面的代码编译干净,但是编译器可以在没有正式声明的情况下推断出类型:

List<string> list = new List<string> { "LINQ", "query", "adventure" };
var query = from string word in list
      where word.Contains("r")
      orderby word ascending
      select word;

显式声明range变量的类型会强制对LINQ Cast操作符进行幕后调用。此调用可能会产生意想不到的结果,并可能会损害性能。如果您在LINQ查询中遇到性能问题,像这里所示的强制转换可能是开始寻找罪魁祸首的一个地方。(此规则的一个例外是当您使用非泛型Enumerable时,在这种情况下您应该使用强制转换。)

对于LINQ,使用var的另一个很好的理由是编译器可以更优化查询。

如果你使用一个静态列表来存储结果,它将在你分配给列表的地方执行,但是使用var,它可以潜在地将原始查询与代码中后面的查询合并,从而对数据库进行更优化的查询。

我有一个例子,我在第一个查询中提取了一些数据,然后循环遍历并请求更多数据以打印出一个表。

LINQ合并了这些,所以第一个只提取id。

然后在循环中,它添加了一个我没有在那里做的额外连接来获取我包含在原始数据中的数据。

经过测试,这种方法效率更高。

如果我们没有使用var,它就会像我们写的那样进行查询。