Let's suppose I have this method:
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
I can call this method successfully:
Type type = typeBuilder.CreateType();
MethodInfo method = type.GetMethod("Double");
object result = method.Invoke(null, new object[] { 4 }); // result = 8
However, If I change my IL code to this:
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
When trying to call the generated method, the following exception is thrown:
TargetInvocationException was unhandled - Exception has been thrown by the target of an invocation.
Why is this? I mean, popping the value from the evaluation stack and then pushing the same value again should do absoultely nothing. By the time it reaches OpCodes.Ret
, the correct value should be on the evaluation stack.
Aucun commentaire:
Enregistrer un commentaire