我对 DynamicMethods、表达式树和 DLR 之间的交互和关系有一些疑问。
我知道 LambdaExpression.Compile 在内部使用 ILGenerator 来创建委托(delegate)。但是,已编译的 LambdaExpression 和 DynamicMethod 之间存在一些根本差异。例如
一个。 DynamicMethods 调用更快
编译后的 LambdaExpressions 可以嵌入闭包(非原始值的 ConstantExpressions)
编译后的 LambdaExpressions 没有 DeclaringType。
问题:
一个。为什么 DynamicMethods 比编译的 LambdaExpressions 调用起来更快?
允许闭包的已编译 LambdaExpressions 有什么特别之处?当我使用非 ConstantExpression 时,表达式树是否真的生成了一个闭包类?如果是这样,这个生成的类去哪里了?
编译后的 LambdaExpressions 去哪里(在运行时)?对他们的支持在哪里实现。不能只是 Reflection.Emit 吧?
我知道 dynamic 关键字实际上只是一个编译器技巧,用于发出 CSharp CallSites、Binders 等。据我所知,在内部,这些生成表达式树并且还使用精简版的 C# 编译器。
问题
一个。生成的表达式树一般是 CallSiteBinders 的函数还是它们在 Microsoft.CSharp dll 中的具体实现和使用?
这些表达式树是由 DynamicExpression 节点组成的吗?或者是其他东西?如果还有其他原因,为什么?
C# 编译器的精简版本在哪里以及为何发挥作用?为什么以及它与对 LambdaExpression.Compile 或 DynamicMethods 或任何类型的 IL 生成的常规调用有何不同?我可以理解如何使用 CallSiteBinders 来构建表达式树,但为什么在发生转换后需要 C# 编译器?一旦它采用表达式树(这只是一个 API)的形式,C# 与它有什么关系。
最佳答案
我对dynamic
了解不多,所以我只回答你问题的第一部分。
Why are DynamicMethods faster to invoke than compiled LambdaExpressions?
如果它们是,我会感到非常惊讶,因为 Expression.Compile()
内部使用 DynamicMethod
。
What's special about compiled LambdaExpressions that allows for closures? Does the Expression Tree actually generate a closure class when I use a non ConstantExpression? And if so, where does this generated class go?
这很容易验证。只需查看通过编译表达式树生成的委托(delegate)的 Target
和 Method
。您会注意到 Target
(也是 Method
的第一个参数)是 System.Runtime.CompilerServices.Closure
.这是一个包含字段 object[] Constants
的类,它存储来自 ConstantExpression
的非原始值。
Where do compiled LambdaExpressions go (at runtime)? Where is the support for them implemented. It can't just be Reflection.Emit, can it?
正如我之前所说,Expression.Compile()
内部使用 DynamicMethod
。所以,是的,它只是 Reflection.Emit。
关于c# - 动态方法、表达式树和 DLR,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17801774/