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

问题描述:

难道是硬编码到编译器,当它遇到分配给表达< Func键<牛逼> >像下面一个lambda返回一个表达式树?编译器如何知道它需要返回表达式树?

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

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

4.6的表达式树类型
表达式树允许在lambda表达式被表示为数据结构代码可执行 代码。表达式树是 System.Linq.Expressions.Expression<D>形式的表达式树类型的值,其中D是任何委托类型。 对于本规范的其余部分,我们将使用简写Expression<D>来引用这些类型 。如果存在从 lambda表达式到代表类型D的转换,则转换也存在 表达式树型Expression<D>。虽然将 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 

按照这些任务,委托删除引用 回报的方法x + 1,和表达式树EXP引用一个数据 结构描述表达式x => x + 1。通用类型Expression的精确 定义以及精确的 规则当lambda表达式被转换为表达式树类型时构建表达式树都不在本规范的 的范围之内。有两件事是重要的,以明确:

  • 并非所有的lambda表达式都可以转换为表达式树。例如,带有语句正文的lambda表达式和包含赋值表达式的表达式不能表示。在 这些情况下,转换依然存在,但在编译时会失败。 这些例外情况在§6.5中有详细说明。
  • 表达提供了一个实例方法编译产生类型d的代表:

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

调用此委托使由表达式 树表示的代码将被执行。因此,鉴于上文的定义,删除和DEL2 是等效的,并且下面的两个语句将具有相同的效果 :

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

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

由于拉姆达被分配到一个Expression

+0

因此,如果它被命名为Mexpression,它必须被分配给Mexpression而不是表达式?那么,有没有关于这方面的任何文件。 – lockedscope

+0

我添加了关于它的答案。 – lockedscope

从C#规范(6.1.12):

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

所以匿名函数(拉姆达)本身并不具有类型,但是当你把它分配给Expression类型的变量(或传递给函数期待Expression参数) - 它是隐式转换为它(假设它是可能 - 不是每个匿名函数都可以转换为表达式树)。与代表同样的故事 - 如果你将它传递给期望Func<int,int>的函数或者分配给这种类型的变量 - 它将成为委托而不是表达式树。

从msdn;

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

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