C#3.0新增功能10 表达式树 02 说明
表达式树是定义代码的数据结构。 它们基于编译器用于分析代码和生成已编译输出的相同结构。表达式树和 Roslyn API 中用于生成分析器和 CodeFixes 的类型之间存在很多相似之处。 (分析器和 CodeFixes 是 NuGet 包,用于对代码执行静态分析,并可为开发人员建议可能的修补程序。)两者概念相似,且最终结果是一种数据结构,该结构允许以有意义的方式对源代码进行检查。 但是,表达式树基于一组与 Roslyn API 完全不同的类和 API。
让我们来举一个简单的示例。 以下是一个代码行:
var sum = + ;
如果要将其作为一个表达式树进行分析,则该树包含多个节点。 最外面的节点是具有赋值 (var sum = 1 + 2;
) 的变量声明语句,该节点包含若干子节点:变量声明、赋值运算符和一个表示等于号右侧的表达式。 该表达式被进一步细分为表示加法运算、该加法左操作数和右操作数的表达式。
让我们稍微深入了解一下构成等于号右侧的表达式。 该表达式是 1 + 2
。 这是一个二进制表达式。 更具体地说,它是一个二进制加法表达式。 二进制加法表达式有两个子表达式,表示加法表达式的左侧和右侧节点。 此处的两个节点都是常量表达式:左操作数是值 1
,右操作数是值 2
。
直观地看,整个语句是一个树:应从根节点开始,遍历到树中的每个节点,以查看构成语句的代码:
- 具有赋值 (
var sum = 1 + 2;
) 的变量声明语句- 隐式变量类型声明 (
var sum
)赋值运算符 (=
)- 隐式 var 关键字 (
var
) - 变量名称声明 (
sum
)
- 隐式 var 关键字 (
- 二进制加法表达式 (
1 + 2
)- 左操作数 (
1
) - 加法运算符 (
+
) - 右操作数 (
2
)
- 左操作数 (
- 隐式变量类型声明 (
这可能看起来很复杂,但它功能强大。 按照相同的过程,可以分解更加复杂的表达式。 请思考此表达式:
var finalAnswer = this.SecretSauceFunction(currentState.createInterimResult(),
currentState.createSecondValue(, ),
decisionServer.considerFinalOptions("hello")
)
+ MoreSecretSauce('A', DateTime.Now, true);
上述表达式也是具有赋值的变量声明。 在此情况下,赋值的右侧是一棵更加复杂的树。 我不打算分解此表达式,但请思考一下不同的节点可能是什么。 存在使用当前对象作为接收方的方法调用,其中一个调用具有显式 this
接收方,一个调用不具有此接收方。 存在使用其他接收方对象的方法调用,存在不同类型的常量参数。 最后,存在二进制加法运算符。 该二进制加法运算符可能是对重写的加法运算符的方法调用(具体取决于 SecretSauceFunction()
或 MoreSecretSauce()
的返回类型),解析为对为类定义的二进制加法运算符的静态方法调用。
尽管具有这种感知上的复杂性,但上面的表达式创建了一种树形结构,可以像第一个示例那样轻松地导航此结构。 可以保持遍历子节点,以查找表达式中的叶节点。 父节点将具有对其子节点的引用,且每个节点均具有一个用于介绍节点类型的属性。
表达式树的结构非常一致。 了解基础知识后,你甚至可以理解以表达式树形式表示的最复杂的代码。 优美的数据结构说明了 C# 编译器如何分析最复杂的 C# 程序并从该复杂的源代码创建正确的输出。
熟悉表达式树的结构后,你会发现通过快速获得的知识,你可处理许多越来越高级的方案。 表达式树的功能非常强大。
除了转换算法以在其他环境中执行之外,表达式树还可用于在执行代码前轻松编写检查代码的算法。 可以编写参数为表达式的方法,然后在执行代码之前检查这些表达式。 表达式树是代码的完整表示形式:可以看到任何子表达式的值。 可以看到方法和属性名称。 可以看到任何常数表达式的值。 还可以将表达式树转换为可执行的委托,并执行代码。
通过表达式树的 API,可创建表示几乎任何有效代码构造的树。 但是,出于尽可能简化的考虑,不能在表达式树中创建某些 C# 习惯用语。 其中一个示例就是异步表达式(使用 async
和 await
关键字)。 如果需要异步算法,则需要直接操作 Task
对象,而不是依赖于编译器支持。 另一个示例是创建循环。 通常,通过使用 for
、foreach
、while
或 do
循环对其进行创建。 正如稍后可以在本系列中看到的那样,表达式树的 API 支持单个循环表达式,该表达式包含控制重复循环的 break
和 continue
表达式。
不能执行的操作是修改表达式树。 表达式树是不可变的数据结构。 如果想要改变(更改)表达式树,则必须创建基于原始树副本但包含所需更改的新树。
C#3.0新增功能10 表达式树 02 说明的更多相关文章
- C#3.0新增功能10 表达式树 05 解释表达式
连载目录 [已更新最新开发文章,点击查看详细] 表达式树中的每个节点将是派生自 Expression 的类的对象. 该设计使得访问表达式树中的所有节点成为相对直接的递归操作. 常规策略是从根节点 ...
- C#3.0新增功能10 表达式树 07 翻译(转换)表达式
连载目录 [已更新最新开发文章,点击查看详细] 本篇将介绍如何访问表达式树中的每个节点,同时生成该表达式树的已修改副本. 以下是在两个重要方案中将使用的技巧. 第一种是了解表达式树表示的算法,以 ...
- C#3.0新增功能10 表达式树 01 简介
连载目录 [已更新最新开发文章,点击查看详细] 如果你使用过 LINQ,则会有丰富库(其中 Func 类型是 API 集的一部分)的经验. (如果尚不熟悉 LINQ,建议阅读 LINQ 教程,以 ...
- C#3.0新增功能10 表达式树 03 支持表达式树的框架类型
连载目录 [已更新最新开发文章,点击查看详细] 存在可与表达式树配合使用的 .NET Core framework 中的类的大型列表. 可以在 System.Linq.Expressions 查 ...
- C#3.0新增功能10 表达式树 06 生成表达式
连载目录 [已更新最新开发文章,点击查看详细] 到目前为止,你所看到的所有表达式树都是由 C# 编译器创建的. 你所要做的是创建一个 lambda 表达式,将其分配给一个类型为 Expressi ...
- C#3.0新增功能10 表达式树 04 执行表达式
连载目录 [已更新最新开发文章,点击查看详细] 表达式树 是表示一些代码的数据结构. 它不是已编译且可执行的代码. 如果想要执行由表达式树表示的 .NET 代码,则必须将其转换为可执行的 IL ...
- C#3.0新增功能09 LINQ 基础02 LINQ 查询简介
连载目录 [已更新最新开发文章,点击查看详细] 查询 是一种从数据源检索数据的表达式. 查询通常用专门的查询语言来表示. 随着时间的推移,人们已经为各种数据源开发了不同的语言:例如,用于关系数据 ...
- C#基础拾遗系列之二:使用ILSpy探索C#7.0新增功能点
C#基础拾遗系列之二:使用ILSpy探索C#7.0新增功能点 第一部分: C#是一种通用的,类型安全的,面向对象的编程语言.有如下特点: (1)面向对象:c# 是面向对象的范例的一个丰富实现, 它 ...
- C#2.0新增功能06 协变和逆变
连载目录 [已更新最新开发文章,点击查看详细] 在 C# 中,协变和逆变能够实现数组类型.委托类型和泛型类型参数的隐式引用转换. 协变保留分配兼容性,逆变则与之相反. 以下代码演示分配兼容性.协 ...
随机推荐
- 解析 Qt 字库移植并能显示中文 (下篇)
原文http://mobile.51cto.com/symbian-272563.htm 本文介绍的是Qt 字库移植并能显示中文,需要的字体库文件,一般是多个.具体移植那一个,看你使用的字库是什么了, ...
- 一次C#和C++的实际应用性能比较(C++允许我们使用任何手段来提高效率,只要愿意做出足够的努力)
05年时,在微软的Rico Mariani做了一次实际应用的C#和C++的性能比较.事情起源于微软著名的元老Raymond Chen(在下敬仰的超级牛人)用C++写了一个英汉词典程序,来描述讲解优化C ...
- 小抄:选择 Unity 的对象生命周期管理员
Unity 框架提供了数种生命周期管理员,各有相同和相异之处.刚开始接触时,难免头昏. 制作这张小抄,只是为了要帮助自己理解和记忆.如果你也用 Untiy,或可参考看看. 文字說明: Transien ...
- xmanager小技巧
使用manager时候,左键选中之后,直接右键粘贴,能带来效率的提升.虽然是小技巧,但有人还是不知道,这里简单写一下,供需要的同学参考. 简单二步设置: 1.工具-选项
- Servlet 3.0异步特性初探
Servlet 是 Java 为了编写服务端程序而定义的一个接口规范,在 Servlet 3.0 以后支持了异步的操作. 最近项目添加了一个代码热部署的功能,在客户端输入信号,信号到达 Web 服务器 ...
- 《菜鸟也要学会C》-和大家聊一聊
简介 为什么要出本系列作品? 怎么学好C? 学完这套课程后,我的编程会怎么样? 1.1为什么要出本系列作品? 随着大部分人喜欢编程,大部分人都有一个毛病,就是想要急切的学完编程.其实这种思想是错误的, ...
- 直播技术:从性能参数到业务大数据,浅谈直播CDN服务监控
线上服务的有效监控和数据收集,一直是后端服务离不开的话题.直播作为一种经典的分布式系统,监控以及数据收集更是必不可少的工作.如何对海量的服务集群有效的监控和保活,又如何抓取集群中的碎片数据中来优化服务 ...
- java源码解析之String类(三)
上一节我们主要讲了String类的一些不是很常用的方法,其中需要掌握的如下,我就不再赘述了 public int length() public boolean isEmpty() public by ...
- 系统学习 Java IO (八)----装饰流 FilterInputStream/FilterOutputStream
目录:系统学习 Java IO---- 目录,概览 这两个流的作用是:"封装其它的输入流,并为它们提供额外的功能" 他们的直接子类有: BufferedInputStream 的作 ...
- 【jar包管理】Maven BOM
BOM Alibaba Spring Boot Dependencies is a Maven BOM used to manage the versions of most used Alibaba ...