将使用'var'影响性能?
之前我问了一个关于为什么我看到这么多的例子使用var
关键字的问题,并得到了答案,虽然它只是匿名types的必要条件,但是它仍然被用来使代码“更快”/更容易和“只是因为”。
在这个链接之后(“C#3.0 – Var is not Objec”),我看到这个var
被编译成IL中的正确types(你会在中途看到它)。
我的问题是,如果使用var
关键字,IL代码还有多less(如果有的话),并且如果在任何地方都使用代码,它会更接近于在代码性能方面有一个可衡量的级别?
var
关键字没有额外的IL代码:对于非匿名types,结果IL应该是相同的。 如果编译器无法创build该IL,因为它无法确定您打算使用的types,则会出现编译器错误。
唯一的技巧是,如果您要手动设置types, var
将推断出您可能已经select了接口或父types的确切types。
8年后更新
我需要更新这个,因为我的理解已经改变了。 我现在认为,在方法返回接口的情况下, var
可能会影响性能,但是您可能会使用确切的types。 例如,如果你有这个方法:
IList<int> Foo() { return Enumerable.Range(0,10).ToList(); }
考虑这三行代码来调用该方法:
List<int> bar1 = Foo(); IList<int> bar = Foo(); var bar3 = Foo();
所有三个按预期编译和执行。 然而,前两行不完全相同,第三行将匹配第二行,而不是第一行。 因为Foo()
的签名是返回一个IList<int>
,编译器将如何构buildbar3
variables。
从性能angular度来看,大部分你都不会注意到。 但是,有些情况下第三行的performance可能不如第一行的performance那么快 。 当您继续使用bar3
variables时,编译器可能无法以相同方式分派方法调用。
请注意,有可能(甚至可能)抖动将能够消除这种差异,但不能保证。 一般来说,你仍然应该考虑var
是一个非因素的性能。 这当然不像使用dynamic
variables。 但说永远不会有所作为可能会夸大它。
正如Joel所说的那样,编译器在编译时应该使用什么types的var,实际上这只是编译器保存击键的一个技巧,例如
var s = "hi";
被replace
string s = "hi";
由任何IL生成之前的编译器 。 生成的IL将与inputstring完全相同 。
由于没有人提到reflection器…
如果您编译以下C#代码:
static void Main(string[] args) { var x = "hello"; string y = "hello again!"; Console.WriteLine(x); Console.WriteLine(y); }
然后使用reflection器,你会得到:
// Methods private static void Main(string[] args) { string x = "hello"; string y = "hello again!"; Console.WriteLine(x); Console.WriteLine(y); }
所以答案显然没有运行时性能的影响!
对于以下方法:
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
C#编译器在编译时推断var
variables的真实types。 生成的IL没有区别。
所以,要清楚的是,这是一种懒惰的编码风格。 考虑到select,我更喜欢本地types; 我将采取额外的“噪音”,以确保我正在编写和阅读正是我认为我在代码/debugging时间。 *耸肩*
我认为你没有正确理解你所读的内容。 如果它被编译成正确的types,那么没有区别。 当我这样做:
var i = 42;
编译器知道这是一个int,并生成代码,如果我写了
int i = 42;
正如你链接到的post所说,它被编译成相同的types。 这不是一个运行时检查或任何其他需要额外的代码。 编译器只是找出types必须是什么,并使用它。
使用var没有运行时性能成本。 尽pipe如此,我还是怀疑编译器需要编译性能成本,因为编译器需要推断types,尽pipe这很可能是可以忽略的。
如果编译器可以执行自动types推理,那么不会有任何性能问题。 这两个都会生成相同的代码
var x = new ClassA(); ClassA x = new ClassA();
然而,如果你正在dynamic地构造types(LINQ …),那么var
是唯一的问题,并且还有其他的机制来比较以说明什么是惩罚。
我总是在网页文章或指南中使用var这个词。
在线文章的文本编辑器的宽度很小。
如果我写这个:
SomeCoolNameSpace.SomeCoolClassName.SomeCoolSubClassName coolClass = new SomeCoolNameSpace.SomeCoolClassName.SomeCoolSubClassName();
您会看到上面显示的预编码文本太长,从盒子中stream出,会被隐藏起来。 读者需要滚动到右侧才能看到完整的语法。
这就是为什么我总是在web文章中使用关键字var的原因。
var coolClass = new SomeCoolNameSpace.SomeCoolClassName.SomeCoolSubClassName();
整个呈现的预编码恰好适合在屏幕内。
实际上,对于声明对象,我很less使用var,我依靠intellisense来更快地声明对象。
例:
SomeCoolNamespace.SomeCoolObject coolObject = new SomeCoolNamespace.SomeCoolObject();
但是,为了从方法中返回对象,我使用var来更快地编写代码。
例:
var coolObject = GetCoolObject(param1, param2);
“var”是人们所爱或恨的东西之一(如地区)。 虽然,不像地区,创build匿名类时,var是绝对必要的。
对我来说,当你直接创build一个对象时,var是有意义的:
var dict = new Dictionary<string, string>();
这就是说,你可以很容易地做到:
Dictionary<string, string> dict =
new和intellisense会在这里为你填写。
如果您只想使用特定的接口,则除非您调用的方法直接返回接口,否则不能使用var。
Resharper似乎在全面使用“var”的方面,这可能会推动更多的人这样做。 但是我同意,如果你正在调用一个方法,读起来很难,而且名称返回的内容并不明显。
var本身并没有放慢速度,但有一个告诫,这并不是很多人想到的。 如果你做var result = SomeMethod();
那么在那之后的代码正在等待某种结果返回到你要调用各种方法或属性或其他的地方。 如果SomeMethod()
将其定义更改为某种其他types,但仍符合其他代码所期望的合同,那么您只是创build了一个非常糟糕的错误(当然,如果没有单元/集成testing)。