9

How do I define a DynamicMethod for a delegate that has an out-parameter, like this?

public delegate void TestDelegate(out Action a);

Let's say I simply want a method that sets the a argument to null when I call the method.

Note that I know that a probably better way to handle this would be to make the method return the Action delegate, but this is just a simplified part of a larger project, and the method in question already returns a value, I need to handle the out parameter in addition to it, hence the question.

I tried this:

using System;
using System.Text;
using System.Reflection.Emit;

namespace ConsoleApplication8
{
    public class Program
    {
        public delegate void TestDelegate(out Action a);

        static void Main(String[] args)
        {
            var method = new DynamicMethod("TestMethod", typeof(void),
                new Type[] { typeof(Action).MakeByRefType() });
            var il = method.GetILGenerator();

            // a = null;
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Starg, 0);

            // return
            il.Emit(OpCodes.Ret);

            var del = (TestDelegate)method.CreateDelegate(typeof(TestDelegate));
            Action a;
            del(out a);
        }
    }
}

However, I get this:

VerificationException was unhandled:
Operation could destabilize the runtime.

on the del(out a); line.

Note that if I comment out the two lines that load a null on the stack and attempts to store it into the argument, the method runs without exceptions.


Edit: Is this the best approach?

il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldnull);
il.Emit(OpCodes.Stind_Ref);
Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
  • Is it really needed to create a dynamic method? why not just implement the method in a class which can be configured to do what you want at runtime? – Stefan Steinegger Aug 18 '09 at 09:32
  • It really has to be a dynamic method, this is a last-stop optimization effort to get a huge reflection-based call-tree to execute faster. So far the overhead of using the dynamic method approach contra the existing code seems to be about 85% less, and this is code that will be called thousands of times each second. Measurements show that quite a lot of cpu is tied up in the existing reflection code. – Lasse V. Karlsen Aug 18 '09 at 09:37

1 Answers1

9

An out argument is just a ref argument with the OutAttribute applied to the parameter.

To store to the by-ref argument, you need to use the stind opcode, because the argument itself is a managed pointer to the object's actual location.

ldarg.0
ldnull
stind.ref
Sam Harwell
  • 97,721
  • 20
  • 209
  • 280