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

时间:2017-04-07 21:12:20

标签: c# .net linq lambda

当它遇到分配给Expression< Func< T>>的lambda时,它是否被硬编码到编译器中以返回表达式树。像下面这样的东西?

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

4 个答案:

答案 0 :(得分:2)

来自C#规范(6.1.12):

  

匿名函数和方法组中没有类型   他们自己,但可能会隐式转换为委托类型或   表达式树类型。

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

答案 1 :(得分:1)

因为lambda被分配给{ name: 'GreenBay', value: '12' }

答案 2 :(得分:1)

是的,在第4.6节“表达式树类型”

中的C#5规范文档中
  

4.6表达式树类型
  表达式树允许将lambda表达式表示为数据结构而不是可执行文件   码。表达式树是表单的表达式树类型的值   System.Linq.Expressions.Expression<D>,其中D是任何委托类型。   对于本规范的其余部分,我们将参考这些类型   使用简写Expression<D>。如果转换存在于   lambda表达式为委托类型D,也存在转换   表达式树类型Expression<D>。而转换一个   lambda表达式为委托类型生成一个委托   引用lambda表达式的可执行代码,转换为   表达式树类型创建表达式树的表示形式   lambda表达式。表达式树是有效的内存数据   lambda表达式的表示形式和   lambda表达透明和显式。就像委托类型一样   D,Expression<D>据说有参数和返回类型   与D的相同。以下示例表示a   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。

答案 3 :(得分:0)

来自msdn;

将lambda表达式赋给Expression类型的变量时,编译器会发出代码来构建表示lambda表达式的表达式树。

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