未优化的 MSIL 中多余的 NOP 和分支

Superfluous NOPs and branches in unoptimized MSIL

当我将以下代码编译为调试时...

public class MyClass
{
    private int myField;

    public int MyProperty
    {
        get { return myField; }
        set { myField = value; }
    }
}

...编译器生成了带有看似无用指令的奇怪字节码。例如,查看为 属性 MyProperty 的 getter 生成的内容(使用 ildasm.exe 反汇编):

.method public hidebysig specialname instance int32 
        get_MyProperty() cil managed
{
    // Code size       12 (0xc)
    .maxstack  1
    .locals init ([0] int32 CS[=11=]00)
    IL_0000:  nop
    IL_0001:  ldarg.0
    IL_0002:  ldfld      int32 MSILTest.MyClass::myField
    IL_0007:  stloc.0
    IL_0008:  br.s       IL_000a
    IL_000a:  ldloc.0
    IL_000b:  ret
} // end of method MyClass::get_MyProperty

具体来说,IL_0000nop 在那里做什么?为什么编译器会在 IL_0008 处突然生成这个无用的 br.s 指令?为什么它会创建临时局部变量 CS[=19=]00?

对于发布配置,指令集按预期生成:

IL_0000:  ldarg.0
IL_0001:  ldfld      int32 MSILTest.MyClass::myField
IL_0006:  ret

编辑

我想我已经找到了为什么分支和临时局部变量在 different question 中的问题的答案:这可能是为了在调试过程中轻松设置断点。所以剩下的问题是为什么会生成nop指令。

编译器创建这些操作码是为了提供更好的调试体验。在每一行的开头,编译器都会引入一个 nop 所以调试器可以在那里中断。发出分支和临时局部变量,让您分析函数 return 值。