表达式树允许将 lambda 表达式表示为数据结构而非可执行代码。表达式目录树是System.Linq.Expressions.Expression< D > 形式的表达式目录树类型 (expression tree type) 的值,其中 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< D > 的确切定义以及将 lambda 表达式转换为表达式树类型时有关构造表达式树的准确规则不在本文的介绍范围之内,将另作说明。
有两个要点需要明确指出:
● 并非所有 lambda 表达式都能转换为表达式树。例如,具有语句体的 lambda 表达式和包含赋值表达式的 lambda 表达式不能这样表示。在这些情况下,转换仍存在,但在编译时将失败
● Expression< D > 提供一个实例方法 Compile,该方法产生一个类型为 D 的委托:
Func< int,int > del2 = exp.Compile();
调用此委托将导致执行表达式树所表示的代码。因此,根据上面的定义, del 和 del2 等效,而且
下面的两个语句也将等效:
int i1 = del(1);
int i2 = del2(1);
执行此代码后, i1 和 i2 的值都为 2。