DynamicMethod 和输出参数?

发布于 2024-08-02 14:12:11 字数 1448 浏览 14 评论 0原文

如何为具有 out 参数的委托定义 DynamicMethod,如下所示?

public delegate void TestDelegate(out Action a);

假设我只是想要一个在调用该方法时将 a 参数设置为 null 的方法。

请注意,我知道处理此问题的更好方法可能是使该方法返回 Action 委托,但这只是较大项目的简化部分,并且相关方法已经返回值,除了它之外,我还需要处理 out 参数,因此出现了问题。

我尝试了这个:

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);
        }
    }
}

但是,我得到了这个:

VerificationException was unhandled:
Operation could destabilize the runtime.

del(out a); 行。

请注意,如果我注释掉在堆栈上加载 null 的两行并尝试将其存储到参数中,则该方法将毫无异常地运行。


编辑:这是最好的方法吗?

il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldnull);
il.Emit(OpCodes.Stind_Ref);

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);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

岁月如刀 2024-08-09 14:12:11

out 参数只是一个带有 OutAttribute 应用于参数。

要存储到 by-ref 参数,您需要使用 stind 操作码,因为参数本身是指向对象实际位置的托管指针。

ldarg.0
ldnull
stind.ref

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文