BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

掌握表达式树

| 作者 Hartmut Wilms 关注 0 他的粉丝 ,译者 张海龙 关注 0 他的粉丝 发布于 2008年2月13日. 估计阅读时间: 5 分钟 | GMTC大前端的下一站,PWA、Web框架、Node等最新最热的大前端话题邀你一起共同探讨。

对于熟悉函数式编程语言的开发者而言,可能不需要再解释为什么说“表达式树(即Expression Tree)是非常有用的”,但对其他人来讲,表达式树则是C# 3.0或VB 9.0的所有新特性中最引人注目的一个概念。

Charlie Calvert讲解了表达式树的基础,他从语法描述开始,并以同Visual Studio 2008一起发行的示例程序——ExpressionTressVisualizer为例,形象地展示了如何使用表达式树。

表达式树与Lambda表达式相关联,Lambda表达式是可在行内实现预期代理和匿名代理的内容的一种方式。Ian Griffiths在他关于表达式树文章中,给出了一个非常不错的Lambda表达式介绍,以及Lambda与表达式树的关系。正如Ian所指出的,“Lambda除了语法不同以外,并没有比我已掌握的匿名方法提供更多的东西,但是,它却使一些匿名方法无法实现的事情变成了可能。”

Func<int, bool> nonExprLambda = x => (x & 1) == 0;
Expression<Func<int, bool>> exprLambda = x => (x & 1) == 0;

[...]

第二行更有趣,它变成Func的代理,将Func作为一种名为Expression的泛型的类型参数,然后按照相同的方式进行初始化,因此,你可能会认为两者是在完成同样的事情,但是,它却能让编译器知道了Expression类型,这就导致了不一样的行为;前者会直接将Lambda表达式编译为IL,而后者则是通过对表达式进行评估后,生成一个可以创建并代表此表达式的对象树的IL。

Charlie仔细钻研了Expression的细节:

Expression<TDelegate>类共有四个属性:

  • Body:获取表达式的主体;
  • Parameters:获取Lambda表达示的参数;
  • NodeType:得到树中某些节点的表达式类型(ExpressionType),这是一个有45种不同值的枚举类型,代表表达式节点的所有可能类型,如返回常数、也可能返回参数、或者返回一个值是否小于另外一个(<),或者返回一个值是否大于另外一个(>),或者返回两个值的和(+)等等;
  • Type:得到表达式的静态类型,在本例中,表达式的类型是Func<int, int, int>。

在C# 3.0和VB 9.0大部分新特性中,表达式树在“LINQ,尤其是LINQ to SQL”中扮演了一个非常重要的角色:

var query = from c in db.Customers
where c.City == "Nantes"
 select new { c.City, c.CompanyName };

LINQ表达式会返回一个IQueryable类型的值,IQueryable值包含有一个表达式树,由它来代表这个LINQ查询。当创建这个查询时,SQL语句并没有被发送到数据库中,只有当你在代码中对这个IQueryable对象进行Iterate操作时,这个SQL语句才会被创建并执行,这个概念就是延迟执行

Charlie Calvert对这种方法的使用进行了说明:

因为查询是以一种高度抽象的数据结构封装后传送给编译器的,所以,编译器可以以它期望的任一方式自由地进行翻译。查询的执行次序和途径并非强制指定的,相反,它可以对表达树进行分析,以发现你所期望的结果,然后再决定如何处理;至少在理论上,它可以独立地考虑很多因素,诸如当前的网络流量、数据库的负载、它当前已有的可用结果集等等;虽然在LINQ to SQL中,它实际上并没有去考虑所有这些因素,但在理论上它可以考虑更多它关心的因素;此外,它还可以对表达式树进行分析,并将LINQ to SQL的输出结果转换成截然不同的形式,然后传递给你手写的自定义代码。

Marlon Grech展示了如何应用表达式树,以及如何创建表达式解析器。Octavio Hernández提供了一个表达式树的表达式类层次汇总表。

查看英文原文Get a Grasp on Expression Trees

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我
社区评论

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT