【问题标题】:DynamicMethod and out-parameters?动态方法和输出参数?
【发布时间】:2009-08-18 08:58:42
【问题描述】:

如何为具有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); 线上。

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


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

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

【问题讨论】:

  • 真的需要创建动态方法吗?为什么不在一个可以配置为在运行时执行您想要的操作的类中实现该方法?
  • 它确实必须是一个动态方法,这是最后一站优化工作,以使基于反射的巨大调用树执行得更快。到目前为止,与现有代码相比,使用动态方法方法的开销似乎减少了大约 85%,而且这是每秒将被调用数千次的代码。测量表明,现有的反射代码占用了相当多的 cpu。

标签: c# dynamicmethod out-parameters


【解决方案1】:

out 参数只是一个 ref 参数,OutAttribute 应用于参数。

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

ldarg.0
ldnull
stind.ref

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-31
    • 1970-01-01
    • 2019-06-20
    • 1970-01-01
    • 2021-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多