在C#中使用var关键字

在与同事讨论在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的types,但是它与声明一个新对象的var不一样。

对于LINQ来说,更糟的是,例如: –

 var results = from item in someList where item != 3 select item; 

这并不比equivilent foreach(var列表someList){// …} equivilent更好。

这里有一个关于types安全性的真正担心 – 例如,如果我们要将该查询的结果放入一个接受IEnumerable <int>和IEnumerable <double>的重载方法中,则调用方可能会无意中传入错误的types。

var 确实保持了强types化,但是问题是这个types在定义时是不是很明显是危险的,当过载意味着编译器错误在你无意中将错误types传递给方法时可能不会发出。

我仍然认为在某些情况下var可以使代码更具可读性。 如果我有一个订单属性的客户类,我想分配给一个variables,我只会这样做:

 var orders = cust.Orders; 

我不关心,如果Customer.Orders是IEnumerable<Order>ObservableCollection<Order>BindingList<Order> – 我想要的是保持该列表在内存中迭代它或得到它的计数或稍后的东西。

对比上面的声明:

 ObservableCollection<Order> orders = cust.Orders; 

对我来说,types名称只是噪音。 如果我回去决定改变Customer.Orderstypes的轨道(从ObservableCollection<Order>IList<Order> ),那么我也需要更改这个声明 – 我不需要做的事情如果我首先使用了var。

我广泛使用var 。 有人批评说,这会降低代码的可读性,但没有理由支持这一说法。

无可否认,这可能意味着我们正在处理的是什么types并不清楚。 所以呢? 这实际上是一个分离devise的重点。 在处理接口时,你强调对variables的types感兴趣。 var需要进一步说明这一点,但是我认为从可读性的angular度来看,这个论点仍然是一样的:程序员不应该对variables的types感兴趣,而应该关心variables的作用 。 这就是为什么微软也称为types推断“鸭子打字”。

那么,当我使用var声明它时,variables是做什么的? 简单来说,IntelliSense告诉我它确实做了什么。 任何关于C#忽略IDE的推理都不符合实际。 实际上,每个C#代码都在支持IntelliSense的IDE中进行编程。

如果我正在使用一个var声明的variables,并弄糊涂了variables的存在,那么我的代码有一些根本性的错误。 var不是原因,它只是使症状可见。 不要责怪使者。

现在,C#团队已经发布了一个编码指南,指出var 只能用来捕获创build匿名types的LINQ语句的结果(因为在这里,我们没有真正的var替代)。 那么,拧紧。 只要C#团队没有给我这个指导方针一个合理的论点,我会忽略它,因为在我的专业和个人的意见,这是纯粹的胡扯。 (对不起,我没有链接到有关的准则。)

实际上,为什么你不应该使用var ,有一些(表面的) 很好的解释 ,但是我仍然相信他们在很大程度上是错误的。 以“searchabililty”为例:作者声称var很难searchMyType被使用的地方。 对。 所以做接口。 其实,为什么我想知道这个class在哪里? 我可能更感兴趣的是它在哪里实例化,这仍然是可search的,因为它的构造函数必须被调用(即使这是间接完成的,types名称必须在某处)。

Var,在我看来,在C#中是件好事 tm 。 任何这样键入的variables仍然是强types的,但是它从定义的赋值的右边获得它的types。 由于types信息在右侧是可用的,所以在大多数情况下,不必要的和过度冗长的也必须在左侧input。 我认为这会显着提高可读性而不会降低types安全性。

从我的angular度来看,从可读性的angular度来看,使用好的variables和方法的命名约定比显式的types信息更重要。 如果我需要的types信息,我总是可以hover在variables(在VS),并得到它。 一般来说,读者不需要明确的types信息。 对于开发人员来说,在VS中你仍然可以得到Intellisense,不pipevariables是如何声明的。 话虽如此,仍然可能有情况下明确声明types是有意义的 – 也许你有一个方法返回一个List<T> ,但是你想把它作为一个IEnumerable<T>在你的方法。 为了确保您使用的是接口,声明接口types的variables可以使这个显式的。 或者,也许你想声明一个没有初始值的variables – 因为它会立即得到一个基于某种条件的值。 在这种情况下,你需要这个types。 如果types信息是有用或必要的,请继续使用它。 但是,我觉得,通常情况下这是没有必要的,而且在大多数情况下,代码更容易阅读。

这两者都不是绝对正确的。 var对可读性有正面和负面的影响。 在我看来,当以下任一情况属实时,应该使用var

  1. 这个types是匿名的(好吧,这里没有任何select,因为在这种情况下它必须是var)
  2. types是显而易见的基于分配的expression式(即var foo = new TypeWithAReallyLongNameTheresNoSenseRepeating()

var没有性能影响,因为它是句法糖; 编译器推断这个types,并在编译成IL的时候定义它; 实际上没有什么dynamic的。

来自C#团队的高级软件devise工程师Eric Lippert:

为什么介绍var关键字?

有两个原因,一个是今天存在的,一个是3.0。

第一个原因是由于所有的冗余,这个代码是非常难看的:

Dictionary<string, List<int>> mylists = new Dictionary<string, List<int>>();

这是一个简单的例子 – 我写得更糟。 任何时候你被迫input两次完全相同的东西,这是我们可以删除的冗余。 写得好多了

var mylists = new Dictionary<string,List<int>>();

让编译器根据赋值来判断types是什么。

其次,C#3.0引入了匿名types。 由于匿名types根据定义没有名称,因此如果匿名types是匿名的,则需要能够从初始化expression式中推断variables的types。

强调我的。 整篇文章, C#3.0仍然是静态types,诚实! ,接下来的系列都相当不错。

这是什么var是。 其他用途可能不会很好。 任何与JScript,VBScript或dynamictypes的比较都是完整的。 再次请注意, var必需的 ,才能使某些其他function在.NET中工作。

我认为var的使用应该加上明智的selectvariables名称。

在foreach语句中使用var没有问题,只要它不是这样的:

 foreach (var c in list) { ... } 

如果更像这样:

 foreach (var customer in list) { ... } 

然后有人阅读代码将更有可能理解“列表”是什么。 如果你有控制列表variables本身的名字,那就更好了。

同样的情况也适用于其他情况。 这是相当无用的:

 var x = SaveFoo(foo); 

…但这是有道理的:

 var saveSucceeded = SaveFoo(foo); 

我想每个人都是他自己的。 我发现自己这样做,这只是疯了:

 var f = (float)3; 

我需要某种12步的var程序。 我的名字是马特,我(ab)使用var。

我们已经采用了“为人而不是在机器上”的理念,基于这样一个假设,即在维护模式下花费的时间要比在新的开发中花费多倍。

对我来说,这就排除了编译器“知道”variables是什么types的观点 – 当然,由于编译器会停止编译代码,因此无法第一次编写无效的代码,但是当下一个开发人员正在读取代码在6个月的时间内,他们需要能够推断出variables正确或不正确的行为,并迅速找出问题的原因。

从而,

 var something = SomeMethod(); 

被我们的编码标准所禁止,但我们的团队鼓励以下内容,因为它提高了可读性:

 var list = new List<KeyValuePair<string, double>>(); FillList( list ); foreach( var item in list ) { DoWork( item ); } 

这并不坏,这更多的是一种文体,它往往是主观的。 它可以添加不一致性,当你使用var和当你不使用。

另一个值得关注的情况是,在下面的调用中,你不能通过查看代码来看到CallMe返回的types:

 var variable = CallMe(); 

这是我对var的主要抱怨。

我使用VAR,当我在方法中声明匿名委托时,不知何故var比我使用Func更清洁。 考虑这个代码:

 var callback = new Func<IntPtr, bool>(delegate(IntPtr hWnd) { ... }); 

编辑 :更新基于朱利安input的最后一个代码示例

Var根本不像变体。 该variables仍然是强types的,只是你不按键来获得这种方式。 您可以将其hover在Visual Studio中查看types。 如果你正在阅读印刷的代码,那么你可能需要考虑一下这个types。 但是只有一行声明了它,许多行也使用它,所以给出一些体面的名字仍然是使代码更容易遵循的最好方法。

是使用Intellisense懒惰? 打字比整个名字less。 还是有些工作less,但不值得批评呢? 我认为有,var是其中之一。

你需要的最可能的时间是匿名types(它是100%需要的); 但它也避免了重复的琐碎的情况下,国际海事组织使线更加清晰。 我不需要两次看到types的一个简单的初始化。

例如:

 Dictionary<string, List<SomeComplexType<int>>> data = new Dictionary<string, List<SomeComplexType<int>>>(); 

(请不要编辑上面的hscroll – 它有点certificate了这一点!!!)

VS:

 var data = new Dictionary<string, List<SomeComplexType<int>>>(); 

然而,有些时候这是误导性的,可能会导致错误。 如果原始variables和初始化types不相同,请小心使用var 。 例如:

 static void DoSomething(IFoo foo) {Console.WriteLine("working happily") } static void DoSomething(Foo foo) {Console.WriteLine("formatting hard disk...");} // this working code... IFoo oldCode = new Foo(); DoSomething(oldCode); // ...is **very** different to this code var newCode = new Foo(); DoSomething(newCode); 

var很困难的一个具体情况是:离线代码评论,特别是纸上的评论。

你不能依靠鼠标hover。

我看不出有什么大不了的

 var something = someMethod(); // Type of 'something' not clear <-- not to the compiler! 

你对“某事”仍然有完全的智能感,对于任何含糊不清的情况你都有unit testing,对吗? ( 你做? )

这不是varchar,它不是暗淡的,而且它不是dynamic的或弱的input。 这是停止maddnes这样的:

 List<somethinglongtypename> v = new List<somethinglongtypename>(); 

并把这个总的思想杂乱减less到:

 var v = new List<somethinglongtypename>(); 

不错,不如:

 v = List<somethinglongtypename>(); 

但是那就是Boo的意思

如果有人使用var关键字是因为他们不想“弄清楚types”,那肯定是错误的原因。 var关键字不会创build一个dynamictypes的variables,编译器仍然需要知道types。 由于variables总是有一个特定的types,如果可能的话,这个types在代码中也应该是明显的。

例如,使用var关键字的好理由是:

  • 在需要的地方,即为匿名types声明参考。
  • 它使代码更具可读性,即去除重复声明。

写出数据types通常会使代码更容易遵循。 它显示了您正在使用的数据types,因此您无需首先弄清楚代码的作用即可找出数据types。

鉴于目前Intellisense的function非常强大,我不确定var是否比在类中使用成员variables或者在可见屏幕区域定义的方法中的局部variables更难读取。

如果你有一行代码如

 IDictionary<BigClassName, SomeOtherBigClassName> nameDictionary = new Dictionary<BigClassName, SomeOtherBigClassName>(); 

阅读比阅读更容易或更难:

 var nameDictionary = new Dictionary<BigClassName, SomeOtherBigClassName>(); 

我认为VAR的关键是只在适当的时候使用它,也就是说,在Linq中做这件事情时(也可能在其他情况下)。

如果你一个types的东西在那么你应该使用它 – 不这样做是简单的懒惰(而不是创造性的懒惰,这是一般被鼓励 – 优秀的程序员工作很懒惰,可以考虑首先是事物的来源)。

一揽子禁令与一开始滥用该构造一样糟糕,但需要有一个明智的编码标准。

另外要记住的是,它不是一个VBtypes的var,它不能改变types – 它一个强typesvariables,它只是types的推断(这就是为什么有人会认为它不是不合理的使用它,例如,一个foreach,但我不同意的可读性和可维护性的原因)。

我怀疑这个将要运行并运行( – :

墨菲

当然, int很容易,但是当variables的types是IEnumerable<MyStupidLongNamedGenericClass<int, string>> ,var变得更容易。

从CodingHorror的这个问题上的post被盗:


不幸的是,你和其他人几乎错了。 虽然我同意你的看法,冗余不是一件好事,但解决这个问题的更好的方法是做如下的事情:

MyObject m = new();

或者如果你传递参数:

Person p = new(“FirstName”,“LastName);

Where in the creation of a new object, the compiler infers the type from the left-hand side, and not the right. This has other advantages over "var", in that it could be used in field declarations as well (there are also some other areas that it could be useful as well, but I won't get into it here).

In the end, it just wasn't intended to reduce redundancy. Don't get me wrong, "var" is VERY important in C# for anonymous types/projections, but the use here is just WAY off (and I've been saying this for a long, long time) as you obfuscate the type that is being used. Having to type it twice is too often, but declaring it zero times is too few.

Nicholas Paldino .NET/C# MVP on June 20, 2008 08:00 AM


I guess if your main concern is to have to type less — then there isn't any argument that's going to sway you from using it.

If you are only going to ever be the person who looks at your code, then who cares? Otherwise, in a case like this:

 var people = Managers.People 

it's fine, but in a case like this:

 var fc = Factory.Run(); 

it short circuits any immediate type deductions my brain could begin forming from the 'English' of the code.

Otherwise, just use your best judgment and programming 'courtesy' towards others who might have to work on your project.

Using var instead of explicit type makes refactorings much easier (therefore I must contradict the previous posters who meant it made no difference or it was purely "syntactic sugar").

You can change the return type of your methods without changing every file where this method is called. Imagine

 ... List<MyClass> SomeMethod() { ... } ... 

which is used like

 ... IList<MyClass> list = obj.SomeMethod(); foreach (MyClass c in list) System.Console.WriteLine(c.ToString()); ... 

If you wanted to refactor SomeMethod() to return an IEnumerable<MySecondClass> , you would have to change the variable declaration (also inside the foreach ) in every place you used the method.

如果你写

 ... var list = obj.SomeMethod(); foreach (var element in list) System.Console.WriteLine(element.ToString()); ... 

instead, you don't have to change it.

@aku: One example is code reviews. Another example is refactoring scenarios.

Basically I don't want to go type-hunting with my mouse. It might not be available.

It's a matter of taste. All this fussing about the type of a variable disappears when you get used to dynamically typed languages. That is, if you ever start to like them (I'm not sure if everybody can, but I do).

C#'s var is pretty cool in that it looks like dynamic typing, but actually is static typing – the compiler enforces correct usage.

The type of your variable is not really that important (this has been said before). It should be relatively clear from the context (its interactions with other variables and methods) and its name – don't expect customerList to contain an int

I am still waiting to see what my boss thinks of this matter – I got a blanket "go ahead" to use any new constructs in 3.5, but what will we do about maintenance?

In your comparison between IEnumerable<int> and IEnumerable<double> you don't need to worry – if you pass the wrong type your code won't compile anyway.

There's no concern about type-safety, as var is not dynamic. It's just compiler magic and any type unsafe calls you make will get caught.

Var is absolutely needed for Linq:

 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 }; 

Now look at anonEnumeration in intellisense and it will appear something like 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 } 

The C# compiler is pretty clever – anon types generated separately will have the same generated type if their properties match.

Outside of that, as long as you have intellisense it makes good sense to use var anywhere the context is clear.

 //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; 

I guess it depends on your perspective. I personally have never had any difficulty understanding a piece of code because of var "misuse", and my coworkers and I use it quite a lot all over. (I agree that Intellisense is a huge aid in this regard.) I welcome it as a way to remove repetitive cruft.

After all, if statements like

 var index = 5; // this is supposed to be bad var firstEligibleObject = FetchSomething(); // oh no what type is it // i am going to die if i don't know 

were really that impossible to deal with, nobody would use dynamically typed languages.

I only use var when it's clear to see what type is used.

For example, I would use var in this case, because you can see immediately that x will be of the type "MyClass":

 var x = new MyClass(); 

I would NOT use var in cases like this, because you have to drag the mouse over the code and look at the tooltip to see what type MyFunction returns:

 var x = MyClass.MyFunction(); 

Especially, I never use var in cases where the right side is not even a method, but only a value:

 var x = 5; 

(because the compiler can't know if I want a byte, short, int or whatever)

To me, the antipathy towards var illustrates why bilingualism in .NET is important. To those C# programmers who have also done VB .NET, the advantages of var are intuitively obvious. The standard C# declaration of:

 List<string> whatever = new List<string>(); 

is the equivalent, in VB .NET, of typing this:

 Dim whatever As List(Of String) = New List(Of String) 

Nobody does that in VB .NET, though. It would be silly to, because since the first version of .NET you've been able to do this…

 Dim whatever As New List(Of String) 

…which creates the variable and initializes it all in one reasonably compact line. Ah, but what if you want an IList<string> , not a List<string> ? Well, in VB .NET that means you have to do this:

 Dim whatever As IList(Of String) = New List(Of String) 

Just like you'd have to do in C#, and obviously couldn't use var for:

 IList<string> whatever = new List<string>(); 

If you need the type to be something different, it can be. But one of the basic principles of good programming is reducing redundancy, and that's exactly what var does.

Use it for anonymous types – that's what it's there for. Anything else is a use too far. Like many people who grew up on C, I'm used to looking at the left of the declaration for the type. I don't look at the right side unless I have to. Using var for any old declaration makes me do that all the time, which I personally find uncomfortable.

Those saying 'it doesn't matter, use what you're happy with' are not seeing the whole picture. Everyone will pick up other people's code at one point or another and have to deal with whatever decisions they made at the time they wrote it. It's bad enough having to deal with radically different naming conventions, or – the classic gripe – bracing styles, without adding the whole ' var or not' thing into the mix. The worst case will be where one programmer didn't use var and then along comes a maintainer who loves it, and extends the code using it. So now you have an unholy mess.

Standards are a good thing precisely because they mean you're that much more likely to be able to pick up random code and be able to grok it quickly. The more things that are different, the harder that gets. And moving to the 'var everywhere' style makes a big difference.

I don't mind dynamic typing, and I don't mind implict typing – in languages that are designed for them. I quite like Python. But C# was designed as a statically explicitly-typed language and that's how it should stay. Breaking the rules for anonymous types was bad enough; letting people take that still further and break the idioms of the language even more is something I'm not happy with. Now that the genie is out of the bottle, it'll never go back in. C# will become balkanised into camps. 不好。

Many time during testing, I find myself having code like this:

 var something = myObject.SomeProperty.SomeOtherThing.CallMethod(); Console.WriteLine(something); 

Now, sometimes, I'll want to see what the SomeOtherThing itself contains, SomeOtherThing is not the same type that CallMethod() returns. Since I'm using var though, I just change this:

 var something = myObject.SomeProperty.SomeOtherThing.CallMethod(); 

对此:

 var something = myObject.SomeProperty.SomeOtherThing; 

Without var, I'd have to keep changing the declared type on the left hand side as well. I know it's minor, but it's extremely convenient.

For the afficionados that think var saves time, it takes less keystrokes to type:

 StringBuilder sb = new StringBuilder(); 

 var sb = new StringBuilder(); 

Count em if you don't believe me…

19 versus 21

I'll explain if I have to, but just try it… (depending on the current state of your intellisense you may have to type a couple more for each one)

And it's true for every type you can think of!!

My personal feeling is that var should never be used except where the type is not known because it reduces recognition readabiltiy in code. It takes the brain longer to recognize the type than a full line. Old timers who understand machine code and bits know exactly what I am talking about. The brain processes in parallel and when you use var you force it to serialize its input. Why would anyone want to make their brain work harder? That's what computers are for.

I split var all over the places, the only questionable places for me are internal short types, eg I prefer int i = 3; over var i = 3;

It can certainly make things simpler, from code I wrote yesterday:

 var content = new Queue<Pair<Regex, Func<string, bool>>>(); ... foreach (var entry in content) { ... } 

This would have be extremely verbose without var .

Addendum: A little time spent with a language with real type inference (eg F#) will show just how good compilers are at getting the type of expressions right. It certainly has meant I tend to use var as much as I can, and using an explicit type now indicates that the variable is not of the initialising expression's type.

None, except that you don't have to write the type name twice. http://msdn.microsoft.com/en-us/library/bb383973.aspx