Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么存储局部变量并将其读回会触发TargetInvestment异常?_C#_.net_Reflection_Cil_Reflection.emit - Fatal编程技术网

C# 为什么存储局部变量并将其读回会触发TargetInvestment异常?

C# 为什么存储局部变量并将其读回会触发TargetInvestment异常?,c#,.net,reflection,cil,reflection.emit,C#,.net,Reflection,Cil,Reflection.emit,假设我有这个方法: MethodBuilder doubleMethod = typeBuilder.DefineMethod("Double", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new [

假设我有这个方法:

MethodBuilder doubleMethod = typeBuilder.DefineMethod("Double", 
                                                     MethodAttributes.Public | MethodAttributes.Static,
                                                     typeof(int), new [] { typeof(int) });
ILGenerator il = countMethod.GetILGenerator();

il.Emit(OpCodes.Ldarg_0);  // We load the input argument (an int) into the evaluation stack
il.Emit(OpCodes.Ldc_I4_2); // We load the integer 2 into the evaluation stack
il.Emit(OpCodes.Mul);      // We multiply both numbers (n * 2)
il.Emit(OpCodes.Ret);      // We return what is left on the evaluation stack, i.e. the result of the multiplication
我可以成功调用此方法:

Type type = typeBuilder.CreateType();
MethodInfo method = type.GetMethod("Double");
object result = method.Invoke(null, new object[] { 4 }); // result = 8
但是,如果我将IL代码更改为:

il.Emit(OpCodes.Ldarg_0);  // We load the input argument (an int) into the evaluation stack
il.Emit(OpCodes.Ldc_I4_2); // We load the integer 2 into the evaluation stack
il.Emit(OpCodes.Mul);      // We multiply both numbers (n * 2)

/* I added these two instructions */
il.Emit(OpCodes.Stloc_0);  // We pop the value from the evaluation stack and store into a local variable
il.Emit(OpCodes.Ldloc_0);  // We read that local variable and push it back into the evaluation stack

il.Emit(OpCodes.Ret);      // We return what is left on the evaluation stack, i.e. the result of the multiplication 
尝试调用生成的方法时,会引发以下异常:

TargetInvocationException未处理-调用的目标已引发异常


为什么会这样?我的意思是,从求值堆栈中弹出值,然后再次推送相同的值,这绝对没有任何作用。当它到达操作码.Ret时,正确的值应该在计算堆栈上。

要在IL中使用局部变量,首先需要声明它,以便运行时知道它的类型。要做到这一点,请使用

您也可以考虑何时发出使用变量的指令。这样,您就不需要记住所有局部变量的索引:

var local = il.DeclareLocal(typeof(int));

…

il.Emit(OpCodes.Stloc, local);
il.Emit(OpCodes.Ldloc, local);

在您深入了解这一点之前,首先要了解如何诊断TargetJournal异常。您必须查看InnerException以找出哪里出了问题。并使用ILGenerator.DeclareLocal(),这样它就可以正确地测量所需的堆栈大小。@HansPassant实际上,内部异常只是声明
“公共语言运行库检测到一个无效程序”
,我认为它太泛化了,找不到相关的,堆栈跟踪似乎也没有帮助。@HansPassant添加
il.DeclareLocal(typeof(int))
成功了!谢谢!您可以将其作为答案发布吗?(还有,为什么我需要调用此方法?)