在与同事讨论了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时,它会增加不一致性。

另一个值得关注的情况是,在下面的调用中,你不能仅通过查看CallMe返回的代码来判断类型:

var variable = CallMe();

这是我对var的主要抱怨。

当我在方法中声明匿名委托时,我使用var,在某种程度上var看起来比我使用Func更干净。考虑下面的代码:

var callback = new Func<IntPtr, bool>(delegate(IntPtr hWnd) {
   ...
});

编辑:根据Julian的输入更新最后一个代码样例

其他回答

当然,int很简单,但当变量的类型是IEnumerable<MyStupidLongNamedGenericClass<int, string>>时,var会让事情变得更简单。

它当然可以让事情变得更简单,从我昨天写的代码来看:

var content  = new Queue<Pair<Regex, Func<string, bool>>>();
...
foreach (var entry in content) { ... }

如果没有var,这将是非常冗长的。

附录:花点时间学习具有真正类型推断的语言(例如f#),就会发现编译器在正确获取表达式类型方面是多么出色。这当然意味着我倾向于尽可能多地使用var,现在使用显式类型表明变量不是初始化表达式的类型。

我分裂var的所有地方,唯一有问题的地方对我来说是内部短类型,例如,我更喜欢int I = 3;除以var I = 3;

这没有错,但可能不合适。参见所有其他回答的例子。

Var x = 5;(坏的)

var x = new SuperDooperClass();(好)

Var x = from t,单位为db。select new {Property1 = t.Field12};(更好的)

来自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时,在这种情况下您应该使用强制转换。)