繁体   English   中英

编译器如何知道它需要返回表达式树?

[英]How does compiler know it needs to return an expression tree?

当遇到分配给表达式<Func <T >>的lambda时,是否将其硬编码到编译器中以返回表达式树?

表达式<Func <int,int >> exp = n => n;

根据C#规范(6.1.12):

匿名函数和方法组本身没有类型,但是可以隐式转换为委托类型或表达式树类型。

因此,匿名函数(lambda)本身没有类型,但是当您将其分配给Expression类型的变量(或传递给需要Expression参数的函数)时,它会隐式转换为它(假设有可能-并非每个匿名函数都可以)可以转换为表达式树)。 与委托的故事相同-如果将其传递给需要Func<int,int>函数或将其分配给此类变量-它将成为委托而不是表达式树。

因为lambda被分配给Expression

是的,在C#5规范文档的4.6节“表达式树类型”中

4.6表达式树类型
表达式树允许将lambda表达式表示为数据结构而不是可执行代码。 表达式树是System.Linq.Expressions.Expression<D>形式的表达式树类型的值,其中D是任何委托类型。 在本规范的其余部分中,我们将使用速写Expression<D>引用这些类型。 如果存在从lambda表达式到委托类型D的转换,则也存在到表达式树类型Expression<D> 将lambda表达式转换为委托类型会生成引用了lambda表达式的可执行代码的委托,而转换为表达式树类型则会创建lambda表达式的表达式树表示形式。 表达式树是lambda表达式的有效内存数据表示形式,并使lambda表达式的结构透明且显式。 就像委托类型D一样, Expression<D>具有参数和返回类型,与D相同。以下示例将lambda表达式表示为可执行代码和表达式树。 因为存在到Func<int,int>的转换,所以也存在到Expression<Func<int,int>>

 Func<int,int> del = x => x + 1; // Code Expression<Func<int,int>> exp = x => x + 1; // Data 

完成这些分配后,委托del引用返回x + 1的方法,表达式树exp引用描述表达式x => x + 1的数据结构。 泛型类型Expression的确切定义以及将lambda表达式转换为表达式树类型时构造表达式树的精确规则,均不在本规范的范围之内。 明确两点很重要:

  • 并非所有的lambda表达式都可以转换为表达式树。 例如,无法表示带有语句主体的lambda表达式,以及包含赋值表达式的lambda表达式。 在这些情况下,转换仍然存在,但将在编译时失败。 这些例外在6.5节中有详细说明。
  • Expression提供了一个实例方法Compile,该方法生成D类型的委托:

    Func<int,int> del2 = exp.Compile();

调用此委托会使表达式树表示的代码得以执行。 因此,鉴于上述定义,del和del2是等效的,并且以下两个语句将具有相同的效果:

 int i1 = del(1); int i2 = del2(1); 

执行此代码后,i1和i2都将具有值2。

来自msdn;

当将lambda表达式分配给Expression类型的变量时,编译器将发出代码以构建表示lambda表达式的表达式树。

https://msdn.microsoft.com/en-us/library/mt654263.aspx

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM