表达式树:使用out或ref参数调用方法

Jos*_*shL 5 .net expression-trees c#-4.0

此代码适用于.NET4:

class Program
{
    static void Main( string[] args )
    {
        var fooExpr = Expression.Parameter( typeof( Foo ), "f" );
        var parmExpr = Expression.Parameter( typeof( int ).MakeByRefType(), "i" );
        var method = typeof( Foo ).GetMethod( "Method1" );
        var invokeExpr = Expression.Call( fooExpr, method, parmExpr );
        var delegateType = MakeDelegateType( typeof( void ), new[] { typeof( Foo ), typeof( int ).MakeByRefType() } );
        var lambdaExpr = Expression.Lambda( delegateType, invokeExpr, fooExpr, parmExpr );
        dynamic func = lambdaExpr.Compile();
        int x = 4;
        func( new Foo(), ref x );
        Console.WriteLine( x );
    }

    private static Type MakeDelegateType( Type returnType, params Type[] parmTypes )
    {
        return Expression.GetDelegateType( parmTypes.Concat( new[] { returnType } ).ToArray() );
    }
}

class Foo
{
    public void Method1( ref int x )
    {
        x = 8;
    }
}
Run Code Online (Sandbox Code Playgroud)

此代码不会(在动态调用点上因运行时错误而爆炸):

class Program
{
    static void Main( string[] args )
    {
        var fooExpr = Expression.Parameter( typeof( Foo ), "f" );
        var parmExpr = Expression.Parameter( typeof( int ).MakeByRefType(), "i" );
        var method = typeof( Foo ).GetMethod( "Method1" );
        var invokeExpr = Expression.Call( fooExpr, method, parmExpr );
        var delegateType = MakeDelegateType( typeof( void ), new[] { typeof( Foo ), typeof( int ).MakeByRefType() } );
        var lambdaExpr = Expression.Lambda( delegateType, invokeExpr, fooExpr, parmExpr );
        dynamic func = lambdaExpr.Compile();
        int x = 4;
        func( new Foo(), out x );
        Console.WriteLine( x );
    }

    private static Type MakeDelegateType( Type returnType, params Type[] parmTypes )
    {
        return Expression.GetDelegateType( parmTypes.Concat( new[] { returnType } ).ToArray() );
    }
}

class Foo
{
    public void Method1( out int x )
    {
        x = 8;
    }
}
Run Code Online (Sandbox Code Playgroud)

怎么会?唯一的区别是使用ref与out参数.

wac*_*any -1

你尝试过改变吗

typeof(int).MakePointerType
Run Code Online (Sandbox Code Playgroud)

代替:

typeof( int ).MakeByRefType()
Run Code Online (Sandbox Code Playgroud)

在行:

var parmExpr = Expression.Parameter( typeof( int ).MakeByRefType(), "i" );
var delegateType = MakeDelegateType( typeof( void ), new[] { typeof( Foo ), typeof( int ).MakeByRefType() } );
Run Code Online (Sandbox Code Playgroud)

问候,