在 IL Emit 中将对象添加到循环列表 - 公共语言运行时检测到无效程序
Add objects to list in loop in IL Emit - Common Language Runtime detected an invalid program
以下是我的C#代码:
List<int> list = new List<int>();
for(int Count = 0; Count < 5; Count++)
list.Add(Count);
return list;
我对应的发射代码如下:
LocalBuilder list = ILout.DeclareLocal(typeof(List<int>));
LocalBuilder Count = ILout.DeclareLocal(typeof(int));
LocalBuilder CmpRes = ILout.DeclareLocal(typeof(bool));
ConstructorInfo DictConstrctor = typeof(List<int>).GetConstructor(new Type[] { });
MethodInfo methodinfo_add = typeof(List<int>).GetMethod("Add", new[] { typeof(int) });
Label IL_001C = ILout.DefineLabel();
Label IL_000B = ILout.DefineLabel();
ILout.Emit(OpCodes.Newobj, DictConstrctor);
ILout.Emit(OpCodes.Stloc_0, list);
ILout.Emit(OpCodes.Ldc_I4_0);
ILout.Emit(OpCodes.Stloc_1, Count);
ILout.Emit(OpCodes.Br_S, IL_001C);
ILout.MarkLabel(IL_000B);
ILout.Emit(OpCodes.Ldloc_0, list);
ILout.Emit(OpCodes.Ldloc_1, Count);
ILout.Emit(OpCodes.Call, methodinfo_add);
ILout.Emit(OpCodes.Ldloc_1, Count);
ILout.Emit(OpCodes.Ldc_I4_1);
ILout.Emit(OpCodes.Add);
ILout.Emit(OpCodes.Stloc_1, Count);
ILout.MarkLabel(IL_001C);
ILout.Emit(OpCodes.Ldloc_1, Count);
ILout.Emit(OpCodes.Ldc_I4_2);
ILout.Emit(OpCodes.Clt);
ILout.Emit(OpCodes.Stloc_3, CmpRes);
ILout.Emit(OpCodes.Ldloc_3, CmpRes);
ILout.Emit(OpCodes.Brtrue_S, IL_000B);
ILout.Emit(OpCodes.Ldloc_0, list);
ILout.Emit(OpCodes.Ret);
它正在抛出异常 - "Common Language Runtime detected an invalid program."。
我这里做错了什么?
感谢任何帮助。
ILout.Emit(OpCodes.Stloc_1, Count);
和
ILout.Emit(OpCodes.Ldloc_1, Count);
没有意义。如果您明确表示 "use local 1"
,则不需要其他参数
同样:
ILout.Emit(OpCodes.Stloc_3, CmpRes);
ILout.Emit(OpCodes.Ldloc_3, CmpRes);
尽管坦率地说,我不确定 CmpRes
是否有任何用处;没有意义的存储和加载 - 只需将其留在堆栈上
注意:如果Count
是"local 1",那么CmpRes
就是"local 2";没有 "local 3",所以 Stloc_3
和 Ldloc_3
格式不正确。
这里又是:
ILout.Emit(OpCodes.Ldloc_0, list);
ILout.Emit(OpCodes.Ldloc_1, Count);
--
接下来我们开始通话;您正在进行静态调用:
ILout.Emit(OpCodes.Call, methodinfo_add);
但那是对象的实例方法,所以应该是虚拟调用。
这里又是一个本地人的失误:
ILout.Emit(OpCodes.Ldloc_1, Count);
这里:
ILout.Emit(OpCodes.Stloc_1, Count);
这里:
ILout.Emit(OpCodes.Ldloc_0, list);
但是,我也严重怀疑这个循环(即使是固定的)是否按照您的预期进行 - 如果我没看错的话,它实际上是:
var list = new List<int>();
for(int i [= 0] ; i < 2 ; i++) // note the 0 here implicit not explicit
{
list.Add(i);
}
return list;
以下是我的C#代码:
List<int> list = new List<int>();
for(int Count = 0; Count < 5; Count++)
list.Add(Count);
return list;
我对应的发射代码如下:
LocalBuilder list = ILout.DeclareLocal(typeof(List<int>));
LocalBuilder Count = ILout.DeclareLocal(typeof(int));
LocalBuilder CmpRes = ILout.DeclareLocal(typeof(bool));
ConstructorInfo DictConstrctor = typeof(List<int>).GetConstructor(new Type[] { });
MethodInfo methodinfo_add = typeof(List<int>).GetMethod("Add", new[] { typeof(int) });
Label IL_001C = ILout.DefineLabel();
Label IL_000B = ILout.DefineLabel();
ILout.Emit(OpCodes.Newobj, DictConstrctor);
ILout.Emit(OpCodes.Stloc_0, list);
ILout.Emit(OpCodes.Ldc_I4_0);
ILout.Emit(OpCodes.Stloc_1, Count);
ILout.Emit(OpCodes.Br_S, IL_001C);
ILout.MarkLabel(IL_000B);
ILout.Emit(OpCodes.Ldloc_0, list);
ILout.Emit(OpCodes.Ldloc_1, Count);
ILout.Emit(OpCodes.Call, methodinfo_add);
ILout.Emit(OpCodes.Ldloc_1, Count);
ILout.Emit(OpCodes.Ldc_I4_1);
ILout.Emit(OpCodes.Add);
ILout.Emit(OpCodes.Stloc_1, Count);
ILout.MarkLabel(IL_001C);
ILout.Emit(OpCodes.Ldloc_1, Count);
ILout.Emit(OpCodes.Ldc_I4_2);
ILout.Emit(OpCodes.Clt);
ILout.Emit(OpCodes.Stloc_3, CmpRes);
ILout.Emit(OpCodes.Ldloc_3, CmpRes);
ILout.Emit(OpCodes.Brtrue_S, IL_000B);
ILout.Emit(OpCodes.Ldloc_0, list);
ILout.Emit(OpCodes.Ret);
它正在抛出异常 - "Common Language Runtime detected an invalid program."。
我这里做错了什么? 感谢任何帮助。
ILout.Emit(OpCodes.Stloc_1, Count);
和
ILout.Emit(OpCodes.Ldloc_1, Count);
没有意义。如果您明确表示 "use local 1"
,则不需要其他参数同样:
ILout.Emit(OpCodes.Stloc_3, CmpRes);
ILout.Emit(OpCodes.Ldloc_3, CmpRes);
尽管坦率地说,我不确定 CmpRes
是否有任何用处;没有意义的存储和加载 - 只需将其留在堆栈上
注意:如果Count
是"local 1",那么CmpRes
就是"local 2";没有 "local 3",所以 Stloc_3
和 Ldloc_3
格式不正确。
这里又是:
ILout.Emit(OpCodes.Ldloc_0, list);
ILout.Emit(OpCodes.Ldloc_1, Count);
--
接下来我们开始通话;您正在进行静态调用:
ILout.Emit(OpCodes.Call, methodinfo_add);
但那是对象的实例方法,所以应该是虚拟调用。
这里又是一个本地人的失误:
ILout.Emit(OpCodes.Ldloc_1, Count);
这里:
ILout.Emit(OpCodes.Stloc_1, Count);
这里:
ILout.Emit(OpCodes.Ldloc_0, list);
但是,我也严重怀疑这个循环(即使是固定的)是否按照您的预期进行 - 如果我没看错的话,它实际上是:
var list = new List<int>();
for(int i [= 0] ; i < 2 ; i++) // note the 0 here implicit not explicit
{
list.Add(i);
}
return list;