编译器如何知道它需要返回表达式树?
难道是硬编码到编译器,当它遇到分配给表达< 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
。
从C#规范(6.1.12):
匿名函数和方法组没有类型和自己的 ,但也可以是隐式转换为委托类型或 表达式树类型。
所以匿名函数(拉姆达)本身并不具有类型,但是当你把它分配给Expression
类型的变量(或传递给函数期待Expression
参数) - 它是隐式转换为它(假设它是可能 - 不是每个匿名函数都可以转换为表达式树)。与代表同样的故事 - 如果你将它传递给期望Func<int,int>
的函数或者分配给这种类型的变量 - 它将成为委托而不是表达式树。
从msdn;
当lambda表达式被分配给类型表达的变量,编译器发出代码来构建表示lambda表达式表达式树。
因此,如果它被命名为Mexpression,它必须被分配给Mexpression而不是表达式?那么,有没有关于这方面的任何文件。 – lockedscope
我添加了关于它的答案。 – lockedscope