在与同事讨论了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:

类型名称相对较短且易于阅读(提示:通常不是泛型) 从初始化式的名称来看,类型并不明显 确切的类型对于理解代码/算法非常重要 在类层次结构上,当一个人不能很容易地知道正在使用层次结构的哪个级别时

最后,我永远不会使用var的本机值类型或相应的可空<>类型(int,十进制,字符串,十进制?,……)。这里有一个隐含的假设,如果你使用var,一定有一个“原因”。

这些都是指导方针。你还应该考虑你同事的经验和技能,算法的复杂性,变量的寿命/范围,等等。

大多数时候,没有完美的正确答案。或者,这并不重要。

[编辑:删除重复的子弹]

其他回答

我认为var的使用应该与明智选择的变量名称相结合。

我在foreach语句中使用var没有问题,前提是它不是这样的:

foreach (var c in list) { ... }

如果是这样的话:

foreach (var customer in list) { ... }

... 这样,阅读代码的人就更有可能理解什么是“列表”。如果您可以控制列表变量本身的名称,那就更好了。

这同样适用于其他情况。这是非常无用的:

var x = SaveFoo(foo);

... 但这是有道理的:

var saveSucceeded = SaveFoo(foo);

各有各的,我想。我发现自己这样做,简直是疯了:

var f = (float)3;

我需要一个12步的var程序。我叫Matt,我(ab)使用var。

在我们的办公室,我们的CTO已经明确禁止使用var关键字,原因与您所陈述的相同。

我个人认为var的使用只在new对象声明中有效,因为对象的类型在语句本身就很明显。

对于LINQ查询,您可以将结果解析为:

IEnumerable<TypeReturnedBySelectObject>

您可以让编译器(以及接下来维护代码的人员)从初始化式赋值的右边推断类型。如果这种推断是可能的,编译器可以这样做,从而节省了您的一些输入。

如果这个推断对那个可怜的家伙来说很容易,那么你没有伤害到任何东西。如果推断很难,那么作为一般规则,您已经使代码更难维护 我不会这么做的。

Lastly, if you intended the type to be something particular, and your initializer expression actually has a different type, using var means it will be harder for you to find the induced bug. By explicitly telling the compiler what you intend the type to be, when the type isn't that, you would get an immediate diagnostic. By sluffing on the type declaration and using "var", you won't get an error on the initialization; instead, you'll get a type error in some expression that uses the identifier assigned by the var expression, and it will be harder to understand why.

寓意是,要谨慎使用var;您通常不会给您自己或您的下游维护人员带来很多好处。并希望他的理由是一样的,这样你就不会因为他认为使用var很容易而猜测他的意图。在编写一个具有较长生命周期的系统时,优化输入量是一个错误。

我发现使用var关键字实际上使代码更具可读性,因为你只是习惯于跳过'var'关键字。当您真的不关心具体类型是什么时,您不需要一直向下滚动来弄清楚代码在做什么。如果我真的需要知道下面的“item”是什么类型,我只需将鼠标悬停在它上面,Visual Studio就会告诉我。换句话说,我更愿意读书

foreach( var item in list ) { DoWork( item ); }

一遍又一遍地

foreach( KeyValuePair<string, double> entry in list ) { DoWork( Item ); }

当我试图消化代码时。我认为这在某种程度上可以归结为个人喜好。在这一点上,我将依赖常识——在重要的方面(安全性、数据库使用、日志记录等)保留强制标准。

-工业。

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

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

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

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