C# 动态方法、表达式树和DLR

C# 动态方法、表达式树和DLR,c#,.net-4.0,expression-trees,dynamic-language-runtime,C#,.net 4.0,Expression Trees,Dynamic Language Runtime,我对DynamicMethods、表达式树和DLR之间的相互作用和关系有一些疑问 我知道LambdaExpression.Compile在内部使用ILGenerator创建委托。然而,编译后的LambdaExpression和DynamicMethod之间存在一些基本的区别。比如说 a。DynamicMethods调用速度更快 b。编译的lambdaexpression可以嵌入闭包(非原语值的constantexpression) b。编译的lambdaexpression没有Declaring

我对DynamicMethods、表达式树和DLR之间的相互作用和关系有一些疑问

  • 我知道LambdaExpression.Compile在内部使用ILGenerator创建委托。然而,编译后的LambdaExpression和DynamicMethod之间存在一些基本的区别。比如说

    a。DynamicMethods调用速度更快

    b。编译的lambdaexpression可以嵌入闭包(非原语值的constantexpression)

    b。编译的lambdaexpression没有DeclaringType

    问题:

    a。为什么DynamicMethods比编译的LambdaExpressions调用更快

    b。允许闭包的已编译lambdaexpression有什么特殊之处?当我使用非常量表达式时,表达式树是否实际生成了闭包类?如果是这样的话,这个生成的类会去哪里

    c。编译的lambdaexpression(在运行时)去哪里?对它们的支持在哪里实施。它不可能只是反射。发射,可以吗

  • 我知道dynamic关键字实际上只是一种编译器技巧,用于发出CSharp调用站点、绑定等。据我所知,它们在内部生成表达式树,并使用精简版的C#编译器

    问题

    a。生成的表达式树通常是CallSiteBinder的函数,还是它们在Microsoft.CSharp dll中的具体实现和用法

    b。这些表达式树是由DynamicExpression节点组成的吗?还是别的什么?如果是别的,为什么

    c。C#编译器的精简版在哪里发挥作用,为什么发挥作用?它与LambdaExpression.Compile或DynamicMethods或任何类型的IL生成的常规调用有何不同?我可以理解如何使用CallSiteBinder构建表达式树,但为什么在转换发生后需要C编译器呢?一旦它以表达式树的形式出现(这只是一个API),C#与它有什么关系呢


  • 嗯,我不能回答你所有的问题,但我可以回答其中一些问题,我想这可能回答了你大部分的问题。也许至少它会给你足够的信息继续研究

    为什么DynamicMethods比编译的LambdaExpressions调用更快

    我不认为他们是,也许你测量错了,这是一个JIT'ing差异

    允许闭包的已编译lambdaexpression有什么特殊之处?当我使用非常量表达式时,表达式树是否实际生成了闭包类?如果是这样的话,这个生成的类会去哪里

    这个我不确定。我假设Expression.Constant可以包含引用类型,那么这不是问题,但是如果它确实只能有值类型,那么我猜编译器将生成一个表达式,其中在闭包中捕获的变量只是作为参数传入

    编译的lambdaexpression(在运行时)去哪里?对它们的支持在哪里实施。它不可能只是反射。发射,可以吗

    System.Linq.Expressions
    实际上只是反射之上的一个更友好的API。Emit,因此它们就像反射一样存储在内存中。Emit是默认的(尽管使用反射。Emit,我相信您可以保存发出的代码)

    生成的表达式树通常是CallSiteBinder的函数,还是它们在Microsoft.CSharp dll中的具体实现和用法

    我只做了一点System.Dynamic的工作,所以我无法回答这个问题,但据我所知,CallSiteBinder只是缓存和调用表达式,而将实际生成的内容传递给其他内容(例如DynamicObject)。但再一次,你可能比我知道的更多

    这些表达式树是由DynamicExpression节点组成的吗?还是别的什么?如果是别的,为什么

    不,dynamic仍然与.net中的所有内容一样受相同规则的约束。Dynamic只是说“在运行时,当我执行x时,尝试构建我通常编写并执行的代码。”类似于
    DynamicObject
    的东西只是构建一个简单的旧表达式树,Dynamic object只是为您提供一些元数据,以便您实际上可以构建该树(如返回类型、访问类型、名称等)

    C#编译器的精简版本在何处以及为什么发挥作用?为什么它与对LambdaExpression.Compile或DynamicMethods或任何类型的IL生成的常规调用有什么不同?我可以理解如何使用CallSiteBinder构建表达式树,但为什么在转换发生后需要C#编译器一旦它以表达式树的形式出现(这只是一个API),那么C#与它有什么关系呢

    我不知道你所说的精简编译器是什么意思,也不知道运行时在生成IL代码时实际做了什么(我想这就是你在这里所追求的),所以我想我无法回答这个问题


    但是,我要说的是,就像我之前说过的那样:
    系统.Linq.Expression
    东西实际上只是Reflection.Emit之上的一个友好API。表达式树就是它需要的信息,它需要进入Reflection.Emit,生成一个动态方法,然后返回给您。

    我对
    动态
    了解不多,所以我要去一个只回答你问题的第一部分

    为什么DynamicMethods比编译的LambdaExpressions调用更快

    如果是,我会非常惊讶,因为
    Expression.Compile()
    内部使用
    DynamicMethod

    允许闭包的已编译lambdaexpression有什么特别之处?当我使用非ConstantExpression时,表达式树是否实际生成闭包类?如果是,生成的类将去哪里

    这很容易验证。只需查看