DLR学习笔记(01)
DLR表达式是DLR的核心骨架。
DLR表达式和编程语言相似,它构造诸如循环表达式,赋值语句,方法调用表达式等。比如,c#的hello world程序:
- Console.Writeline(“Hello World”);
等价的DLR表达式如下:
- MethodInfo method = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) });
- Expression callExpression = Expression.Call(null,method,Expression.Constant("Hello World"));
此处,由于WriteLine是静态方法,所以第一个参数为null。
DLR表达式和普通的编程语言有几处不同点。
代码即数据,数据即代码
在DLR表达式中,代码就是数据,很容易对他做处理。
和CLR的IL相同,DLR表达式也作为多个语言的公共标准。DLR表达式值定义抽象语法,而没有具体语法。而且还支持序列号,我们可以序列化抽象语法到具体语法,或者相反。
代码即数据
代码在DLR表达式中就是数据,作为对象存在于内存中。对比C#代码,在运行时是一系列IL质量。DLR表达式不能如C#代码那样运行,要运行必须解释它,或者转换成IL代码。比如:
- Action callDelegate = Expression.Lambda<Action>(callExpression).Compile();
- callDelegate();
第一行代码把callExpression包裹为一个拉姆达表达式,并且调用Compile方法编译该表达式,使之成为可以调用的.NET委托。第一行代码把数据转换成IL指令。第二行执行这个编译后的指令。
可以看到,写DLR表达式比C#代码更复杂。写DLR表达式的原因之一就是一旦代码作为对象在内存中,那就可以很简单的去处理它,相对处理IL指令而言。当然如果想要执行它,还必须通过解释或者编译把对象转换为代码。LINQ to SQL就是一个对DLR表达式转换成代码例子,它将DLR表达式树转换成SQL语句。
和CLR一样的公共标准
DLR表达式就像一组IL指令,设计为多个语言的公共标准。DLR表达式是诸如IronPython和IronRuby原因的公共标准标准。如下图2-1:
具体语法和序列化
DLR表达式和编程语言的一个不同点就是DLR表达式只有抽象语法,没有具体语法。具体语法比如C#中,写下5+2。编译代码,转换器会转换代码。在内存中表示为一个对象的树。这个树的表现法就是一个抽象的语法树,代表了抽象语法。多个具体语法可以映射到一个抽象语法上。
DLR表达式支持序列化。当序列化一个DLR表达式树到一个文件。那么这个表达式树的文本格式就是一个DLR表达式的具体语法。
和DLR表达式不同,一个典型的编程语言如C#定义一个具体语法和一个抽象语法。所以具体语法和抽象语法是一一对应。
表达式和语句(Expressions vs. Statements)
表达式和语句的不同点很简单,表达式有输出值,语句没有。如下面的例子。这些表达式都是有输出值的。
- 5 + 2
- x = 7 //assignment expression
- i = j = 7 //this line of code consists of two assignment expressions
- someObject.Foo() //method call expression
i = j = 7这句语句比较有趣,它是由2个表达式组合的一个表达式: j = 7 和i = (j = 7)表达式j=7输出7作为值,传递给变量i。如果j=7不是一个表达式,那么i就得不到赋值,编译就会出错。
接下来看一下语句
- int i; //variable declaration statement
- x = 5; //assignment statement
- someObject.Foo(); //method call statement
第一行是声明本地变量,是一个语句。
第二行如果加上分号的话是赋值表达式,没加分号就是赋值语句。
类似的,如果方法调用表达式后面加上分号,也可得到方法调用语句。
C#中if语言结构是一个语句,而不是表达式。
if (true) //if statement
Console.WriteLine(“Hello”);
下面的代码是无效的,因为if语句没有值可以赋给x
//This code is not valid in C#
x = if (true)
Console.WriteLine(“Hello”);
表达式和语句,对于DLR来说有什么关系?很简单,DLR表达式只有表达式,没有语句。这就是为什么成为DLR表达式而不是DLR语句。看个例子,加深理解。listing2-1是一段无效的C#代码。
Listing 2-1. Invalid C# Code That Assigns an If Statement to a Variable.
- {
- String x = "Hello";
- String y = if (true) //This causes compilation error.
- x.ToLower();
- }
再看Listing2-2,和上面的几乎是等价。
Listing 2-2. Assigning an If Statement to a Variable in DLR Expression
- MethodInfo method = typeof(String).GetMethod("ToLower", new Type[] { });
- ParameterExpression x = Expression.Variable(typeof(String), "x");
- ParameterExpression y = Expression.Variable(typeof(String), "y");
- Expression blockExpression = Expression.Block(new ParameterExpression[] { x, y },
- Expression.Assign(x, Expression.Constant("Hello")),
- Expression.Assign(y,
- Expression.Condition(Expression.Constant(true),
- Expression.Call(x, method),
- Expression.Default(typeof(String)),
- typeof(String)))
- );
- Func<String> blockDelegate = Expression.Lambda<Func<String>>(blockExpression).Compile();
- String result = blockDelegate();
- Console.WriteLine(result);
DLR代码写了一堆才完成C#代码完成的功能。Listing2-2中有几个有趣的地方,首先,blockExpression变量是一个容器,容纳更小的子表达式。DLR block表达式的value就是最后一个子表达式的值。这和Listing2-1不同。Listing2-1中,一对括号中的代码形成一个块语句,也没有输出值。
第二个不同点就是第6行,把条件表达式赋值给参数表达式y,条件表达式等价于C#中的if语句。参数表达式y等价于参数y。和C#不同,if条件结构在DLR中是一个表达式,不是语句,他有输出值可以赋值给变量。
第13行编译整个块表达式为代码——一个委托类型Func<String>。 Func<String>意思就是一个委托,无输入参数,输出参数是string对象。这个委托类型需要匹配块表达式。DLR块表达式有值,这个值就是最后一个子表达式的值。在这个例子中,最后一个子表达式就是赋值表达式,把条件表达式赋值给变量y表达式,这个赋值表达式的值是typeof(String),那么整个快表达式的输出值也是typeof(String)
Listing 2-2 输出值是hello.
转载于:https://blog.51cto.com/cnn237111/859639
DLR学习笔记(01)相关推荐
- JavaWeb黑马旅游网-学习笔记01【准备工作】
Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...
- JavaWeb-综合案例(用户信息)-学习笔记01【列表查询】
Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb-综合案例(用户信息)-学习笔记01[列表查询] JavaWeb-综合案例(用户信息)-学习笔记02[登录功能] JavaWeb-综合案 ...
- Servlet和HTTP请求协议-学习笔记01【Servlet_快速入门-生命周期方法、Servlet_3.0注解配置、IDEA与tomcat相关配置】
Java后端 学习路线 笔记汇总表[黑马程序员] Servlet和HTTP请求协议-学习笔记01[Servlet_快速入门-生命周期方法.Servlet_3.0注解配置.IDEA与tomcat相关配置 ...
- Tomcat学习笔记01【Web相关概念、Tomcat基本操作】
Java后端 学习路线 笔记汇总表[黑马程序员] Tomcat学习笔记01[Web相关概念.Tomcat基本操作][day01] Tomcat学习笔记02[Tomcat部署项目][day01] 目录 ...
- XML学习笔记01【xml_基础、xml_约束】
Java后端 学习路线 笔记汇总表[黑马程序员] XML学习笔记01[xml_基础.xml_约束][day01] XML学习笔记02[xml_解析][day01] 目录 01 xml_基础 今日内容 ...
- Bootstrap学习笔记01【快速入门、栅格布局】
Java后端 学习路线 笔记汇总表[黑马程序员] Bootstrap学习笔记01[快速入门.栅格布局][day01] Bootstrap学习笔记02[全局CSS样式.组件和插件.案例_黑马旅游网][d ...
- JavaScript学习笔记01【基础——简介、基础语法、运算符、特殊语法、流程控制语句】
w3school 在线教程:https://www.w3school.com.cn JavaScript学习笔记01[基础--简介.基础语法.运算符.特殊语法.流程控制语句][day01] JavaS ...
- HTML/CSS学习笔记01【概念介绍、基本标签】
w3cschool菜鸟教程.CHM(腾讯微云):https://share.weiyun.com/c1FaX6ZD HTML/CSS学习笔记01[概念介绍.基本标签.表单标签][day01] HTML ...
- JDBC学习笔记01【JDBC快速入门、JDBC各个类详解、JDBC之CRUD练习】
黑马程序员-JDBC文档(腾讯微云)JDBC笔记.pdf:https://share.weiyun.com/Kxy7LmRm JDBC学习笔记01[JDBC快速入门.JDBC各个类详解.JDBC之CR ...
最新文章
- python中字符串编码转换
- 驱动设计的思想:面向对象/分层/分离
- Quartz-Job 详解
- cad vba 打开文件对话框_CAD文件损坏?无法打开?别急,这八种方法或许能帮到你...
- ITK:手动遍历具有成形邻域的图像区域
- fragment入门
- 【文末送书】调参太费力?自动化机器学习来帮你!
- 由锚点失效引发的hasLayout探究
- Navicat的快捷键
- 二叉树创建,遍历,叶子,深度
- Mybatis原理分析之二:框架整体设计
- 如何在 Mac 上使用快速操作工作流程?
- (期末复习)html元素上下左右置中对齐的三种方法
- 计算机二级考试报名如何上传照片?
- 学简单python好学吗_python好学吗语法简单吗举个例子
- python妹子图爬虫5千张高清大图突破防盗链福利5千张福利高清大图
- Django系列(1)-自动化生成API文档
- Python——类(class)的定义及使用
- 计算机考研专硕好考还是学硕好考,考研是学硕难考还是专硕难考?很多人都猜错了...
- SV学习(4)——数据作用域和类型转换 $cast()
热门文章
- 打造一个宇宙 星系模拟产生对宇宙进化惊人见解
- 推荐!神经进化才是深度学习未来的发展之路!
- 异构智能吴韧:物联网是“伪命题”?智联网才是未来
- 取消Windows server 2008关机提示备注的方法
- jQuery Validate
- Linux系统管理工具-iostat、free、ps、netstat、tcpdump
- 你需要一个首席数据官吗?
- MFC窗体控件随窗体变化
- Java多线程之Callable接口的实现
- PostgreSQL 10.1 手册_部分 II. SQL 语言_第 5 章 数据定义_5.11. 外部数据