在与同事讨论了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确实保持强类型,但问题是,在定义中不立即显示类型是否危险,当重载意味着当你无意中将错误的类型传递给方法时,编译器可能不会发出错误,这种情况会被放大。


当前回答

我想你在你的问题中指出了var的主要问题:“我不需要弄清楚类型”。正如其他人指出的那样,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时,在这种情况下您应该使用强制转换。)

来自c#团队的高级软件设计工程师Eric Lippert:

为什么引入var关键字?

There are two reasons, one which exists today, one which will crop up in 3.0. The first reason is that this code is incredibly ugly because of all the redundancy: Dictionary<string, List<int>> mylists = new Dictionary<string, List<int>>(); And that's a simple example – I've written worse. Any time you're forced to type exactly the same thing twice, that's a redundancy that we can remove. Much nicer to write var mylists = new Dictionary<string,List<int>>(); and let the compiler figure out what the type is based on the assignment. Second, C# 3.0 introduces anonymous types. Since anonymous types by definition have no names, you need to be able to infer the type of the variable from the initializing expression if its type is anonymous.

我特别强调。整篇文章,c# 3.0仍然是静态类型的,真的!,以及随后的系列相当不错。

这就是var的作用。其他用途可能就没这么好用了。任何与JScript、VBScript或动态类型的比较都是胡扯。再次注意,var是为了使某些其他特性在. net中工作而必需的。

我们采用了“为人编写代码,而不是为机器编写代码”的理念,基于这样的假设:在维护模式中花费的时间要比在新的开发模式中花费的时间长好几倍。

对我来说,这就排除了编译器“知道”变量是什么类型的说法——当然,你不可能第一次就写出无效的代码,因为编译器会阻止你的代码编译,但是当下一个开发人员在6个月的时间里阅读代码时,他们需要能够推断出变量做得正确或不正确的地方,并快速确定问题的原因。

因此,

var something = SomeMethod();

在我们的编码标准中是不合法的,但在我们的团队中鼓励这样做,因为它增加了可读性:

var list = new List<KeyValuePair<string, double>>();
FillList( list );
foreach( var item in list ) {
   DoWork( item ); 
}

不要这样做,这会让你的代码难以阅读。

总是使用尽可能严格的输入,拐杖只会让你的生活地狱。

在我看来,大量使用var是没有问题的。它本身不是一个类型(您仍然在使用静态类型)。相反,这只是一个节省时间的方法,让编译器自己判断要做什么。

像任何其他节省时间的方法(例如自动属性)一样,在到处使用它之前,最好先了解它是什么以及它是如何工作的。