在与同事讨论了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。有人批评这降低了代码的可读性,但没有证据支持这种说法。
Admittedly, it may mean that it's not clear what type we are dealing with. So what? This is actually the point of a decoupled design. When dealing with interfaces, you are emphatically not interested in the type a variable has. var takes this much further, true, but I think that the argument remains the same from a readability point of view: The programmer shouldn't actually be interested in the type of the variable but rather in what a variable does. This is why Microsoft also calls type inference “duck typing.”
当我用var声明变量时,它会做什么呢?简单,智能感知让它做什么它就做什么。任何关于c#的推理都忽略了IDE,这是不现实的。实际上,每个c#代码都是在支持智能感知的IDE中编写的。
如果我使用了一个var声明的变量,并对变量的用途感到困惑,那么我的代码就有根本性的问题。Var不是原因,它只是使症状可见。不要责怪送信的人。
现在,c#团队发布了一个编码指南,声明var应该只用于捕获创建匿名类型的LINQ语句的结果(因为在这里,我们没有真正的替代var的方法)。去他的。只要c#团队没有给我一个合理的论证,我就会忽略它,因为在我的专业和个人观点中,这纯粹是胡扯。(抱歉;我找不到相关指南的链接。)
Actually, there are some (superficially) good explanations on why you shouldn't use var but I still believe they are largely wrong. Take the example of “searchabililty”: the author claims that var makes it hard to search for places where MyType is used. Right. So do interfaces. Actually, why would I want to know where the class is used? I might be more interested in where it is instantiated and this will still be searchable because somewhere its constructor has to be invoked (even if this is done indirectly, the type name has to be mentioned somewhere).
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')时,我们阻止了对使用这种语法定义的变量的赋值。