DLR學習筆記 01

2021-09-21 20:48:27 字數 4194 閱讀 7952

dlr表示式是dlr的核心骨架。

dlr表示式和程式語言相似,它構造諸如迴圈表示式,賦值語句,方法呼叫表示式等。比如,c#的hello world程式:

console.writeline(「hello world」); 

等價的dlr表示式如下:

methodinfo method = 

typeof

(console).getmethod(

"writeline"

, new

type );  

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(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.

再看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(

newparameterexpression ,  

expression.assign(x, expression.constant(

"hello"

)),  

expression.assign(y,  

expression.condition(expression.constant(

true

),  

expression.call(x, method),  

expression.default(

typeof

(string)),  

typeof

(string)))  

);  

funcblockdelegate = expression.lambda>(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。 func意思就是乙個委託,無輸入引數,輸出引數是string物件。這個委託型別需要匹配塊表示式。dlr塊表示式有值,這個值就是最後乙個子表示式的值。在這個例子中,最後乙個子表示式就是賦值表示式,把條件表示式賦值給變數y表示式,這個賦值表示式的值是typeof(string),那麼整個快表示式的輸出值也是typeof(string)

listing 2-2 輸出值是hello.

學習筆記 01

在網上搜尋了一些資料,由於不知道哪些入門容易,所以先看看找到的資料,也對.net有個初步了解。將資料作了個整理 net framework 執行環境 visual studio net 開發工具 microsoft windows server 2003 企業伺服器 microsoft office...

學習筆記 CentOS 學習筆記01

簡單的做個課堂筆記 虛擬機器用的是vmware,系統是centos cd etc sysconfig network scripts pwdls 顯示列表 cat ifcfg eth0 檢視檔案內容 vi ifcfg eth0 進入vi編輯器 onboot no 原始設定 x逐字刪除 d刪除整行 a...

php學習筆記 01

環境變數 argv 包含所有從命令 文字中傳遞給指令碼的引數.argc 包含從命令列傳遞給指令碼的引數的總數.php self 包含現在正在執行的指令碼名稱.但是,如果php是從命令列執行的,這個變數不可用。http get vars 包含一組用http get方法檢索到的並儲存在當前指令碼中的變數...