在与同事讨论了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关键字。
他们把它和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:
类型名称相对较短且易于阅读(提示:通常不是泛型)
从初始化式的名称来看,类型并不明显
确切的类型对于理解代码/算法非常重要
在类层次结构上,当一个人不能很容易地知道正在使用层次结构的哪个级别时
最后,我永远不会使用var的本机值类型或相应的可空<>类型(int,十进制,字符串,十进制?,……)。这里有一个隐含的假设,如果你使用var,一定有一个“原因”。
这些都是指导方针。你还应该考虑你同事的经验和技能,算法的复杂性,变量的寿命/范围,等等。
大多数时候,没有完美的正确答案。或者,这并不重要。
[编辑:删除重复的子弹]
从关于这一主题的讨论来看,结果似乎是:
Good: var customers = new List<Customer>();
争议性:var customers = dataAccess.GetCustomers();
忽略“var”神奇地帮助重构的错误观点,对我来说最大的问题是人们坚持认为他们不关心返回类型是什么,“只要他们能枚举集合”。
考虑:
IList<Customer> customers = dataAccess.GetCustomers();
var dummyCustomer = new Customer();
customers.Add(dummyCustomer);
现在考虑:
var customers = dataAccess.GetCustomers();
var dummyCustomer = new Customer();
customers.Add(dummyCustomer);
现在,重构数据访问类,使GetCustomers返回IEnumerable<Customer>,看看会发生什么……
这里的问题是,在第一个示例中,您明确了对GetCustomers方法的期望—您说您希望它返回一些行为类似于列表的东西。在第二个示例中,这个期望是隐式的,从代码中不能立即看出。
(对我来说)有趣的是,许多支持var的论点说“我不在乎它返回什么类型”,但接着说“我只需要迭代它……”。(因此它需要实现IEnumerable接口,这意味着类型很重要)。
我不明白这有什么大不了的。
var something = someMethod(); // Type of 'something' not clear <-- not to the compiler!
你仍然对“某事”有完全的智能感知,对于任何不明确的情况,你都有单元测试,对吗?(是吗?)
它不是varchar,也不是dim,当然也不是动态或弱类型。它像这样阻止疯狂的人:
List<somethinglongtypename> v = new List<somethinglongtypename>();
把这些杂乱的思想归纳为:
var v = new List<somethinglongtypename>();
不错,但不如:
v = List<somethinglongtypename>();
但这就是布的作用。