表达式树:使用 out 或 ref 参数调用方法
Posted
技术标签:
【中文标题】表达式树:使用 out 或 ref 参数调用方法【英文标题】:Expression trees: invoking a method with out or ref arguments 【发布时间】: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”参数。谢谢马克。
【参考方案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() );
问候,
【讨论】:
以上是关于表达式树:使用 out 或 ref 参数调用方法的主要内容,如果未能解决你的问题,请参考以下文章