在与同事讨论了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的所有地方,唯一有问题的地方对我来说是内部短类型,例如,我更喜欢int I = 3;除以var I = 3;

其他回答

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

在边缘情况下肯定会有分歧,但我可以告诉你我的个人指导方针。

当我决定使用var时,我看看这些标准:

变量的类型(对人来说)从上下文是很明显的 变量的确切类型(对人类来说)并不是特别相关。 [例如,你可以弄清楚算法在做什么,而不用关心你使用的是哪种容器] 类型名非常长,会影响代码的可读性(提示:通常是泛型)

相反,这些情况会促使我不使用var:

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

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

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

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

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

@Keith -

在你们的比较中 IEnumerable < int > IEnumerable<double>你不需要 担心——如果你传递了错误的类型 您的代码无论如何都无法编译。

这并不完全正确——如果一个方法同时重载到IEnumerable<int>和IEnumerable<double>,那么它可能会无声地将意外推断的类型(由于程序中的其他一些更改)传递给错误的重载,从而导致不正确的行为。

我想问题是这种情况出现的可能性有多大!

我猜部分问题是var给给定的声明增加了多少混乱——如果不清楚某个东西是什么类型(尽管它是强类型的,编译器完全理解它是什么类型),有人可能会掩盖一个类型安全错误,或者至少需要更长的时间来理解一段代码。

有人不喜欢批评var..所有答案downmodded..哦. .

@Jon Limjap: 我知道。:)我的意思是可读性被降级了,就像在VB6一样。我不喜欢依靠智能感知来确定给定变量的类型。我希望能单独用源代码求出它。

命名惯例也没用——我已经用好名字了。我们要回到前缀时代吗?

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

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

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

IEnumerable<TypeReturnedBySelectObject>