在LINQ to Objects中,扩展方法需要将一个委托类型作为参数,这样就可以将lambda表达式赋予参数。lambda表达式也可以赋予Expression类型的参数。C#编译器根据类型给lambda表达式定义不同的行为。如果类型是Expression,编译器就从lambda表达式中创建一个表达式树,并存储在程序集中。这样,就可以在运行期间分析表达式树,并进行优化,以便于查询数据源。
下面看看一个前面使用的查询表达式(代码文件ExpressionTreeSample/Program.cs);
var brazilRacers = from r in racers
where r.Country == “Brazil”
orderby r.Wins
select r;
这个查询表达式使用了扩展方法Where()、OrderByO和Select()。 Enumerable类定义了Where)扩展方法,并将委托类型Func<T,bool>作为参数谓词。
public static IEnumerable Where{
this IEnumerable source, Func<TSource, bool> predicate);
这样,就把lambda表达式赋予谓词。这里lambda表达式类似于前面介绍的匿名方法。
Func<Racer, bool> predicate =r => r.Country == “Brazil”;
Enumerable类不是唯—一个定义了扩展方法Where()的类。Queryable类也定义了WhereO扩展方法。这个类对Where(扩展方法的定义是不同的:
public static IQueryable Where
(this IQueryable source,
Expression<Func<TSource, bool>> predicate):
其中,把lambda表达式赋予类型Expression,该类型的操作是不同的:
Expression<Func<Racer, bool>> predicate = r => r.Country == “Brazil”;
除了使用委托之外,编译器还会把表达式树放在程序集中。表达式树可以在运行期间读取。表达式树从派生自抽象基类Expression的类中构建。Expression类与Expression不同。继承自Expression表达式类BinaryExpression,ConstantExpression、 InvocationExpression.lambdaExpression.NewExpression. NewArrayExpression. TemaryExpression 和 Unary Expression等。编译器会从lambda表达式中创建表达式树。
例如,lambda表达式r.Country="Brazil"使用了ParameterExpression, MemberExpression.ConstantExpression 和MethodCallExpression,来创建一个表达式树,并将该树存储在程序集中。之后在运行期间使用这个树,创建一个用于底层数据源的优化查询。DisplayTreeO方法在控制台上图形化地显示表达式树。其中传递了一个Expression对象,并根据表达式的类型,把表达式的一些信息写到控制台上。根据表达式的类型,递归地调用DisplayTree)方法。
C#表达树
于 2022-07-21 09:38:11 首次发布