不能不说的C#特性-表达式树

2008-09-18 00:00 by 横刀天笑, 17112 阅读, 14 评论, 收藏编辑

最近发生了很多很多事情,频繁的搬家。工作上的事情也挺多的,所以博客更新的非常缓慢。

已经有很多很多人聊过这个话题,今天我在这里重复也不会探讨出什么新东西,只是把自己的理解描述出来,更是为了整个系列文章的完整性。

当你听说Linq给你的承诺时,你怎么想的?Wow,我们可以以统一的方式操作各种各样的数据了。这就是我当时的想法。虽然人们在现实中总是喜欢差异,认为差异才能产生美,如果一切的一切都是一样的,这个世界将无比的单调,可是作为程序员的我们却对标准趋之若鹜,对差异嫉恶如仇。看同桌的你是不是正在为了Oracle和Sql Server两种数据库编写两套数据访问的类?

表达式树概念

Linq的承诺貌似Java那个梦想一样:Write Once,Run Anywhere。Java是怎么做到的?Sun等公司为我们在各种平台架构上实现了各自的虚拟机,Java的编译分为两个阶段,第一阶段将Java代码编译为字节码,在这个阶段不管在什么平台上,只要Java源代码一样生成的字节码是一致的,第二个阶段,也就是运行阶段,虚拟机会根据平台的不同生成不同的代码。就是通过将编译器分为前端和后端来实现这个梦想。

实际上LINQ也是这么做的,对各种数据的操作无非“增删查改”,但是具体做的时候关系数据库需要使用SQL来操作,而XML需要XPath来操作。我们如何将“增删查改”的语法做到一致,让我们用起来好像操作的数据只有一种?

答案是使用表达式树

表达式树仅仅是将表达式(这里特指Lambda表达式)用树状的数据结构来表示。相当于Java的字节码,至于如何去解析这个树的结构那就看你自己了,如何去解释这个表达式树。

看下面这个Lambda表达式:

username => username == “yuyi”

我们主要看表达式的主体:username == “yuyi”,如果我们是要对数据库进行操作,这将翻译为字段username中所有值为”yuyi”的行,如果操作的是XML那也许是查询名称为username,值为”yuyi”的attribute。表达式树承载的只是这样一个结构:

如何解释它这是你的事。

在C#中Expression<Function<string,bool>> IsTrue = username=>username==”yuyi”,就表示一个表达式树,这个语句在编译后就组成为一个树状的结构。

在编译原理中,我们知道编译器的前两个阶段主要做的是:词法分析、语法分析。在词法分析中编译器会从代码文件中读入一个个的字符,然后识别出其中的关键字、标识符、运算符、常量、字符串等。

比如上面的表达式就会识别出:

Username->标识符

==->运算符

“yuyi”->字符串

这些东西就叫做符号

然后以这些符号作为输入进行语法分析,语法分析会将这些符号组合成一个树,这个树我们称之为抽象语法树(AST),表达式树也是一种简单的AST。

(在VS2008带的例子中有个DynamicQuery的例子,这里有一个Dynamic.cs文件,这里就自己做表达式的解析,只不过解析的是用字符串形式的表达式,通过这个代码你可以看看表达式的解析过程,这里有一个ExpressionParser类,它就是负责表达式的词法解析的,该类里有一个Token的机构,这就是上面所说的符号,TokenId表示符号的类型

<"Samples"1033"CSharpSamples"LinqSamples"DynamicQuery>)

对于Lambda表达式,有两种编译方式,常规的:

Func<string,bool> IsTrue = username => username == “yuyi”;

这个时候编译器会将其编译为匿名方法,关于匿名方法的相关介绍可以参看我这篇文章

编译成表达式树:

Expression<Func<string,bool>> IsTrue = username => username == “yuyi”;

这么细微的差别,C#这次却不真的编译这条语句,而是将其进行词法、语法分析,得到的是一个数据结构。

我们注意到表达式树还有一个Compile实例方法,它可以将表达式编译成匿名方法,也就是这个数据结构可以向匿名方法转变。

想想Linq to SQL,实际上它不就是C#作为源语言,SQL作为目标语言的一个编译过程么。形成表达式树(抽象语法树)后,就是代码生成了,只不过这个代码生成有的时候是生成代码,比如Linq to SQL,生成的是SQL语句,有的时候是生成的方法调用,比如Linq to XML,生成的是对XML文档的操作。

为什么一样的语句,有的时候是操作内存中的对象集合,有的时候是操作远程数据库?请查看我这篇文章

关于表达式树更多细节内容,你可以查看TerryLee老大的这篇图文并茂的文章

不能不说的C#特性-表达式树的更多相关文章

  1. 转载:C#特性-表达式树

    原文地址:http://www.cnblogs.com/tianfan/ 表达式树基础 刚接触LINQ的人往往觉得表达式树很不容易理解.通过这篇文章我希望大家看到它其实并不像想象中那么难.您只要有普通 ...

  2. C#特性-表达式树

    表达式树ExpressionTree   表达式树基础 转载需注明出处:http://www.cnblogs.com/tianfan/ 刚接触LINQ的人往往觉得表达式树很不容易理解.通过这篇文章我希 ...

  3. C#学习笔记(九):LINQ和表达式树

    LINQ LINQ:语言集成查询(Language Integrated Query)是一组用于c#和Visual Basic语言的扩展.它允许编写C#或者Visual Basic代码以查询数据库相同 ...

  4. C#3.0新特性:隐式类型、扩展方法、自动实现属性,对象/集合初始值设定、匿名类型、Lambda,Linq,表达式树、可选参数与命名参数

    一.隐式类型var 从 Visual C# 3.0 开始,在方法范围中声明的变量可以具有隐式类型var.隐式类型可以替代任何类型,编译器自动推断类型. 1.var类型的局部变量必须赋予初始值,包括匿名 ...

  5. 程序猿修仙之路--数据结构之你是否真的懂数组? c#socket TCP同步网络通信 用lambda表达式树替代反射 ASP.NET MVC如何做一个简单的非法登录拦截

    程序猿修仙之路--数据结构之你是否真的懂数组?   数据结构 但凡IT江湖侠士,算法与数据结构为必修之课.早有前辈已经明确指出:程序=算法+数据结构  .要想在之后的江湖历练中通关,数据结构必不可少. ...

  6. 再讲IQueryable<T>,揭开表达式树的神秘面纱

    接上篇<先说IEnumerable,我们每天用的foreach你真的懂它吗?> 最近园子里定制自己的orm那是一个风生水起,感觉不整个自己的orm都不好意思继续混博客园了(开个玩笑).那么 ...

  7. [.net 面向对象程序设计进阶] (7) Lamda表达式(三) 表达式树高级应用

    [.net 面向对象程序设计进阶] (7) Lamda表达式(三) 表达式树高级应用 本节导读:讨论了表达式树的定义和解析之后,我们知道了表达式树就是并非可执行代码,而是将表达式对象化后的数据结构.是 ...

  8. C#中的Lambda表达式和表达式树

    在C# 2.0中,通过方法组转换和匿名方法,使委托的实现得到了极大的简化.但是,匿名方法仍然有些臃肿,而且当代码中充满了匿名方法的时候,可读性可能就会受到影响.C# 3.0中出现的Lambda表达式在 ...

  9. LinQ实战学习笔记(三) 序列,查询操作符,查询表达式,表达式树

    序列 延迟查询执行 查询操作符 查询表达式 表达式树 (一) 序列 先上一段代码, 这段代码使用扩展方法实现下面的要求: 取进程列表,进行过滤(取大于10M的进程) 列表进行排序(按内存占用) 只保留 ...

随机推荐

  1. leetcode650 2 Keys Keyboard

    思路: 把给定的数分解质因子之后,对于每一个质因子x,都需要x次操作(一次copy all操作和x-1次paste),所以答案就是对分解后的所有质因子求和. 实现: class Solution { ...

  2. FCC 基础JavaScript 练习2

    1. 引号不是字符串中唯一的可以被转义字符.下面是常见的转义序列列表: \'  单引号 \" 双引号 \\ 反斜杠符 \n 换行符 \r 回车符 \t 制表符 \b 退格符 \f  换页符 ...

  3. C语言入门100题,考算法的居多

    入门题,考算法的居多,共同学习! 1. 编程,统计在所输入的50个实数中有多少个正数.多少个负数.多少个零. 2. 编程,计算并输出方程X2+Y2=1989的所有整数解. 3. 编程,输入一个10进制 ...

  4. 15Microsoft SQL Server 数据库维护

    Microsoft SQL Server 数据库维护 2.6.1数据库联机与脱机 --联机:该状态为数据库正常状态,也就是我们常看到的数据库的状态,该状态下的数据库处于可操作状态,可以对数据库进行任何 ...

  5. JavaScript中的方法

    JavaScript中的方法 在JavaScript中,可以通过对象来调用对应的方法.在JavaScript中,有三个重要的window对象方法:用于显示警告信息的alert.用于显示确认信息的con ...

  6. Stuts2学习——HelloWorld

    这两天从对Struts一窍不通到成功运行HelloWorld,在SSH这条路上迈出了第一步. 下面我把我的第一个Struts程序放上来: 一.新建web project,配置文件等准备工作 1. 新建 ...

  7. css--小白入门篇2

    一.css基础选择器 html负责结构,css负责样式,js负责行为. css写在head标签里面,容器style标签. 先写选择器,然后写大括号,大括号里面是样式. 1 <style type ...

  8. [Luogu] P1407 [国家集训队]稳定婚姻

    题目描述 我国的离婚率连续7年上升,今年的头两季,平均每天有近5000对夫妇离婚,大城市的离婚率上升最快,有研究婚姻问题的专家认为,是与简化离婚手续有关. 25岁的姗姗和男友谈恋爱半年就结婚,结婚不到 ...

  9. 洛谷 P1280 尼克的任务 (线性DP)

    题意概括 线性资源分配的问题,因为空闲的时间大小看后面的时间(反正感觉这个就是个套路)所以从后往前DP. 转移方程 如果当前时刻没有工作 f[i]=f[i+1]+1 如果当前时刻有工作 f[i]=ma ...

  10. 03 Python的那些事

    目录: 1) 创始人以及重要发展历程 2) Python语言的特点 3) TIOBE排名 4) 解释器 5) Python后缀名 6) 变量规则和约定 7) 常量 8) 注释 9) 缩进 10) Py ...