C# 表达式树 创建、生成、使用、lambda转成表达式树~表达式树的知识详解
笔者最近学了表达式树这一部分内容,为了加深理解,写文章巩固知识,如有错误,请评论指出~
表达式树的概念
- 表达式树的创建有 Lambda法 和 组装法。
- 学习表达式树需要 委托、Lambda、Func<> 基础。
- 表达式树 形状可以参考 二叉树。
- 可以把表达式树理解成 数学表达式。
数学表达式的所有常量、符号为表达式树的底节点。每一次计算生成的结果是一个结点,或者说他们的共同结点就是他们应该进行的运算。
生成表达式树
表达式树的创建有 Lambda表达式法 和 组装法
为了方便,这里指定生成的表达式为 ( i * j ) + ( x * y )
他们的运算是这样的
Lambda 生成表达式树
在控制台创建应用,需要引入
using System.Linq.Expressions;
1,创建表达式
(系统自动把 Lambda表达式 转为表达式树,当然,不是所有的 Lambda表达式都能转为表达式树,详细请参考文章后面的“系统自动把 Lambda表达式 转为 表达式树” 一节)
Expression<Func<int, int, int, int, int>> func = (i, j, x, y) => (i * j) + (x * y);
2,输出系统转换的表达式
输入这一行代码后运行,看看控制台输出的表达式树
Console.WriteLine(func);
3,把代码转为数据
(把代码当作数据来使用)
var compile = func.Compile();
//或 Func<int, int, int, int, int> compile = func.Compile();
4,代入运算
int result = compile(12, 13, 14, 15); //把具体数字代入表达式并运算
Console.WriteLine(result); //输出表达式结果
完整代码如下
Expression<Func<int, int, int, int, int>> func = (i, j, x, y) => (i * j) + (x * y);
Console.WriteLine(func); //输出表达式 var compile = func.Compile(); //把代码转为数据
//或 Func<int, int, int, int, int> compile = func.Compile(); int result = compile(, , , ); //把具体数字代入表达式并运算
Console.WriteLine(result); //输出表达式结果
Console.ReadKey();
控制台输出
组装法生成表达式树
表达式由 "符号" 和 运算符组成,。
使用 ParameterExpression 类型 来修饰参数,使用 Expression.Parameter(Type type,string name) 实例化参数。
1,生成 a b d 参数
ParameterExpression a = Expression.Parameter(typeof(int), "i");
ParameterExpression b = Expression.Parameter(typeof(int), "j");
ParameterExpression c = Expression.Parameter(typeof(int), "x");
ParameterExpression d = Expression.Parameter(typeof(int), "y");
分析:
i、j、x、y 是结点名称,a、b、c、d 是实例名称。不用留精力思考我上面 a b c d i j x y 的名称设定。
ParameterExpression 表示创建一个节点,Parameter 表示一个命名的参数表达式,详细请参考文章后面的 “Expression 参数分类”。
Expression.Parameter(Type type,string name) 表示这个节点的属性。
2,生成结点
Expression r1 = Expression.Multiply(a, b); //乘法运行
Expression r2 = Expression.Multiply(c, d); //乘法运行
分析:
创建了 ( i * j ) 和 ( x * y ) 两个运算
Multiply 表示 不进行溢出检查的乘法运算。Expression 里有 85种 操作方法,更多加减乘除比较大小等操作在文章后面详细附上,参考 “ 运算操作符” 一节。
3,生成终结点
Expression result = Expression.Add(r1, r2); //相加
4,生成表达式树、转换、输出表达式树、代入数据进行运算
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(, , , ));
完整代码如下
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(, , , ));
Console.ReadKey();
控制台界面
补充说明
1,系统自动把 Lambda表达式 转为 表达式树
对 lambda表达式 的要求 只能 由 传入参数 和 返回参数 两部分表示。lambda表达式 不能包含其它判断、循环等的代码。
错误举例
Expression<Func<int, int, int, int, int>> func = (a, b, c, d) =>
{
if (a < )
{
a += ;
}
/*
* 其它操作代码
*/
return a + b + c + d;
};
把那些东西通通删除,修改后:
Expression<Func<int, int, int, int, int>> func = (a, b, c, d) => a + b + c + d;
这样的 “最简” 的 lambda表达式 才能被系统自动转为表达式树
2,运算操作符
一般数学上,有加减乘除、取余、求幂等操作,而在程序中,运算操作符可以有更多的选择,达 85 种。
笔者这里给出一张图列出部分方法。
微软官方 的操作运算符列表 https://docs.microsoft.com/zh-cn/dotnet/api/system.linq.expressions.expression?view=netframework-4.7.2
估计大家看微软的文档会有点不爽~这里推荐大神翻译、整理的列表 https://blog.csdn.net/zhuqinfeng/article/details/70168337
3,Expression 参数
以数学 椭圆周长公式:L = 2πb + 4(a-b) ,a 为长半轴,b 为短半轴, 进行举例
Parameter 类似于 数学的 未知数 如 a 、 b;使用方法
ParameterExpression a = Expression.Parameter(typeof(int), "a")
ParameterExpression b = Expression.Parameter(typeof(int), "b")
Constant 表示一个常数,例如 2πb 中的 2 或者 2π ;使用方法
ConstantExpression define = Expression.Constant(2);
其它更多参数分类 请查看 https://blog.csdn.net/zhuqinfeng/article/details/70168337
这里附上部分截取图片
4,Expression 的操作方法
表示加减乘除等运算的方法。以下图举例
Multiply(a,b) 为乘法,Add(r1,r2) 为加法。
当然,并没有这么简单,他们都有相关的重载方法和高级的使用用途。
请查看 https://blog.csdn.net/zhuqinfeng/article/details/70168337
这里给出部分截图
5,表达式树的高级用法
表达式树可以结合 数据库查询 或 Linq,衍生很多高级操作。
例如 动态查询、遍历表达式树、转成成 SQL where 子句等等,限于幅度,笔者不再赘述。
下面的链接可以查看 System.Linq.Expressions 的所有类型对象。https://docs.microsoft.com/zh-cn/dotnet/api/System.Linq.Expressions?view=netframework-4.7.2
好好学习,天天向上~期望 3号面试成功
C# 表达式树 创建、生成、使用、lambda转成表达式树~表达式树的知识详解的更多相关文章
- JSON创建键值对(key是中文或者数字)方式详解
JSON创建键值对(key是中文或者数字)方式详解 先准备好一个空的json对象 var obj = {}; 1. 最原始的方法 obj.name = 'zhangsan'; //这种方式很简单的添加 ...
- Scrapy框架——介绍、安装、命令行创建,启动、项目目录结构介绍、Spiders文件夹详解(包括去重规则)、Selectors解析页面、Items、pipelines(自定义pipeline)、下载中间件(Downloader Middleware)、爬虫中间件、信号
一 介绍 Scrapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,使用它可以以快速.简单.可扩展的方式从网站中提取所需的数据.但目前Scrapy的用途十分广泛,可 ...
- quartz定时任务cron表达式讲解及翻译成现实语言的插件的使用详解
cron表达式讲解 参见该网址: https://www.cnblogs.com/GarfieldTom/p/3746290.html cron表达式只有专业技术人员才看得懂,普通人不知道表达式是什么 ...
- AngularJS开发指南15:AngularJS的创建服务,将服务注入到控制器,管理服务依赖详解
创建服务 虽然AngularJS提供了很多有用的服务,但是如果你要创建一个很棒的应用,你可能还是要写自己的服务.你可以通过在模块中注册一个服务工厂函数,或者通过Module#factory api或者 ...
- oracle创建用户、表空间、临时表空间、分配权限步骤详解
首先登陆管理员账号,或者有DBA权限的用户,接下来依次: --查询所有用户select * from dba_users;--创建新用户create user gpmgt identified by ...
- 使用Eclipse创建Web项目时WEB-INF下找不到web.xml问题详解
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/yjrguxing/article/deta ...
- Code First开发系列之管理数据库创建,填充种子数据以及LINQ操作详解
返回<8天掌握EF的Code First开发>总目录 本篇目录 管理数据库创建 管理数据库连接 管理数据库初始化 填充种子数据 LINQ to Entities详解 什么是LINQ to ...
- 8天掌握EF的Code First开发系列之3 管理数据库创建,填充种子数据以及LINQ操作详解
本文出自8天掌握EF的Code First开发系列,经过自己的实践整理出来. 本篇目录 管理数据库创建 管理数据库连接 管理数据库初始化 填充种子数据 LINQ to Entities详解 什么是LI ...
- Spring框架系列(10) - Spring AOP实现原理详解之AOP代理的创建
上文我们介绍了Spring AOP原理解析的切面实现过程(将切面类的所有切面方法根据使用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor).本文在此基 ...
随机推荐
- Linux 设置代理时, 密码出现特殊字符怎么办?
配置代理的格式一般是这样的: $ export https_proxy=https://用户名:密码@代理地址:代理端口 比如需要配置这些: $ export http_proxy=http://Co ...
- mysql8.0关闭log-bin功能
一.查看log-bin是否开启: mysql> show variables like 'log-bin'; 二.关闭log-bin: 在配置文件中的 [mysqld] 配置节中增加 skip- ...
- HTTPS的误解(二)
大家好,我们接着HTTPS的误解(一)接着讲,经常有人会说更换或转移服务器时要购买新证书,服务器SSL证书价格很贵,易维信(EVTrust)给大家澄清了这些容易产生误解的地方,详细见下面文章. 误解四 ...
- [PY3]——IO——文件目录操作
IO—os.shutil—文件目录操作 目录操作 1. 新建 os.mkdir(path[, mode]) 相当于mkdir,新建目录 os.makedirs(path[, mode]) 相当于mkd ...
- jdbc报java.lang.ClassNotFoundException: com.mysql.jdbc.Drive
今天从开始写了一个jdbc连接mysql驱动的程序 真的是各种报错啊 首先这是代码 package com.dmeck; import java.sql.Connection; import java ...
- Html-完整表格
表头th 特殊的单元格:加粗.居中 它的用户是取代td的位置即可 <table border="2"> <tr> <th>姓名</th&g ...
- LINQ操作List<T>
LINQ操作List<T>主要包括: 1.筛选 List<string> stcdList = stcdArray.ToList<string>() .FindAl ...
- 手把手教你用 Keras 实现 LSTM 预测英语单词发音
1. 动机 我近期在研究一个 NLP 项目,根据项目的要求,需要能够通过设计算法和模型处理单词的音节 (Syllables),并对那些没有在词典中出现的单词找到其在词典中对应的押韵词(注:这类单词类似 ...
- Cheatsheet: 2017 07.01 ~ 07.31
Other 8 Key Application Performance Metrics & How to Measure Them The Code Review: The Most Impo ...
- Struts 类型转换之局部和全局配置
我们碰到过很多情况,就是时间日期常常会出现错误,这是我们最头疼的事,在struts2中有一些内置转换器,也有一些需要我们自己配置. 我们为什么需要类型转换呢? 在基于HTTP协议的Web应用中 客户端 ...