表达式树练习实践:入门基础
什么是表达式树
来自微软官方文档的定义:
表达式树以树形数据结构表示代码。
它能干什么呢?
你可以对表达式树中的代码进行编辑和运算。这样能够动态修改可执行代码、在不同数据库中执行 LINQ 查询以及创建动态查询。
好不好玩?
表达式树还能用于动态语言运行时 (DLR) 以提供动态语言和 .NET Framework 之间的互操作性,同时保证编译器编写员能够发射表达式树而非 Microsoft 中间语言 (MSIL)。
哪里有应用?
ORM框架、工作流框架等,使用到 Lambda 的代码。。。动态执行代码、动态组装代码等。
创建表达式树
创建表达式树有两种方式:通过 lambda 表达式、通过 API。
创建表达式树的意思是,在此之前已经编写好每个结点,最后使用代码将所有结点组合起来,生成表达式树。
示例(通过API创建表达式树)
```ParameterExpression a = Expression.Parameter(typeof(int), "i");ParameterExpression b = Expression.Parameter(typeof(int), "j");Expression r1 = Expression.Multiply(a, b);ParameterExpression c = Expression.Parameter(typeof(int), "x");ParameterExpression d = Expression.Parameter(typeof(int), "y");Expression r2 = Expression.Multiply(c, d);Expression result = Expression.Add(r1, r2);Expression<Func<int, int, int, int, int>> func = Expression.Lambda<Func<int, int, int, int, int>>(result, a, b, c, d);var com = func.Compile();Console.WriteLine("表达式" + func);Console.WriteLine(com(12, 12, 13, 13));Console.ReadKey();
上面关于表达式树的代码很多,以下这一步叫生成/创建表达式树。
Expression<Func<int, int, int, int, int>> func = Expression.Lambda<Func<int, int, int, int, int>>(result, a, b, c, d);
以下这句叫执行表达式树
var com = func.Compile();
其它代码是用于生成表达式树结点/逻辑。
回归正题,创建表达式树的两种方法。
lambda 创建表达式树
上面的表达式树示例,是用于生成
( i * j ) + ( x * y )
但是就这么简单的操作,要写这么长,实在不合理。
而通过 lambda ,可以这样写
Expression<Func<int, int, int, int, int>> func = (i, j, x, y) => (i * j) + (x * y);
如果使用 lambda 生成表达式树, lambda 只能使用单行语句,不能使用 if、for等语句。
具体关于 Lambda 的表达式树,后面其它文章有说明。
通过 API 创建表达式树
就是这样
Expression<Func<int, int, int, int, int>> func = Expression.Lambda<Func<int, int, int, int, int>>(result, a, b, c, d);
两种方式左边的都是一样的,区别在于等号右边。
Expression< TDelegate >
上面示例的最终结果都是生成
Expression<Func<int, int, int, int, int>> func
func 是表达式树变量。
我们可以了解以下表达式树具有的方法和属性。
用于生成表达式树结点的,是 Expression 类型。
那么,创建的表达式树 func ,是 Expression<TDelegate>
类型。
定义如下
public sealed class Expression<TDelegate> : LambdaExpression
具有方法如下
Compile() | 将表达式树描述的 lambda 表达式编译为可执行代码,并生成表示 lambda 表达式的委托。 |
Compile(Boolean) | 将表达式树描述的 Lambda 表达式编译为已解释或已编译的代码,并生成表示该 Lambda 表达式的委托。 |
Compile(DebugInfoGenerator) | 将 lambda 编译到方法定义中。(Inherited from LambdaExpression) |
Update(Expression, IEnumerable) | 创建一个与此表达式类似的新表达式,但使用所提供的子级。如果所有子级都相同,则将返回此表达式。 |
Accept(ExpressionVisitor) | 调度到此节点类型的特定 Visit 方法。例如,MethodCallExpression调用 VisitMethodCall。 |
由于 Expression<TDelegate>
继承了 LambdaExpression
,所以有很多属性方法也可以用。
CanReduce | 指示可将节点简化为更简单的节点。如果返回 true,则可以调用 Reduce() 以生成简化形式。 |
Name | 获取 lambda 表达式的名称。 |
NodeType | 返回此 Expression 的节点类型。 |
Parameters | 获取 lambda 表达式的参数。 |
ReturnType | 获取 lambda 表达式的返回类型。 |
TailCall | 获取一个值,该值指示是否将通过尾调用优化来编译 lambda 表达式。 |
Type | 获取此 Expression 表示的表达式的静态类型。 |
好了,以上权当小笔记,备忘,目前先用不上,后面慢慢来使用。
解析/执行表达式树
创建表达式树后,就要执行表达式树。
在此之前,你需要了解 委托 Delegate,Func,Action,以及他们中间的关系。
执行表达式树是这样子的
Expression<Func<int, int, int, int, int>> func = Expression.Lambda<Func<int, int, int, int, int>>(result, a, b, c, d);var com = func.Compile();var runRasult = com(12, 12, 13, 13);
func 只是一个表达式树,我们把表达式树构建好后,“要将表达式树转为代码”,使用
.Compile()
方法,可以将表达式树生成一个 委托(例如上面的 com)。
为了简洁上面使用了 var,实际上是这样的
Func<int,int,int,int,int> com = func.Compile();
四个参数,一个返回值。
var runRasult = com(12, 12, 13, 13);
C#里有语法糖,对委托可以这样写
以后后面都是这样写了,能够缩成一行的代码,就没必要写出两行。
在 Vs 里面调试和查看表达式树,可以看这里
https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/expression-trees/debugging-expression-trees-in-visual-studio
初学者不必纠结于这些,了解一下本文内容,记一下概要信息即可。
表达式树练习实践:入门基础相关推荐
- python 从入门到实践 pdf_python入门基础实践课,带你有效的学习python
你还在枯燥的一个人学python吗?你尝试过python入门基础实践课吗? python入门实践课,带你快速了解python,它与你平时学python,有什么不一样的地方呢: 1.完全免费 第一次学p ...
- 3.Jenkins入门基础使用与Maven+SonarQube集成配置与实践
目录一览: Maven 集成配置与实践 SonarQube 集成配置与实践 WeiyiGeek Blog - 为了能到远方,脚下的每一步都不能少. Tips : 本文章来源 Blog 站点或者 We ...
- NVIDIA DLI——深度学习基础-理论与实践入门
今天参加了 NVIDIA DLI课程,主要学习基础理论,并进行实践. 深度学习理论与实践入门培训 | NVIDIAhttps://www.nvidia.cn/training/instructor-l ...
- 4.Jenkins入门基础使用与邮箱钉钉微信消息通知集成配置与实践
WeiyiGeek Blog - 为了能到远方,脚下的每一步都不能少. Tips : 本文章来源 Blog 站点或者 WeiyiGeek 公众账号 (技术交流.友链交换请邮我哟), 原文地址: 4.J ...
- python爬虫实践——零基础快速入门(四)爬取小猪租房信息
上篇文章我们讲到python爬虫实践--零基础快速入门(三)爬取豆瓣电影 接下来我们爬取小猪短租租房信息.进入主页后选择深圳地区的位置.地址如下: http://sz.xiaozhu.com/ 一,标 ...
- envi 文件 生成mat_JVM 内存分析工具 MAT 的深度讲解与实践——入门篇
1. MAT 工具简介 MAT(全名:Memory Analyzer Tool),是一款快速便捷且功能强大丰富的 JVM 堆内存离线分析工具.其通过展现 JVM 异常时所记录的运行时堆转储快照(Hea ...
- 深入入门正则表达式(java) - 1 - 入门基础
深入入门正则表达式(java) - 引言 深入入门正则表达式(java) - 1 - 入门基础 深入入门正则表达式(java) - 2 - 基本实例 深入入门正则表达式(java) - 3 - 正则 ...
- Java入门基础及面试100题--初入门
Java入门基础及面试100题 注:适合应届毕业生或java初入门者 1.面向对象的特征有哪些方面? 答:面向对象的特征主要有以下几个方面: - 抽象:抽象是将一类对象的共同特征总结出来构造类的过程, ...
- 【无标题】C#nbsp;语言入门基础介绍学习通http://www.bdgxy.com/
文章来源: 学习通http://www.bdgxy.com/ 普学网http://www.boxinghulanban.cn/ 智学网http://www.jaxp.net/ 表格制作excel教程h ...
最新文章
- mysql 大量数据 更改索引_Mysql索引数据结构详解与索引优化
- xfs_repair 实际工作中的问题
- 测试香港服务器访问速度的方法
- linux nohup 终端断了,linux 后台执行nohup 命令,终端断开无影响
- Mac 编译报错 symbol(s) not found for
- QT中的QGridLayout布局
- MySQL的隔离级别
- Android的线程使用来更新UI----Thread、Handler、Looper、Time...
- 的不定积分_不定积分大集合——方法篇
- python标准库之random模块
- Linux学习---新建文件,查看文件,修改权限,删除
- NO JVM installation found. please install a 64-bit JDK,解决方法 Error launching android studio NO J
- 柳絮飘,往事忆:家(二)
- 微型计算机原理顺序程序设计,微机原理实验,顺序实验.docx
- php自定义文件后缀名,显示文件扩展名 显示文件后缀名设置篇-DIV CSS网页开发准备...
- 算法导论程序24--直接寻址表(Python)
- 基于Java毕业设计畜牧场信息管理系统源码+系统+mysql+lw文档+部署软件
- Linux永久修改主机名和IP
- c libxml2解析html,在Python中,lxml和libxml2哪个更适合解析格式错误的html?
- html5 混合地址,混合引用是指在一个引用的单元格地址中的什么?
热门文章
- Wave 文件(5): 获取 Wave 文件的格式信息
- 连续对焦 auto对焦_如何在Windows 10上使用对焦辅助(请勿打扰模式)
- outlook附件大小限制_如何在Outlook中调整大图片附件的大小
- Java8基础之super关键字
- Java8新特性--CompletableFuture
- stl中Priority Queues(优先队列)的基本用法
- WiFi行业将走向何方?
- JavaScript匿名函数以及在循环中的匿名函数
- protobuf在java应用中通过反射动态创建对象
- Cowboy 源码分析(十八)