DLR学习笔记(01)

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:

ad6425318720420187187fcbadad23bf[4]

具体语法和序列化

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();  

再看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.  
  13.            Func<String> blockDelegate = Expression.Lambda<Func<String>>(blockExpression).Compile();  
  14.            String result = blockDelegate();  
  15.            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.

你可能感兴趣的:(.net,编程语言,表达式,hello,dlr)