使用'var'会影响性能吗?

Jef*_*nke 223 c# variables performance var

之前我问了一个问题,为什么我看到这么多的例子都使用了这个var关键字并得到了答案,虽然它只是匿名类型所必需的,但它仍然被用来使编写代码"更快"/更容易和"只是因为".

这个链接("C#3.0 - Var不是Objec")之后,我看到它var被编译成IL中的正确类型(你会在中间的文章中看到它).

我的问题是IL代码使用var关键字take 会有多少(如果有的话),如果在任何地方使用它,它是否会接近于对代码性能有可衡量的水平?

Joe*_*orn 305

var关键字没有额外的IL代码:对于非匿名类型,生成的IL应该是相同的.如果编译器无法创建该IL,因为它无法确定您打算使用的类型,则会出现编译器错误.

唯一的技巧是,var如果要手动设置类型,将推断出您可能选择了接口或父类型的确切类型.


8年后更新

我的理解已经改变,我需要更新它.我现在相信,var在方法返回接口的情况下,可能会影响性能,但您会使用精确类型.例如,如果您有此方法:

IList<int> Foo()
{
    return Enumerable.Range(0,10).ToList();
}
Run Code Online (Sandbox Code Playgroud)

考虑这三行代码来调用该方法:

List<int> bar1 = Foo();
IList<int> bar = Foo();
var bar3 = Foo();
Run Code Online (Sandbox Code Playgroud)

所有三个按预期编译和执行.但是,前两行完全相同,第三行与第二行匹配,而不是第一行.因为签名Foo()是返回一个IList<int>,这就是编译器将如何构建bar3变量.

从表现的角度来看,大多数情况下你都不会注意到.但是,有些情况下第三行的性能可能不如第一行的性能快.当您继续使用该bar3变量时,编译器可能无法以相同的方式调度方法调用.

请注意,可能(甚至可能)抖动可以消除这种差异,但不能保证.通常,您仍然应该考虑var在性能方面不是一个因素.它当然不像使用dynamic变量.但要说它根本没有任何区别可能会夸大它.

  • @NelsonRothermel:`var x = 42;`*不是*模棱两可.整数文字的类型为"int".如果你想要一个文字长,你写`var x = 42L;`. (49认同)
  • IL不仅应该相同 - 它*是*相同的.var i = 42; 编译与int i = 42完全相同的代码; (23认同)
  • @BrianRasmussen:我知道你的帖子是旧的,但我认为`var i = 42;`(推断类型是int)与`long i = 42;`不同.所以在某些情况下,您可能会对类型推断做出错误的假设.如果值不合适,这可能会导致难以捉摸的/边缘案例运行时错误.出于这个原因,当值没有显式类型时,显式仍然是个好主意.因此,例如,`var x = new List <List <Dictionary <int,string>()>()>()`是可以接受的,但`var x = 42`有点模棱两可,应该写成`int x = 42` 但是他们自己...... (15认同)
  • 在您的3行代码行为不同的示例中,第一行*不会编译*.第二行和第三行(*do*compile)完全相同.如果`Foo`返回一个`List`而不是`IList`,则所有三行都会编译,但第三行*的行为类似于第一行*,而不是第二行. (15认同)
  • 呃IL在C#中代表什么?我从来没有真正听说过它. (6认同)
  • 我参加派对有点晚了,但行"List <int> bar1 = Foo();" 会抛出编译时错误.你不能假设抽象(例如IList <int>)是一个特定的具体结果(例如List <int>).这根本不会编译,除非我在这里遗漏了一些东西. (6认同)
  • 中级语言.它类似于Java的字节码,读取有点像汇编程序. (5认同)
  • 你可以解决你的答案,因为"更新"部分是*明显错误*.请参阅Servy上面的评论. (3认同)

ljs*_*ljs 71

正如Joel所说,编译器在编译时计算 var应该是什么类型,实际上它只是编译器为保存击键而执行的一个技巧,例如

var s = "hi";
Run Code Online (Sandbox Code Playgroud)

被替换为

string s = "hi";
Run Code Online (Sandbox Code Playgroud)

在生成任何IL之前由编译器生成.生成的IL 与您键入的字符串完全相同.


Ric*_*dOD 25

至今没有人提到反射器......

如果编译以下C#代码:

static void Main(string[] args)
{
    var x = "hello";
    string y = "hello again!";
    Console.WriteLine(x);
    Console.WriteLine(y);
}
Run Code Online (Sandbox Code Playgroud)

然后在上面使用反射器,你得到:

// Methods
private static void Main(string[] args)
{
    string x = "hello";
    string y = "hello again!";
    Console.WriteLine(x);
    Console.WriteLine(y);
}
Run Code Online (Sandbox Code Playgroud)

所以答案很明显没有运行时性能!


Rob*_*Rob 17

对于以下方法:

   private static void StringVsVarILOutput()
    {
        var string1 = new String(new char[9]);

        string string2 = new String(new char[9]);
    }
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)


Mic*_*urr 14

C#编译器var在编译时推断出变量的真实类型.生成的IL没有区别.


Chr*_*isH 14

所以,要清楚,这是一种懒惰的编码风格.考虑到选择,我更喜欢原生类型; 我将采取额外的"噪音",以确保我正在编写和阅读我认为我在代码/调试时的确切内容.*耸肩*

  • 这只是您的主观看法,而不是有关性能问题的答案。正确答案是它对性能没有影响。我投票赞成接近 (3认同)

jal*_*alf 8

我认为你没有正确理解你所读到的内容.如果它被编译为正确的类型,那么没有什么区别.当我这样做:

var i = 42;
Run Code Online (Sandbox Code Playgroud)

编译器知道它是一个int,并生成代码,就像我写的一样

int i = 42;
Run Code Online (Sandbox Code Playgroud)

正如您链接的帖子所说,它被编译为相同的类型.它不是运行时检查或其他需要额外代码的东西.编译器只是弄清楚类型必须是什么,并使用它.


Bri*_*lph 5

使用var没有运行时性能成本.虽然,我怀疑编译器需要推断出类型的编译性能成本,尽管这很可能是可以忽略不计的.

  • RHS必须计算其类型 - 编译器会捕获不匹配的类型并抛出错误,所以我认为并不是真正的成本. (10认同)