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


当前回答

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

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

因此,

var something = SomeMethod();

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

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

其他回答

使用var而不是显式类型使重构更容易(因此我必须反驳前面的帖子,他们的意思是它没有区别,或者它纯粹是“语法糖”)。

您可以更改方法的返回类型,而无需更改调用此方法的每个文件。想象一下

...
List<MyClass> SomeMethod() { ... }
...

就像这样

...
IList<MyClass> list = obj.SomeMethod();
foreach (MyClass c in list)
  System.Console.WriteLine(c.ToString());
...

如果您希望重构SomeMethod()以返回IEnumerable<MySecondClass>,则必须在使用该方法的每个地方更改变量声明(也在foreach中)。

如果你写

...
var list = obj.SomeMethod();
foreach (var element in list)
  System.Console.WriteLine(element.ToString());
...

相反,你不需要改变它。

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

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

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可以节省时间的狂热爱好者来说,它可以减少敲击键盘的次数:

StringBuilder sb = new StringBuilder();

than

var sb = new StringBuilder();

如果你不相信,你可以数数……

19对21

如果有必要我会解释的,但你试试吧……(取决于你的智能感知的当前状态,你可能需要为每一个输入更多)

你能想到的每一种类型都是如此!!

我个人的感觉是,除非在不知道类型的情况下,否则永远不应该使用var,因为它降低了代码中的识别可读性。大脑识别字体的时间比识别一整行字体要长。那些懂机器码和比特的老家伙知道我在说什么。大脑是并行处理的,当你使用var时,你强迫它序列化它的输入。为什么会有人想让自己的大脑更努力地工作呢?这就是电脑的作用。

第一。

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

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

在做了十年的Java专业人员之后,我在c#世界里还是个新手。我最初的想法是“哦,不!这就把类型安全丢进了下水道”。然而,我对var了解得越多,我就越喜欢它。

1) Var与显式声明的类型一样是类型安全的。这都是关于编译时语法糖。

2)遵循DRY原则(不要重复)。DRY是关于避免冗余的,在两边都命名类型肯定是冗余的。避免冗余就是要让你的代码更容易修改。

3)至于确切的型号……嗯. .我认为你应该有一个大致的概念你有一个整数,一个套接字,一些UI控件,等等。智能感知将从这里引导你。知道确切的类型通常并不重要。例:我认为99%的情况下你并不关心给定的变量是long还是int, float还是double。对于最后1%的情况,在真正重要的地方,只需将鼠标指针悬停在var关键字上方。

4)我曾看到过这样一种荒谬的观点:现在我们需要回到1980年风格的匈牙利疣,才能区分变量类型。毕竟,在蒂莫西·道尔顿(Timothy Dalton)扮演詹姆斯·邦德(James Bond)的时代,这是判断变量类型的唯一方法。但现在是2010年。我们已经学会了根据变量的用法和内容来命名变量,并让IDE指导我们确定它们的类型。只要继续这样做,var就不会伤害你。

总而言之,var不是什么大东西,但它确实是一个很好的东西,而且它是Java最好很快复制的东西。所有反对的观点似乎都是基于ide之前的谬误。我会毫不犹豫地使用它,我很高兴R#帮助我做到这一点。