DLR表达式是DLR的核心骨架。

DLR表达式和编程语言相似,它构造诸如循环表达式,赋值语句,方法调用表达式等。比如,c#的hello world程序:

  1. Console.Writeline(“Hello World”);

等价的DLR表达式如下:

  1. MethodInfo method = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) });
  2. Expression callExpression = Expression.Call(null,method,Expression.Constant("Hello World"));

此处,由于WriteLine是静态方法,所以第一个参数为null。

DLR表达式和普通的编程语言有几处不同点。

代码即数据,数据即代码

在DLR表达式中,代码就是数据,很容易对他做处理。

和CLR的IL相同,DLR表达式也作为多个语言的公共标准。DLR表达式值定义抽象语法,而没有具体语法。而且还支持序列号,我们可以序列化抽象语法到具体语法,或者相反。

代码即数据

代码在DLR表达式中就是数据,作为对象存在于内存中。对比C#代码,在运行时是一系列IL质量。DLR表达式不能如C#代码那样运行,要运行必须解释它,或者转换成IL代码。比如:

  1. Action callDelegate = Expression.Lambda<Action>(callExpression).Compile();
  2. 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)


表达式和语句的不同点很简单,表达式有输出值,语句没有。如下面的例子。这些表达式都是有输出值的。

  1. 5 + 2
  2. x = 7 //assignment expression
  3. i = j = 7 //this line of code consists of two assignment expressions
  4. someObject.Foo() //method call expression

i = j = 7这句语句比较有趣,它是由2个表达式组合的一个表达式: j = 7 和i = (j = 7)表达式j=7输出7作为值,传递给变量i。如果j=7不是一个表达式,那么i就得不到赋值,编译就会出错。

接下来看一下语句

  1. int i; //variable declaration statement
  2. x = 5; //assignment statement
  3. 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.

  1. {
  2. String x = "Hello";
  3. String y = if (true) //This causes compilation error.
  4. x.ToLower();
  5. }

再看Listing2-2,和上面的几乎是等价。

Listing 2-2. Assigning an If Statement to a Variable in DLR Expression

  1. MethodInfo method = typeof(String).GetMethod("ToLower", new Type[] { });
  2. ParameterExpression x = Expression.Variable(typeof(String), "x");
  3. ParameterExpression y = Expression.Variable(typeof(String), "y");
  4. Expression blockExpression = Expression.Block(new ParameterExpression[] { x, y },
  5. Expression.Assign(x, Expression.Constant("Hello")),
  6. Expression.Assign(y,
  7. Expression.Condition(Expression.Constant(true),
  8. Expression.Call(x, method),
  9. Expression.Default(typeof(String)),
  10. typeof(String)))
  11. );
  12. Func<String> blockDelegate = Expression.Lambda<Func<String>>(blockExpression).Compile();
  13. String result = blockDelegate();
  14. 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)相关推荐

  1. JavaWeb黑马旅游网-学习笔记01【准备工作】

    Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...

  2. JavaWeb-综合案例(用户信息)-学习笔记01【列表查询】

    Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb-综合案例(用户信息)-学习笔记01[列表查询] JavaWeb-综合案例(用户信息)-学习笔记02[登录功能] JavaWeb-综合案 ...

  3. Servlet和HTTP请求协议-学习笔记01【Servlet_快速入门-生命周期方法、Servlet_3.0注解配置、IDEA与tomcat相关配置】

    Java后端 学习路线 笔记汇总表[黑马程序员] Servlet和HTTP请求协议-学习笔记01[Servlet_快速入门-生命周期方法.Servlet_3.0注解配置.IDEA与tomcat相关配置 ...

  4. Tomcat学习笔记01【Web相关概念、Tomcat基本操作】

    Java后端 学习路线 笔记汇总表[黑马程序员] Tomcat学习笔记01[Web相关概念.Tomcat基本操作][day01] Tomcat学习笔记02[Tomcat部署项目][day01] 目录 ...

  5. XML学习笔记01【xml_基础、xml_约束】

    Java后端 学习路线 笔记汇总表[黑马程序员] XML学习笔记01[xml_基础.xml_约束][day01] XML学习笔记02[xml_解析][day01] 目录 01 xml_基础 今日内容 ...

  6. Bootstrap学习笔记01【快速入门、栅格布局】

    Java后端 学习路线 笔记汇总表[黑马程序员] Bootstrap学习笔记01[快速入门.栅格布局][day01] Bootstrap学习笔记02[全局CSS样式.组件和插件.案例_黑马旅游网][d ...

  7. JavaScript学习笔记01【基础——简介、基础语法、运算符、特殊语法、流程控制语句】

    w3school 在线教程:https://www.w3school.com.cn JavaScript学习笔记01[基础--简介.基础语法.运算符.特殊语法.流程控制语句][day01] JavaS ...

  8. HTML/CSS学习笔记01【概念介绍、基本标签】

    w3cschool菜鸟教程.CHM(腾讯微云):https://share.weiyun.com/c1FaX6ZD HTML/CSS学习笔记01[概念介绍.基本标签.表单标签][day01] HTML ...

  9. JDBC学习笔记01【JDBC快速入门、JDBC各个类详解、JDBC之CRUD练习】

    黑马程序员-JDBC文档(腾讯微云)JDBC笔记.pdf:https://share.weiyun.com/Kxy7LmRm JDBC学习笔记01[JDBC快速入门.JDBC各个类详解.JDBC之CR ...

最新文章

  1. python中字符串编码转换
  2. 驱动设计的思想:面向对象/分层/分离
  3. Quartz-Job 详解
  4. cad vba 打开文件对话框_CAD文件损坏?无法打开?别急,这八种方法或许能帮到你...
  5. ITK:手动遍历具有成形邻域的图像区域
  6. fragment入门
  7. 【文末送书】调参太费力?自动化机器学习来帮你!
  8. 由锚点失效引发的hasLayout探究
  9. Navicat的快捷键
  10. 二叉树创建,遍历,叶子,深度
  11. Mybatis原理分析之二:框架整体设计
  12. 如何在 Mac 上使用快速操作工作流程?
  13. (期末复习)html元素上下左右置中对齐的三种方法
  14. 计算机二级考试报名如何上传照片?
  15. 学简单python好学吗_python好学吗语法简单吗举个例子
  16. python妹子图爬虫5千张高清大图突破防盗链福利5千张福利高清大图
  17. Django系列(1)-自动化生成API文档
  18. Python——类(class)的定义及使用
  19. 计算机考研专硕好考还是学硕好考,考研是学硕难考还是专硕难考?很多人都猜错了...
  20. SV学习(4)——数据作用域和类型转换 $cast()

热门文章

  1. 打造一个宇宙 星系模拟产生对宇宙进化惊人见解
  2. 推荐!神经进化才是深度学习未来的发展之路!
  3. 异构智能吴韧:物联网是“伪命题”?智联网才是未来
  4. 取消Windows server 2008关机提示备注的方法
  5. jQuery Validate
  6. Linux系统管理工具-iostat、free、ps、netstat、tcpdump
  7. 你需要一个首席数据官吗?
  8. MFC窗体控件随窗体变化
  9. Java多线程之Callable接口的实现
  10. PostgreSQL 10.1 手册_部分 II. SQL 语言_第 5 章 数据定义_5.11. 外部数据