返回变量是由编译器自动创建的吗?

ana*_*lov 5 c# compiler-construction

在查看项目源代码时,我偶然发现了一个方法并且想知道一件事.从性能/内存/编译器的角度来看,以下两种方法是否完全相同?

public static string Foo(string inputVar)
{
    string bar = DoSomething(inputVar);
    return bar;
}

public static string Foo(string inputVar)
{
    return DoSomething(inputVar);
}
Run Code Online (Sandbox Code Playgroud)

返回变量是由编译器自动创建的吗?

sve*_*are 8

使用IL Disassembler(包含在.NET SDK/VS中),您可以查看编译器生成的IL.代码是使用VS2013(而不是Roslyn)生成的.

最上面的一个给出以下IL:

.method public hidebysig static string  Foo(string inputVar) cil managed
{
  // Code size       14 (0xe)
  .maxstack  1
  .locals init ([0] string bar,
           [1] string CS$1$0000)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  call       string TestIL.Program::DoSomething(string)
  IL_0007:  stloc.0
  IL_0008:  ldloc.0
  IL_0009:  stloc.1
  IL_000a:  br.s       IL_000c
  IL_000c:  ldloc.1
  IL_000d:  ret
} // end of method Program::Foo
Run Code Online (Sandbox Code Playgroud)

第二个:

.method public hidebysig static string  Foo(string inputVar) cil managed
{
  // Code size       12 (0xc)
  .maxstack  1
  .locals init ([0] string CS$1$0000)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  call       string TestIL.Program::DoSomething(string)
  IL_0007:  stloc.0
  IL_0008:  br.s       IL_000a
  IL_000a:  ldloc.0
  IL_000b:  ret
} // end of method Program::Foo
Run Code Online (Sandbox Code Playgroud)

差异似乎是第一个在方法locals表中创建了一个额外的条目.如果这是由JIT编译器优化,我不知道.

回答这个问题:不,在这种情况下编译器似乎不会自动生成局部变量,但在更高级的情况下它可能会执行(如返回x*(y + z)).

编辑:如果您打开"优化代码",它更加清晰:

.method public hidebysig static string  Foo(string inputVar) cil managed
{
  // Code size       9 (0x9)
  .maxstack  1
  .locals init ([0] string bar)
  IL_0000:  ldarg.0
  IL_0001:  call       string TestIL.Program::DoSomething(string)
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  ret
} // end of method Program::Foo

.method public hidebysig static string  Foo(string inputVar) cil managed
{
  // Code size       7 (0x7)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  call       string TestIL.Program::DoSomething(string)
  IL_0006:  ret
} // end of method Program::Foo
Run Code Online (Sandbox Code Playgroud)

  • 考虑启用编译器优化.我预计它会将IL减少到3分别为5条指令,这将使差异更明显. (2认同)