Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用IL通过ref指定字段是否合法?_C#_Clr_Reflection.emit - Fatal编程技术网

C# 使用IL通过ref指定字段是否合法?

C# 使用IL通过ref指定字段是否合法?,c#,clr,reflection.emit,C#,Clr,Reflection.emit,据我所知,在表达式树中没有与引用类型交互的方法。(例如,任何东西都不会发出stind.*或ldind.*操作码)。 我正在编写一个重写程序来避开这个麻烦。因为我正在构建一个新类型,它将方法体替换为委托调用(以避免CompileToMethod只能执行不能与新成员交互的静态方法)。对于by-ref和out参数,我认为应该用StrongBox替换它们的用法 因此,如果我遇到一个签名如下的方法: public class SomeClass { public virtual bool Some

据我所知,在表达式树中没有与引用类型交互的方法。(例如,任何东西都不会发出
stind.*
ldind.*
操作码)。 我正在编写一个重写程序来避开这个麻烦。因为我正在构建一个新类型,它将方法体替换为委托调用(以避免
CompileToMethod
只能执行不能与新成员交互的静态方法)。对于by-ref和out参数,我认为应该用
StrongBox
替换它们的用法

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

public class SomeClass
{
    public virtual bool SomeMethod(string arg1,ref int arg2)
    {
    }
}
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;
    }
}
我生成的覆盖、callbase方法和委托字段如下所示:

public class SomeClass
{
    public virtual bool SomeMethod(string arg1,ref int arg2)
    {
    }
}
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;
    }
}
公共类SomeClass:SomeClass
{
私有静态布尔方法(
SomeClass目标,字符串arg1,保险箱arg2)
{
返回调用target.SomeMethod(arg1,ref arg2.Value)
}
私有函数方法;
公共重写bool SomeMethod(字符串arg1,ref int arg2)
{
strong框=新的strong框();
box.Value=arg2;
bool retVal=SomeMethod.Invoke(this,arg1,box);
arg2=box.Value;
返回返回;
}
}
然而,执行这种转换需要大量代码,因为每个参数都会带来很多复杂性。如果我可以像
&box.Value=&arg2
那样将其地址分配给arg2的地址,那么在执行
box.Value=arg2
的设置时会容易得多。这样,当委托在值字段上执行变异时,更改将被转发。这样做意味着我不需要有一个变量来保存返回值,也不需要执行参考值更新


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

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

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

}
类程序
{
公共类
{
私有只读int;
公共类(int n){u n=n;}
公共虚拟布尔方法(字符串arg1,引用int arg2){
if(String.IsNullOrWhiteSpace(arg1))返回false;
arg2+=arg1.长度+\n;
返回true;
}
}
私有委托bool SomeDelegate(SomeClass,字符串arg1,ref int arg2);
静态void Main(字符串[]参数){
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(Expression.Call(instance,someMethodInfo,arg1Param,arg2Param),instance,arg1Param,arg2Param);
var someDelegate=lambda.Compile();
var myClass=新的SomeClass(2);
var arg1=“是”;
var arg2=1;
var result=someDelegate(myClass,arg1,ref arg2);
如果(arg2!=6)抛出新异常(“坏!”);
控制台。WriteLine(“工作…”);
}
}

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

这让我想起了Eric Lippert的。