编译lambda表达式会导致委托使用Closure参数

当我使用Expression.Lambda( ... ).Compile()来从表达式树创建委托时,结果是一个委托,其第一个参数是Closure

 public static Func CreateTest() { ParameterExpression a = Expression.Parameter( typeof( T ) ); ParameterExpression b = Expression.Parameter( typeof( T ) ); Expression addition = Expression.Add( a, b ); return (Func)Expression.Lambda( addition, a, b ).Compile(); } ... // 'addition' equals // Int32 lambda_method( // System.Runtime.CompilerServices.Closure, // Int32, // Int32 ) Func addition = DelegateHelper.CreateTest(); int result = addition( 5, 5 ); 

我可以通过普通代码轻松调用委托而不传递Closure对象,但是这个Closure来自哪里?

如何动态调用此委托?

 // The following does not work. // Exception: MethodInfo must be a runtime MethodInfo object. MethodInfo additionMethod = addition.Method; int result = (int)additionMethod.Invoke( null, new object[] { 5, 5 } ); 

使用表达式树看起来我必须传递Closure对象。

 PropertyInfo methodProperty = typeof( Delegate ).GetProperty( "Method", typeof( MethodInfo ) ); MemberExpression getDelegateMethod = Expression.Property( Expression.Constant( addition ), methodProperty ); Func getMethodInfo = (Func)Expression.Lambda( getDelegateMethod ).Compile(); // Incorrect number of arguments supplied for call to method // 'Int32 lambda_method(System.Runtime.CompilerServices.Closure, Int32, Int32)' Expression call = Expression.Call( getMethodInfo(), Expression.Constant( 5 ), Expression.Constant( 5 ) ); 

这是一个简单的例子,它本身没有意义。 我实际上想要实现的是能够用Func<Action>包装例如Func<Action> Func<Action> 。 我已经可以为非嵌套代理执行此操作。 这在reflection过程中非常有用, 如此处所述 。

我应该如何正确初始化此Closure对象,或者如何防止它出现在那里?

您看到的Closure类型是一个实现细节。 MSDN非常清楚:

此API支持.NET Framework基础结构,不能直接在您的代码中使用。 表示动态生成的方法的运行时状态。

表达式树可以具有状态。

Closure实例将包含lambda表达式关闭的所有非文字常量。 它还可以包含表达式树中嵌套lambda的委托链。

为实现这一点,表达式树编译器使用了一个可爱的小技巧。 它使用DynamicMethod生成内存代码,根据定义静态。 然而,他们正在创建一个“关闭其第一个论点”的代表 。 这意味着CLR将传递委托的目标字段作为静态方法的第一个参数,因此您不必这样做。 有效地隐藏了您的Closure参数。

解决问题的方法很简单,不要尝试调用方法,调用委托,或者在使用reflection时使用Delegate.DynamicInvoke ,或者在表达式树的上下文中使用Expression.Invoke 。