在与同事讨论了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确实保持强类型,但问题是,在定义中不立即显示类型是否危险,当重载意味着当你无意中将错误的类型传递给方法时,编译器可能不会发出错误,这种情况会被放大。
有时编译器也能比开发人员“更好”地推断出需要什么——至少开发人员不了解他所使用的api需要什么。
例如-当使用linq时:
示例1
Func<Person, bool> predicate = (i) => i.Id < 10;
IEnumerable<Person> result = table.Where(predicate);
示例2
var predicate = (Person i) => i.Id < 10;
var result = table.Where(predicate);
在上面的代码中-假设一个是使用Linq到Nhibernate或Linq到SQL,示例1将
返回Person对象的整个结果集,然后在客户端进行筛选。
然而,示例2将在服务器上执行查询(例如在Sql server上使用Sql),因为编译器足够聪明,可以计算出Where函数应该采用表达式>而不是Func。
示例1中的结果在返回IEnumerable时也不能在服务器上进一步查询,而在示例2中,编译器可以计算出结果是否应该是IQueryable而不是IEnumerable
我认为人们不理解var关键字。
他们把它和Visual Basic / JavaScript关键字搞混了,
这完全是另一回事。
许多人认为var关键字意味着
弱类型(或动态类型),而实际上c#是并保持强类型。
如果你在javascript中考虑这个:
var something = 5;
你可以:
something = "hello";
在c#中,编译器会从第一条语句中推断出类型,
导致“int”类型的东西,因此会产生第二条语句
在异常中。
人们只需要明白,使用var关键字并不意味着
动态类型,然后决定var关键字的使用程度,
知道它对于将要编译的内容绝对没有区别。
当然var关键字的引入是为了支持匿名类型,
但如果你看这个:
LedDeviceController controller = new LedDeviceController("172.17.0.1");
这是非常非常冗长的,我相信这是一样可读的,如果不是更多:
var controller = new LedDeviceController("172.17.0.1");
结果是完全相同的,所以是的,我在我的代码中使用它
更新:
也许,只是也许……他们应该用另一个关键词,
那我们就不会有这样的讨论了……也许是“推断”关键字而不是“var”
好吧,这个问题会一直固执己见,但我会试着给出我的观点-尽管我认为我的观点是如此混乱,你可能不会从中得到什么。
首先——有匿名类型,为此你需要使用“var”关键字来分配一个匿名类型作为类的对象——这里没有太多的讨论,“var”是必要的。
然而,对于更简单的类型,如int型、长型、字符串型等等,我倾向于输入适当的类型。主要是因为它有点像“懒人的工具”,我在这里看不到太多的好处,很少的按键和它可能带来的困惑,这是不值得的。特别是浮点数的各种类型(浮点数、双精度数、十进制数)使我感到困惑,因为我对字面量中的后缀不坚定——我喜欢在源代码中看到类型。
话虽如此,如果类型更复杂和/或它显式地重复在赋值的右侧,我倾向于大量使用var。这可以是一个List<string>或etc,例如:
var list = new List<string>();
在这种情况下,我认为没有必要重复类型两次——特别是当您开始更改代码和类型更改时——泛型类型可能会变得越来越复杂,因此必须更改它们两次只是一种痛苦。当然,如果你希望针对IList<string>编码,那么你必须显式地命名类型。
简而言之,我做了以下事情:
当类型很短或不能脱离上下文读取时,显式地命名类型
在必要时使用var(废话)
当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();
它使我的大脑从代码的“英文”开始形成的任何即时类型推断短路。
否则,就用你最好的判断和编程“礼貌”来对待那些可能不得不为你的项目工作的人。