博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
说说lambda表达式与表达式树(未完)
阅读量:6095 次
发布时间:2019-06-20

本文共 2801 字,大约阅读时间需要 9 分钟。

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 IQueryProvider.CreateQuery(Expression expression)    {      return new Query(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(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
results = AmazonHelper.PerformWebQuery(url); return results; } }

 

解析一个表达式树的例子

 

转载于:https://www.cnblogs.com/lwzz/p/3364451.html

你可能感兴趣的文章
nessus安装及使用
查看>>
AspNet GridView Excel 下载 Excel 导出
查看>>
cordova 源码分析记录
查看>>
04 企业的结构
查看>>
php 记录日志时 基础的日志格式
查看>>
dedecms生成文档数据库崩溃 mysql daemon failed to start
查看>>
Linux的50个基本命令
查看>>
Objective-C中创建单例方法的步骤
查看>>
[转]无法安装MVC3,一直卡在vs10-kb2483190
查看>>
Codeforces 520B:Two Buttons(思维,好题)
查看>>
web框架-(二)Django基础
查看>>
Jenkins持续集成环境部署
查看>>
emoji等表情符号存mysql的方法
查看>>
ubuntu14.04中国源
查看>>
Excel到R中的日期转换
查看>>
网络层
查看>>
centos7没有ifconfig命令
查看>>
10-SAP PI开发手册-ERP发布服务供外围系统调用(RFC类型)
查看>>
cmd命令行查看windows版本
查看>>
城市三联动简单实例
查看>>