之前我问了一个问题,为什么我看到这么多的例子使用var关键字,得到的答案是,虽然它只对匿名类型是必要的,但它仍然被用来使代码编写“更快”/更容易,并且“只是因为”。
通过这个链接(“c# 3.0 - Var不是对象”),我看到Var在IL中被编译为正确的类型(您将在文章的中间看到它)。
我的问题是,如果有的话,使用var关键字的IL代码会占用多少,如果它在任何地方都被使用,它是否会接近于具有可测量的代码性能水平?
之前我问了一个问题,为什么我看到这么多的例子使用var关键字,得到的答案是,虽然它只对匿名类型是必要的,但它仍然被用来使代码编写“更快”/更容易,并且“只是因为”。
通过这个链接(“c# 3.0 - Var不是对象”),我看到Var在IL中被编译为正确的类型(您将在文章的中间看到它)。
我的问题是,如果有的话,使用var关键字的IL代码会占用多少,如果它在任何地方都被使用,它是否会接近于具有可测量的代码性能水平?
当前回答
“var”是人们要么喜欢要么讨厌的东西之一(就像区域一样)。不过,与区域不同,var在创建匿名类时是绝对必要的。
对我来说,当你直接像这样更新一个对象时,var是有意义的:
var dict = new Dictionary<string, string>();
话虽如此,你可以很容易地做到:
Dictionary<string, string> dict = new和intellisense将在这里为您填充其余部分。
如果你只想使用一个特定的接口,那么你不能使用var,除非你调用的方法直接返回该接口。
Resharper似乎是在使用“var”的一边,这可能会促使更多人这样做。但我同意,如果你在调用一个方法,并且它的名称返回的是什么并不明显,那就更难读了。
Var本身并没有减慢速度,但有一个警告,很多人都没有想到。如果你执行var result = SomeMethod();之后的代码会期望返回某种结果,你会调用各种方法或属性之类的。如果SomeMethod()将其定义更改为其他类型,但它仍然满足其他代码所期望的契约,那么您就创建了一个非常严重的错误(当然,如果没有单元/集成测试)。
其他回答
“var”是人们要么喜欢要么讨厌的东西之一(就像区域一样)。不过,与区域不同,var在创建匿名类时是绝对必要的。
对我来说,当你直接像这样更新一个对象时,var是有意义的:
var dict = new Dictionary<string, string>();
话虽如此,你可以很容易地做到:
Dictionary<string, string> dict = new和intellisense将在这里为您填充其余部分。
如果你只想使用一个特定的接口,那么你不能使用var,除非你调用的方法直接返回该接口。
Resharper似乎是在使用“var”的一边,这可能会促使更多人这样做。但我同意,如果你在调用一个方法,并且它的名称返回的是什么并不明显,那就更难读了。
Var本身并没有减慢速度,但有一个警告,很多人都没有想到。如果你执行var result = SomeMethod();之后的代码会期望返回某种结果,你会调用各种方法或属性之类的。如果SomeMethod()将其定义更改为其他类型,但它仍然满足其他代码所期望的契约,那么您就创建了一个非常严重的错误(当然,如果没有单元/集成测试)。
var关键字没有额外的中间语言(IL)代码:结果IL对于非匿名类型应该是相同的。如果编译器不能创建那个IL,因为它不能找出你想要使用的类型,你就会得到一个编译器错误。
唯一的技巧是,如果您手动设置类型,var将推断出您可能已经选择了一个Interface或父类型的确切类型。
c#编译器在编译时推断var变量的真实类型。产生的IL没有差异。
以下方法:
private static void StringVsVarILOutput()
{
var string1 = new String(new char[9]);
string string2 = new String(new char[9]);
}
IL输出是这样的:
{
.method private hidebysig static void StringVsVarILOutput() cil managed
// Code size 28 (0x1c)
.maxstack 2
.locals init ([0] string string1,
[1] string string2)
IL_0000: nop
IL_0001: ldc.i4.s 9
IL_0003: newarr [mscorlib]System.Char
IL_0008: newobj instance void [mscorlib]System.String::.ctor(char[])
IL_000d: stloc.0
IL_000e: ldc.i4.s 9
IL_0010: newarr [mscorlib]System.Char
IL_0015: newobj instance void [mscorlib]System.String::.ctor(char[])
IL_001a: stloc.1
IL_001b: ret
} // end of method Program::StringVsVarILOutput
就像Joel说的,编译器在编译时计算出var应该是什么类型,实际上这只是编译器用来节省击键的一个技巧,举个例子
var s = "hi";
被替换为
string s = "hi";
在生成任何IL之前,编译器会调用。生成的IL将完全相同,如果你键入字符串。