![](/img/trans.png)
[英]How does the compiler know what datatype the lambda expression should be
[英]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表达式的表达式树。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.