假设我有以下代码:
public class Class1
{
private Class2 obj;
public void MethodA()
{
var class2 = new Class2();
class2.PropertyI = 2;
obj = MethodB(class2);
}
public Class2 MethodB(Class2 class2)
{
return class2;
}
}
public class Class2
{
public int PropertyI { get; set; }
}
使用Visual Studio 2010作为.NET 2.0程序集编译生成的IL代码如下:
.method public hidebysig instance void MethodA() cil managed
{
.maxstack 3
.locals init (
[0] class ClassLibrary1.Class2 class2)
L_0000: nop
L_0001: newobj instance void ClassLibrary1.Class2::.ctor()
L_0006: stloc.0
L_0007: ldloc.0
L_0008: ldc.i4.2
L_0009: callvirt instance void ClassLibrary1.Class2::set_PropertyI(int32)
L_000e: nop
L_000f: ldarg.0
L_0010: ldarg.0
L_0011: ldloc.0
L_0012: call instance class ClassLibrary1.Class2 ClassLibrary1.Class1::MethodB(class ClassLibrary1.Class2)
L_0017: stfld class ClassLibrary1.Class2 ClassLibrary1.Class1::obj
L_001c: ret
}
.method public hidebysig instance class ClassLibrary1.Class2 MethodB(class ClassLibrary1.Class2 class2) cil managed
{
.maxstack 1
.locals init (
[0] class ClassLibrary1.Class2 CS$1$0000)
L_0000: nop
L_0001: ldarg.1
L_0002: stloc.0
L_0003: br.s L_0005
L_0005: ldloc.0
L_0006: ret
}
我的问题如下:
nop
和L_0006
之间没有L_0007
代码?
L_0001
到L_0006
与L_0007
到L_0009
不同,为什么没有nop
操作码?L_0003
?答案 0 :(得分:9)
C#编译器在大括号中发出NOP指令。这使得 lot 更容易在代码中设置断点。调试器只允许在代码上设置断点,大括号通常不会产生任何代码。所以这只是一个简单的调试辅助工具,这些NOP不会在发布版本中生成。
BR.S指令是编译器中的一个小缺陷,它没有peephole optimizer来摆脱这些无关的指令。通常,优化代码不是C#编译器的工作,而是由the jitter完成的。这将轻松轻松地删除指令。
答案 1 :(得分:1)
您看到的所有内容都是因为您正在调试模式下进行编译。冗余跳转和nops是禁用的优化传递以及调试支持(我相信)。
在发布模式下编译。