在与同事讨论了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确实保持强类型,但问题是,在定义中不立即显示类型是否危险,当重载意味着当你无意中将错误的类型传递给方法时,编译器可能不会发出错误,这种情况会被放大。
摘自CodingHorror关于这一问题的文章:
不幸的是,你和其他人都错了。虽然我同意你的观点,冗余不是一件好事,但解决这个问题的更好方法应该是这样做:
MyObject m = new();
或者如果你传递参数:
Person p = new("FirstName", "LastName ");
在创建新对象时,编译器从左边推断类型,而不是右边。这比“var”有其他优点,因为它也可以在字段声明中使用(还有其他一些领域,它也可能有用,但我不会在这里讨论)。
最后,这并不是为了减少冗余。不要误解我,“var”在c#中对于匿名类型/投影是非常重要的,但是这里的使用是非常错误的(我已经说了很长很长一段时间了),因为你混淆了正在使用的类型。输入两次太频繁了,但是声明0次就太少了。
2008年6月20日上午08:00,c#mvp
我想如果你主要关心的是必须少打字——那么没有任何争论会动摇你使用它。
如果你只是一个查看代码的人,那么谁在乎呢?否则,在这种情况下:
var people = Managers.People
没关系,但在这种情况下:
var fc = Factory.Run();
它使我的大脑从代码的“英文”开始形成的任何即时类型推断短路。
否则,就用你最好的判断和编程“礼貌”来对待那些可能不得不为你的项目工作的人。
Apart from readability concerns, there is one real issue with the use of 'var'. When used to define variables that are assigned to later in the code it can lead to broken code if the type of the expression used to initialize the variable changes to a narrower type. Normally it would be safe to refactor a method to return a narrower type than it did before: e.g. to replace a return type of 'Object' with some class 'Foo'. But if there is a variable whose type is inferred based on the method, then changing the return type will mean that this variable can longer be assigned a non-Foo object:
var x = getFoo(); // Originally declared to return Object
x = getNonFoo();
所以在这个例子中,改变getFoo的返回类型会使getNonFoo的赋值变为非法。
如果getFoo和它的所有用途都在同一个项目中,这不是什么大问题,但如果getFoo在一个库中供外部项目使用,如果他们像这样使用'var',你就不能确保缩小返回类型不会破坏某些用户的代码。
正是由于这个原因,当我们在Curl编程语言中添加类似的类型推断特性(在Curl中称为'def')时,我们阻止了对使用这种语法定义的变量的赋值。
在IEnumerable<int>和IEnumerable<double>之间的比较中,你不需要担心-如果你传递了错误的类型,你的代码无论如何都不会编译。
不需要考虑类型安全,因为var不是动态的。这只是编译器的魔法,任何类型不安全的调用都会被捕获。
Linq绝对需要Var:
var anonEnumeration =
from post in AllPosts()
where post.Date > oldDate
let author = GetAuthor( post.AuthorId )
select new {
PostName = post.Name,
post.Date,
AuthorName = author.Name
};
现在看看智能感知中的anonEnumeration,它会显示类似IEnumerable<'a>
foreach( var item in anonEnumeration )
{
//VS knows the type
item.PostName; //you'll get intellisense here
//you still have type safety
item.ItemId; //will throw a compiler exception
}
c#编译器非常聪明——单独生成的anon类型如果它们的属性匹配,将具有相同的生成类型。
除此之外,只要你有智能感知,在上下文清楚的地方使用var是有意义的。
//less typing, this is good
var myList = new List<UnreasonablyLongClassName>();
//also good - I can't be mistaken on type
var anotherList = GetAllOfSomeItem();
//but not here - probably best to leave single value types declared
var decimalNum = 123.456m;