我试图使用.NET中的反射和发射生成一个动态程序集。我得到了一个错误,“公共语言运行时检测到一个无效的程序。”我创建了另一个程序,它具有我希望使用硬编码类型的功能。我试图编写的功能最终将使用动态类型,但我可以使用ILDasm查看我需要生成的IL。我将生成的IL与编译器生成的IL进行比较。在我看到的一个方法的.locals init声明中,编译器生成的代码中有一个额外的项,
编译器生成的:
.locals init ([0] class [System.Core]System.Linq.Expressions.ParameterExpression CS$0$0000,
[1] class [System.Core]System.Linq.Expressions.ParameterExpression[] CS$0$0001)我的:
.locals init (class [System.Core]System.Linq.Expressions.ParameterExpression V_0,
class [System.Core]System.Linq.Expressions.ParameterExpression[] V_1)我不明白编译器生成的代码中"1“和”1“的重要性。有人能告诉我这是什么意思吗?
作为一个更普遍的问题,我可以在没有太多麻烦的情况下跟踪大多数ILDasm输出。但我经常遇到一个有问题的表达。例如,在ILDasm中的这一行
callvirt instance class [EntityFramework]System.Data.Entity.ModelConfiguration.EntityTypeConfiguration`1<!!0> [EntityFramework]System.Data.Entity.DbModelBuilder::Entity<class DynamicEdmxTrial.HardFooAsset>()"!!0“可能指的是Entity<>的泛型类型,但我不确定,我不知道ILDasm输出是否有一个键可以向我解释其更模糊的输出。
发布于 2013-09-23 18:34:14
该规范是免费提供的这里。这需要一些习惯,但大多数细节是很容易找到的,一旦你知道了结构。
!!列在二.7.1类型中
键入::= \ Description \ Clause‘!’Int32 _Int32 _
换句话说,在C#将调用f<T, U>()的方法中,!!0为T,!!1为U。
然而,[0]是一个很好的问题。规范似乎没有解决这个问题。.locals指令在is .15.4.1.3中描述了.locals指令,该指令列出了如下语法
MethodBodyItem ::= .\x{e76f} .locals init‘(’LocalsSignature‘)’LocalsSignature ::= Local‘,’Local *Local::= Type Id‘
似乎没有任何东西允许[0]存在,除非它是Type的一部分,而且Type也不允许以[开头的任何东西。我的猜测是,这是Microsoft实现特有的一个无文档化的特性,目的是帮助人类读者了解位置0是局部变量CS$0$0000,以便生成的指令按索引访问局部变量。
对ILAsm的实验表明,这正是它的含义。使用一个简单的C#程序:
static class Program {
static void Main() {
int i = 0, j = 1;
}
}编译然后拆卸它(csc test.cs && ildasm /text test.exe >test.il)显示:
....
.locals init (int32 V_0,
int32 V_1)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: ldc.i4.1
IL_0004: stloc.1
IL_0005: ret
....将.locals修改为
.locals init ([0] int32 V_0, [0] int32 V_1)给出一个有用的警告消息:
test.il(41) : warning : Local var slot 0 is in use事实上,声明不同类型的变量,然后使用[2]、[1]、[0]对它们进行重新排序,组装并立即拆解结果,表明变量被重新排序了。
https://stackoverflow.com/questions/18965440
复制相似问题