LambdaExpression.Compile和Delegate.CreateDelegate之间的区别

时间:2017-04-06 15:31:39

标签: c# .net lambda delegates

在优化反射调用的过程中,我尝试使用Delegate.CreateDelegateLambdaExpression.CompileMethodInfo转换为更快的代理。

基于this question,我期望LambdaExpression.Compile执行得更好,因为它会为方法调用生成实际的MSIL - 某处接近直接方法调用。

然而,在基准测试之后,我注意到这两种技术的性能大致相同。

我的假设是,在调用使用LambdaExpression.Compile创建的委托时,我得到的开销是由于代理本身的使用。为了确认,我创建了另一个基准测试,我在其中手动创建了直接调用该方法的委托,并且它具有类似的性能。

因此,我的问题是:LambdaExpression.CompileDelegate.CreateDelegate生成的委托对象有什么不同吗?

我正在寻找关于两种方法之间差异的理论答案,所以我不想进入实施细节,但这是实施的主旨:

1 个答案:

答案 0 :(得分:2)

Delegate.CreateDelegate和LambdaExpression.Compile之间存在差异,实际上第二种做法更多,并且在特定条件下可以更有效。

当您手动调用Delegate.CreateDelegate时,您可以使用目标值的某些重载调用它,但在某些情况下,如静态方法,您没有目标值。

在没有目标值的后台中,使用生成的方法创建委托,以便在跳转到实际方法之前在堆栈中弹出无用值。你可以用观察者观察它:委托有InPtr& InPtrAux

当IntPtrAux被分配给有效指针时,这意味着之前调用InPtr来弹出句柄并跳转到IntPtrAux。这就是为什么委托给一个实例方法的委托(句柄是“this”)比静态方法的委托更有效。

在lambda表达式编译生成委托时,始终使用Target(用于闭包)并避免通过IntPtrAux调用/跳转,并且通常是有效的。