Lambda表达式可以转换成为代码(委托)或者数据(表达式树)。若将其赋值给委托,则Lambda表达式将转换为IL代码;如果赋值给 Expression<TDelegate>,则构造出一颗表达式树。表达式树本质上来说就是一颗抽象语法树(AST),也就是一段代码经过 解析后用树形来表达出这段代码的意思。解释器将在代码优化和代码生成的时候使用到AST。在.NET中,表达式树就是C#编译器解析lambda表达式的 结果。简单来说,转换成表达式树以后,我们可以通过自己的解释器解析表达式树来按需求实现自己的逻辑。

比如想表达加法,用中文写就是 “二大于一” ,用数学来表达就是 "2>1",我们想表达的抽象概念就是大于,和具体的形式无关。因此表达式树中就有表示GreaterThan的一种Type,表达的就是这么一种 大于的抽象概念。它可以由编译器把lambda表达式 ()=> 2>1 编译成我们所需的表达式树,然后我们再通过解析这个表达式树,把抽象概念翻译成我们所需的“二大于一”这种中文的具体形式。

有这么一个笑话,说的是三国版批评与自我批评:

”关羽:我要批评张飞,平时说话声音太大,虽然用意是关心将士温饱,但说话的样子很凶,不利于团结基层兵士。 张飞:我批评赵云,身为大将,衣着太干净、太鲜亮,看起来很骄傲。赵云:我要批评关羽,你的赤兔马违反了公务用马管理办法,属于超豪华配备吧?关羽:X, 你TM懂不懂什么叫批评啊?会不会玩啊?“

用上面的例子来说,就是lambda表达式要表达的是“批评他人”这个意思,但是不同的人解读“批评他人”是不同的。可以用访问者模式来做到这一点。

C#中不是每个类型都能相加的,编译器会报错。但是我们表达的意思是两种类型相加这一通用的概念,因此这时候就可以用表达式树来表达这一种概念,来“绕过”编译器限制。这是合理的。

我 们可以自定义对于表达式中相加Expression.Add的理解,也可以由C#编译器按照它的理解来帮我们编译成可执行的匿名函数。C#编译器理解中并 不是每种类型都可以相加的,因此如果Expression.compile成Func类型函数那么在执行的时候就有可能会报Exception,比如 "The binary operator Add is not defined for the types 'System.String' and 'System.String'."

表达式树的顺序与遍历……

编译器可以由lambda表达式帮我们生成一颗表达式树,我们接下来解决的就是要如何解析这个树的问题。对于树我们采用至顶向下的遍历方式,借助访问者模式去解析表达式树。

表达式树的生成

当编译器看到某个lambda表达式赋值给了类型为Expression的变量的时候,就会将其编译成对一系列工厂方法的调用,这些工厂方法将会在程序运行时动态的构造出表达式树。

表达式树将在程序运行时动态构造,不过一旦构造完成,则无法被再次修改。

  public abstract class QueryProvider : IQueryProvider
{
protected QueryProvider()
{
} IQueryable<S> IQueryProvider.CreateQuery<S>(Expression expression)
{
return new Query<S>(this, expression);
} IQueryable IQueryProvider.CreateQuery(Expression expression)
{
Type elementType = TypeSystem.GetElementType(expression.Type);
try
{
return (IQueryable)Activator.CreateInstance(typeof(Query<>).MakeGenericType(elementType), new object[] { this, expression });
}
catch (TargetInvocationException tie)
{
throw tie.InnerException;
}
} IQueryProvider.Execute<S>(Expression expression)
{
return (S)this.Execute(expression);
} object IQueryProvider.Execute(Expression expression)
{
return this.Execute(expression);
} public abstract string GetQueryText(Expression expression);
public abstract object Execute(Expression expression);
}
  public class AmazonBookQueryProvider : QueryProvider
{
public override String GetQueryText(Expression expression)
{
AmazonBookQueryCriteria criteria; // Retrieve criteria
criteria = new AmazonBookExpressionVisitor().ProcessExpression(expression); // Generate URL
String url = AmazonHelper.BuildUrl(criteria); return url;
} public override object Execute(Expression expression)
{
String url = GetQueryText(expression);
IEnumerable<AmazonBook> results = AmazonHelper.PerformWebQuery(url);
return results;
}
}
解析一个表达式树的例子

说说lambda表达式与表达式树(未完)的更多相关文章

  1. C#复习笔记(4)--C#3:革新写代码的方式(Lambda表达式和表达式树)

    Lambda表达式和表达式树 先放一张委托转换的进化图 看一看到lambda简化了委托的使用. lambda可以隐式的转换成委托或者表达式树.转换成委托的话如下面的代码: Func<string ...

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

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

  3. 16.C#初见Lambda表达式及表达式树(九章9.1-9.3)

    在说明Lambda相关知识前,我们需要了解Lambda表达式常用于LINQ,那么我们来聊下LINQ. LINQ的基本功能就是创建操作管道,以及这些操作需要的任何状态.这些操作表示了各种关于数据的逻辑: ...

  4. Lambda表达式和表达式树

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

  5. 深入学习C#匿名函数、委托、Lambda表达式、表达式树类型——Expression tree types

    匿名函数 匿名函数(Anonymous Function)是表示“内联”方法定义的表达式.匿名函数本身及其内部没有值或者类型,但是可以转换为兼容的委托或者表达式树类型(了解详情).匿名函数转换的计算取 ...

  6. lambda表达式和表达式树(深入理解c#)

    1.Lambda形式 1). Lambda表达式最冗长的形式: (显式类型的参数列表)=>{语句} 2). 大多数时候,都可以用一个表达式来表示主体,该表达式的值是Lambda的结果,在这些情况 ...

  7. C# 表达式树 创建、生成、使用、lambda转成表达式树~表达式树的知识详解

    笔者最近学了表达式树这一部分内容,为了加深理解,写文章巩固知识,如有错误,请评论指出~ 表达式树的概念 表达式树的创建有 Lambda法 和 组装法. 学习表达式树需要 委托.Lambda.Func& ...

  8. 无法将具有语句体的lambda表达式转换为表达式树

    很早就碰到了这个问题,当时也没有深入的研究,趁着空闲,遂把这个问题研究清楚. (一)普通案例 下面从一个普通的案例入手,下面准备两个List集合,都是放在内存里面的(需要模拟到远端执行的时候,我们是通 ...

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

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

  10. [.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门

    [.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门 本节导读: 认识表达式树(Expression Tree),学习使用Lambda创建表达式树,解析表达式树. 学习 ...

随机推荐

  1. 02-Vue入门之数据绑定

    2.1. 什么是双向绑定? Vue框架很核心的功能就是双向的数据绑定. 双向是指:HTML标签数据 绑定到 Vue对象,另外反方向数据也是绑定的.通俗点说就是,Vue对象的改变会直接影响到HTML的标 ...

  2. 读《你必须知道的.NET》继承本质论 Bird bird=new Chicken()

    我们创建如下的三层继承层次类. public abstract class Animal { public abstract void ShowType(); } public class Bird ...

  3. python脚本实现集群检测和管理

    python脚本实现集群检测和管理 场景是这样的:一个生产机房,会有很多的测试机器和生产机器(也就是30台左右吧),由于管理较为混乱导致了哪台机器有人用.哪台机器没人用都不清楚,从而产生了一个想法-- ...

  4. [ucgui] 对话框8——Framewin小工具

    >_<" 这里主要是窗口小工具Framewin的用法介绍,包括创建背景窗口及其消息回调函数,创建Frame窗口并设置其回调函数,这里一些其他的功能被我注释掉了,有向状态栏添加最大 ...

  5. [C++] 井字棋游戏源码

    TicTac.h #define EX 1 //该点左鼠标 #define OH 2 //该点右鼠标 class CMyApp : public CWinApp { public: virtual B ...

  6. ajaxSubmit与ajaxFileUpload的空值

    ajaxSubmit发现正文无内容, ajaxFileUpload发现无上传内容, 嗯,你只是忘记了 html 中控件的 name 没有指定,这哥们不认 id 的.

  7. 使用Lucene.NET实现数据检索功能

    引言     在软件系统中查询数据是再平常不过的事情了,那当数据量非常大,数据存储的媒介不是数据库,或者检索方式要求更为灵活的时候,我们该如何实现数据的检索呢?为数据建立索引吧,利用索引技术可以更灵活 ...

  8. JAVA学习中Swing部分JDialog对话框窗体的简单学习

    package com.swing; import java.awt.Color;import java.awt.Container;import java.awt.event.ActionEvent ...

  9. JQ中 trigger()和triggerHandler()区别

    既然使用了trigger和triggerHandler,那么你应该了解了他们的差别了. trigger():在每一个匹配的元素上触发某类事件. triggerHandler():这个特别的方法将会触发 ...

  10. 部署rfc5766-turn-server--谷歌推荐的开源穿透服务器 [复制链接]

    谷歌推荐的开源穿透服务器,包含trun和stun服务,主页:https://code.google.com/p/rfc5766-turn-server/(个人觉得可以利用这个来进一步搭建VPN,有兴趣 ...