【问题标题】:Expression trees: invoking a method with out or ref arguments表达式树:使用 out 或 ref 参数调用方法
【发布时间】:2011-08-29 20:20:54
【问题描述】:

此代码适用于 .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;
    }
}

此代码不会(在动态调用站点出现运行时错误):

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;
    }
}

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

【问题讨论】:

  • 错误是:“委托 有一些无效参数”...没有更多细节,没有内部异常。
  • 出于好奇,如果您在呼叫站点使用ref 而不是out 会发生什么?另外,如果你用正确的out etc 签名声明一个委托类型,并尝试一个静态类型的编译 lambda,会发生什么?
  • 哇,奇怪...如果我在调用站点使用'ref'(并在方法声明中保留'out'),那就可以了。一个错误?编辑 - 再三考虑,不是错误。奇怪的是,没有明确的方法可以在动态构造的委托类型上创建“out”参数。谢谢马克。

标签: .net c#-4.0 expression-trees


【解决方案1】:

Ref 参数将由 CLR 管理,这是一个经典变量,如果这是一个值,它将只是 Box(封装到一个对象中以管理通过引用传递元素)。 p>

Out允许有多个输出,在编译过程中会产生更大的影响。

表达式在运行时编译,但“out”有效性在编译时检查。

通过有效性,我的意思是编译器确保方法 WILL ASSIGN 值给 out 参数。

【讨论】:

    【解决方案2】:

    你尝试过改变

    typeof(int).MakePointerType
    

    代替:

    typeof( int ).MakeByRefType()
    

    在行:

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

    问候,

    【讨论】:

      猜你喜欢
      • 2010-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-28
      • 1970-01-01
      • 2017-03-25
      • 1970-01-01
      • 2011-05-13
      相关资源
      最近更新 更多