表达式树

以前没听过表达式树,只听过表达式,而且听过Lambda表达式,首先介绍一下.NET里表达式树的核心概念:讲代码作为数据,他将一些代码表示为一个对象树,树中的每个节点本身都是一个表达式,不同的表达式类型代表能在代码中执行不同操作:二元操作,一元操作,方法调用等等.

System.Linq.Expression命名空间包含了代表表达式的各个类.所有的表达式类都从Expression

类派生,Expresssion是个抽象类,主要包括的是一些静态方法,这些方法用于生成其他表达式类的实例.Expression类还包含了两个重要属性:

Type属性:代表了表达式求值结果的类型.比如,一个,一个表达式是要获取一个字符串的Length属性,那么该表达式的Type属性应为int类型.

NodeType属性:代表了表达式的种类.这个种类表示成Expression Type美剧的一个成员:LessThan,Invoke,

Multiply,MemberAccess(好像有80多种).

案例:

Expression firstArg = Expression.Constant(2);

Expression secondArg = Expression.Constant(4);

Expression add = Expression.Add(firstArg, secondArg);

Console.WriteLine(add);

//输出结果为 : <2 + 4>

Console.ReadKey();

分析:上述表达式会生成如下表达式:

我突然这么一说,你肯定觉得我在忽悠你,我骗人,像我这样的正人君子不会骗你的.表达式中的”叶”表达式在代码中是最先创建的:表达式时自下而上构建的.这是由”表达式不易变”这一事实实现的.

将表达式树编译成委托

LambdaExpression是从Expression派生的类型.泛型类Expression<TDelegate>是从LamdaExpression派生的,其中反省参数TDelegate必须是委托类型.

LambdaExpression有个Comlile方法能创建恰当类型的一个委托.而Expression<TDelegate>的Compile方法返回TDelegate类型的委托.案例如下:

Expression firstArg = Expression.Constant(2);

Expression secondArg = Expression.Constant(4);

Expression add = Expression.Add(firstArg, secondArg);

Expression<Func<int>> func = Expression.Lambda<Func<int>>(add);

Func<int> compiled = func.Compile();

Console.WriteLine(compiled);

Console.ReadKey();

分析:我们通过Expression.Lambda<TDelegate>(Expression expression)方法来创建Expression<TDelegate>类型对象,再调用其Complie方法获取表达式树编译出的委托实例.

C#Lambda表达式转换成表达式树

我们知道Lambda表达式能显示或隐式的转换成恰当的委托实例.但是,编译器也能轻松的将Lambda表达式构建成一个表达式树:

将Lambda表达式转换成表达式树

Expression <Func<int>> return 5=()=>5;

但是,并不是所有的Lambda表达式都能转换成表达式树,有一些限制:不能将带有一个语句块的Lambda转换成一个表达式树----只有对的那个表达式进行求值的Lambda才可以.表达式中不能包含赋值操作,因为表达式树中表示不了这种操作.还有其他一些较少见的限制,总而言之,如果存在转换问题,会在编译时发现.

位于LINQ核心的表达式树

表达式树可以说是LINQ的核心之一,为什么是LINQ的核心之一呢?因为表达式树使得C#不再是仅仅能编译成IL,我们可以通过C#生成一个表达式树,将结果作为一个中间格式,在将其转换成目标平台上的本机语言.比如SQL.我们常用的LINQ to SQL就是这样生成的.

下图展示了LINQ to Objects和LINQ to SQL的不同路径

表达式树的用途:

通过Expression的派生类中的各种节点类型,我们就可以构建表达式树;然后可以把表达式树转换成相应的委托类型实例,最后执行委托实例的代码,但是我们不会绕这么大的弯子来执行委托实例的代码.

表达式树主要在LINQ to SQL中使用,我们需要将LINQ to SQL查询表达式(返回Queryable类型)转换成表达式树.之所以需要转换是因为LINQ to SQl查询表达式不是在C#代码中执行的,LINQ to SQL查询表达式被转换成SQL,通过网络发送,最后在数据库服务器中执行.

 

C#编程(六十五)----------表达式树的更多相关文章

  1. C#高级编程六十六天----表达式树总结【转】

    https://blog.csdn.net/shanyongxu/article/details/47257139 表达式树总结 基础 表达式树提供了一个将可执行代码转换成数据的方法.如果你要在执行代 ...

  2. 孤荷凌寒自学python第六十五天学习mongoDB的基本操作并进行简单封装4

    孤荷凌寒自学python第六十五天学习mongoDB的基本操作并进行简单封装4 (完整学习过程屏幕记录视频地址在文末) 今天是学习mongoDB数据库的第十一天. 今天继续学习mongoDB的简单操作 ...

  3. 第三百六十五节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的基本查询

    第三百六十五节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的基本查询 1.elasticsearch(搜索引擎)的查询 elasticsearch是功能 ...

  4. Gradle 1.12用户指南翻译——第六十五章. Maven 发布(新)

    其他章节的翻译请参见:http://blog.csdn.net/column/details/gradle-translation.html翻译项目请关注Github上的地址:https://gith ...

  5. “全栈2019”Java第六十五章:接口与默认方法详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  6. OpenCV开发笔记(六十五):红胖子8分钟带你深入了解ORB特征点(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  7. 《手把手教你》系列技巧篇(六十五)-java+ selenium自动化测试 - cookie -下篇(详细教程)

    1.简介 今天这一篇,宏哥主要讲解:利用WebDriver 提供可以读取.添加和删除cookie 信息的相关操作方法.验证浏览器中是否存在某个cookie.原因是:因为基于真实的cookie 的测试是 ...

  8. 学习ASP.NET Core Razor 编程系列十五——文件上传功能(三)

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  9. C#高级编程六十九天----DLR简介 .在.NET中使用DLR(转载) 我也来说说Dynamic

    DLR 一.近年来,在TIOBE公司每个月发布的编程语言排行榜中,C#总是能挤进前十名,而在最近十年来,C#总体上呈现上升的趋势.C#能取得这样的成绩,有很多因素,其中它在语言特性上的锐意进取让人印象 ...

随机推荐

  1. centos6.5环境DNS-本地DNS服务器bind的搭建

    centos6.5环境DNS-本地DNS服务器bind的搭建 域名系统(英文:Domain Name System,缩写:DNS)是因特网的一项服务.它作为将域名和IP地址相互映射的一个分布式数据库, ...

  2. 使用OpenSSL自建CA + Nginx配置HTTPS

    Ubuntu 16.04(ECS),OpenSSL 1.0.2g  1 Mar 2016,Nginx 1.10.3 (Ubuntu), 浏览器:Chrome 67,Firefox 61,Edge 40 ...

  3. XSS代码注入框架

    首先需要了解一下几点: 1.浏览器中Javascript变量的生命周期 Javascript变量的生命周期并不是你声明这个变量个窗口闭就被回收,只要有引用就会一直持续到浏览器关闭. 2.window对 ...

  4. python之Anaconda版本管理

    首先安装Anaconda,当其安装成功后,可以在cmd中测试是否安装成功,conda --version conda的环境管理 Conda的环境管理功能允许我们同时安装若干不同版本的Python,并能 ...

  5. POJ 3666 Making the Grade(二维DP)

    题目链接:http://poj.org/problem?id=3666 题目大意:给出长度为n的整数数列,每次可以将一个数加1或者减1,最少要多少次可以将其变成单调不降或者单调不增(题目BUG,只能求 ...

  6. 【OOB】MSHTML!CPaste­Command::Convert­Bitmapto­Png heap-based buffer overflow学习

    IE 11 MSHTML!CPaste­Command::Convert­Bitmapto­Png heap-based buffer overflow学习 MS14-056, CVE-2014-41 ...

  7. Java编程的逻辑 (24) - 异常 (上)

    ​本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...

  8. K8s中,tomcat的一部分jvm参数,如何通过env环境变量传递?

    这两天解决的一个需求: 如果用户没有在deployment中设置env参数,则tomcat默认使用1G左右的内存: 如果用户在deployment中提供了jvm参数,则tomcat将这部分的参数,覆盖 ...

  9. vs2010添加头文件与库文件搜索目录

    1 添加头文件搜索目录 项目属性->配置属性->C/C++->常规->添加包含目录 2 添加库文件搜索 项目属性->配置属性->VC++目录->库目录

  10. jenkins自动构建部署

    环境 centos7   tomcat8.5.37   maven3.3.9   jdk8   git1.8.3.1 安装jdk,tomcat,maven,git(环境变量,配置文件什么的自行百度) ...