c# - 使用 IL 将 ref 分配给字段是否合法?

标签 c# clr reflection.emit

据我所知,没有办法与表达式树中的引用类型进行交互。 (例如,没有任何东西发出 stind.*ldind.* 操作码)。 我正在研究一些重写器来解决这个烦恼。由于我正在构建一个新类型,该类型的方法主体已替换为委托(delegate)调用(以解决 CompileToMethod 只能执行无法与新成员交互的静态方法这一事实)。对于 by-ref 和 out 参数,我想我会将它们的用法替换为 StrongBox<T> .

因此,如果我遇到一个具有如下签名的方法::

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

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

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 的设置时会容易得多, 如果我能做类似 &box.Value = &arg2 的事情即按原样将其地址分配给 arg2 的地址。这样,当委托(delegate)对值字段执行更改时,就会转发更改。这样做意味着我不需要有一个变量来保存返回值,也不需要执行引用值更新。

或者,如果有一种方法可以使用表达式树执行按引用分配的语义,我当然会洗耳恭听。

最佳答案

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

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

关于c# - 使用 IL 将 ref 分配给字段是否合法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4368434/

相关文章:

c# - Windows 10 Slite不起作用

c# - CIL中函数调用的参数是如何传递的?

c# - 如何在 C#/IL 中改变盒装值类型(原始或结构)

c# - Paypal电子商务网站如何处理多种货币?

c# - 有没有办法将 appsettings 转换为 env. ASP.NET Core 应用程序中的变量?

c# - 如何将完整的 C# 项目转换为 vb.net?

SQL CLR 存储过程输出

c# - 执行栈和线程的栈和局部变量列表是否引用不同的栈?

c# - 有没有办法从 IL 代码中获取 “reflect” ILGenerator.Emit 命令?

c# - DynamicAssembly 中的数组边界检查仅在计算堆栈为空时才有效