【问题标题】:Is it legal to assign by ref to a field using IL?通过 ref 分配给使用 IL 的字段是否合法?
【发布时间】:2011-05-21 02:03:41
【问题描述】:

据我所知,没有办法与表达式树中的引用类型进行交互。 (例如,什么都不会发出 stind.*ldind.* 操作码)。 我正在做一个重写器来解决这个烦恼。因为我正在构建一个新类型,它的方法体被委托调用替换(为了解决CompileToMethod 只能执行不能与新成员交互的静态方法的事实)。对于 by-ref 和 out 参数,我想我会用StrongBox<T> 替换它们的用法。

所以,如果我遇到一个签名看起来像这样的方法::

public class SomeClass
{
    public virtual bool SomeMethod(string arg1,ref int arg2)
    {
    }
}

我生成的覆盖、callbase 方法和委托字段将如下所示::

public class SomeClass<1> : SomeClass
{
     private static bool SomeMethod<0>(
             SomeClass target,string arg1,StrongBox<int> arg2)
     {
        return call target.SomeMethod(arg1,ref arg2.Value)
     }

     private Func<SomeClass,string,StrongBox<int>,bool> <0>SomeMethod;

    public override bool SomeMethod(string arg1,ref int arg2)
    {
        StrongBox<int> box = new StrongBox<int>();
        box.Value = arg2;
        bool retVal = <0>SomeMethod.Invoke(this,arg1,box);
        arg2 = box.Value;
        return retVal;
    }
}

然而,执行这种转换的代码相当多,对于每个参数它都会引入很多复杂性。当我执行box.Value = arg2 的设置时会容易得多,如果我可以执行&amp;box.Value = &amp;arg2 之类的操作,即按原样将其地址分配给arg2 的地址。这样,当委托对值字段执行突变时,就会转发更改。这样做意味着我不需要有一个变量来保存返回值,也不需要执行引用值更新。

另外,如果有一种方法可以使用表达式树执行按引用分配的语义,我当然会全神贯注。

【问题讨论】:

  • 这让我想起了 Eric Lippert 的Ref Class

标签: c# clr reflection.emit


【解决方案1】:

不确定我是否真的理解,但也许这是一个解决方案:

class Program
{

    public class SomeClass
    {
        private readonly int _n;

        public SomeClass(int n) { _n = n; }

        public virtual bool SomeMethod(string arg1, ref int arg2) {
            if (String.IsNullOrWhiteSpace(arg1)) return false;
            arg2 += arg1.Length + _n;
            return true;
        }
    }

    private delegate bool SomeDelegate(SomeClass that, string arg1, ref int arg2);

    static void Main(string[] args) {
        var instance = Expression.Parameter(typeof (SomeClass), "that");
        var arg1Param = Expression.Parameter(typeof(string), "arg1");
        var arg2Param = Expression.Parameter(typeof (int).MakeByRefType(), "arg2");
        var someMethodInfo = typeof (SomeClass).GetMethod("SomeMethod");
        var lambda = Expression.Lambda<SomeDelegate>(Expression.Call(instance, someMethodInfo, arg1Param, arg2Param), instance, arg1Param, arg2Param);
        var someDelegate =lambda.Compile();
        var myClass = new SomeClass(2);
        var arg1 = "yup";
        var arg2 = 1;
        var result = someDelegate(myClass, arg1, ref arg2);
        if(arg2 != 6) throw new Exception("Bad!");
        Console.WriteLine("works...");
    }

}

我认为重要的一点是typeof (int).MakeByRefType()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-28
    • 2022-10-18
    • 1970-01-01
    • 2020-04-11
    相关资源
    最近更新 更多