在与同事讨论了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而不是显式类型使重构更容易(因此我必须反驳前面的帖子,他们的意思是它没有区别,或者它纯粹是“语法糖”)。
您可以更改方法的返回类型,而无需更改调用此方法的每个文件。想象一下
...
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());
...
相反,你不需要改变它。
好吧,这个问题会一直固执己见,但我会试着给出我的观点-尽管我认为我的观点是如此混乱,你可能不会从中得到什么。
首先——有匿名类型,为此你需要使用“var”关键字来分配一个匿名类型作为类的对象——这里没有太多的讨论,“var”是必要的。
然而,对于更简单的类型,如int型、长型、字符串型等等,我倾向于输入适当的类型。主要是因为它有点像“懒人的工具”,我在这里看不到太多的好处,很少的按键和它可能带来的困惑,这是不值得的。特别是浮点数的各种类型(浮点数、双精度数、十进制数)使我感到困惑,因为我对字面量中的后缀不坚定——我喜欢在源代码中看到类型。
话虽如此,如果类型更复杂和/或它显式地重复在赋值的右侧,我倾向于大量使用var。这可以是一个List<string>或etc,例如:
var list = new List<string>();
在这种情况下,我认为没有必要重复类型两次——特别是当您开始更改代码和类型更改时——泛型类型可能会变得越来越复杂,因此必须更改它们两次只是一种痛苦。当然,如果你希望针对IList<string>编码,那么你必须显式地命名类型。
简而言之,我做了以下事情:
当类型很短或不能脱离上下文读取时,显式地命名类型
在必要时使用var(废话)
当var(在我看来)不影响可读性时,使用它来偷懒