这些CIL语句有何区别?

4
运行 ILDASM 在从相同的 C# 代码生成的两个程序集上(但可能是不同的编译器版本),我分别从每个 dll 中获得以下输出。
.locals init (class MyClass/'<>c__DisplayClass3' V_0)

并且

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

这两个语句有什么区别,特别是'[0]'符号的意义是什么?
2个回答

4
这两个语句在功能上是完全相同的。区别在于ILDASM在第二种情况下使用了来自.pdb文件的数据。当调试信息可用时,ILDASM将包括变量名和索引;否则,它会给它们一个通用名称并省略索引。
我只能猜测索引被包含是为了帮助您将任何ldloc.x指令与其变量名相关联。
顺便说一下,显式提供变量索引可能在手动编辑MSIL时很有用,因为它可以防止您在添加或删除本地变量时犯错误:
.locals init ([0] int32 x,
              [1] int32 y,
              [2] int32 z)
ldloc.1 //load y

如果您在没有检查方法并修复索引的情况下稍后删除了 x
.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

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

  • [0] - 槽索引
  • class MyClass/'<>c__DisplayClass3' - 变量类型
  • 'CS$<>8__locals4' - 变量名称

您是否声明了多个MyClass类型的变量以及您提到的代码行?


澄清一下,IL代码是从MyClass中包含的一个私有方法生成的。 我相信MyClass/'<>c__DisplayClass3'是为在该方法中定义的Lambda函数生成的类的名称。 我主要关注的是这个特定语句为什么在可能不同编译器版本或操作系统环境中不同,并且它是否具有任何影响。感谢您的回答。 - Andrew Marshall
无论如何,您都可以使用 ldloc.0 将值推送到堆栈上。我不确定为什么 ildasm 认为仅有时显示索引是有用的。 - zinglon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接