2011-09-07 158 views
4

在从相同的C#代码(但可能不同的编译器版本)生成的两个程序集上运行ILDASM后,我从每个相应的dll获得以下输出。这些CIL语句有什么区别?

.locals init (class MyClass/'<>c__DisplayClass3' V_0) 

.locals init ([0] class MyClass/'<>c__DisplayClass3' 'CS$<>8__locals4') 

是什么这两个语句之间的差异,具体是什么'[0]'符号的意义是什么?

回答

4

这两个语句在功能上是相同的。这种差异是由ILDASM在第二种情况下使用来自.pdb的数据引起的。当调试信息可用时,ILDASM包含变量名称和索引;否则会给它们通用名称并省略索引。

我只能推测索引是为了帮助您将任何ldloc.x指令与其变量名关联起来。

顺便说一句,明确提供可变折射率手工编辑MSIL时可能是有用的,因为它会阻止你犯了一个错误添加或删除当地人时:如果您稍后删除x没有

.locals init ([0] int32 x, 
       [1] int32 y, 
       [2] int32 z) 
ldloc.1 //load y 

检查你的方法并修复你的索引:

.locals init ([1] int32 y, //error -- Undefined type of local var slot 0 in method frob 
       [2] int32 z) 
ldloc.1 //oops, would have loaded z 
1

它被称为槽索引。该索引可用于引用适当的变量(与引用/按名称访问相同)。在第一个例子中,instanve将被V_0名称访问,第二个由0索引访问。

  • [0] - 插槽指数
  • class MyClass/'<>c__DisplayClass3' - 变量类型
  • 'CS$<>8__locals4' - 变量名

你有行代码一起宣布MyClass类型的多个变量,你刚才提到?

+0

为了澄清,IL是从包含在'MyClass'中的私有方法生成的。我相信'MyClass /'<> c__DisplayClass3''是为方法中定义的lambda函数生成的类的名称。我的主要兴趣是为什么这个特定的陈述与可能不同的编译器版本或操作系统环境有什么不同,以及它是否有任何意义。感谢您的回答。 –

+0

无论采用哪种方式,都需要使用'ldloc.0'将值压入堆栈。我不确定为什么ildasm认为它只有时才显示索引是有用的。 – zinglon