[.net 物件導向程式設計進階] (6) Lamda表示式(二) 表示式樹快速入門

yubinfeng發表於2015-07-04

[.net 物件導向程式設計進階] (6) Lamda表示式(表示式樹快速入門

本節導讀:

認識表示式樹(Expression Tree),學習使用Lambda建立表示式樹,解析表示式樹。

學習表示式在程式設計中的優點:比如構造動態查詢、動態構造表示式樹完成未知物件屬性訪問,比反射的效能高出很多。我們可以說表示式樹才是Lambda的精髓,是我們必須要熟練掌握並靈活運用的。 

1.關於表示式樹(Expression Tree) 

表示式樹以樹形資料結構表示程式碼,其中每一個節點都是一種表示式,比如方法呼叫和 x < y 這樣的二元運算等。 

表示式樹,對於剛接觸的人來說,比較難以理解。那麼什麼是表示式樹,通俗點來說,就是使用一種樹形的資料結構來快取表示式。 

2.表示式樹能幫我們做點什麼? 

面我們說了表示式樹是一種資料結構,那麼為什麼要把表示式定義成表示式樹呢,轉成一種資料結構,能幫我們做點什麼?先明確了他能為我們帶來什麼,才有動力繼續看下去。 

說到他的作用,當然是非常有用的,我們在很多場景下都要使用他,當表示式變為一個表示式樹的資料結構時,表示式就變為一個物件,你可以對錶達式樹中的物件元素(表示式的程式碼)進行編輯和運算。下面列舉幾種常用的: 

  1. 通過修改表示式樹能夠動態修改可執行程式碼
  2. 在不同資料庫中執行 LINQ 查詢
  3. 建立動態查詢。
  4. 完成類似反射訪問未知物件屬性,通過動態構造表示式樹,生成委託。 

3. 表示式樹的建立 

名稱空間: System.Linq.Expressions  

建立表示式樹示例: 

Expression<Func<int, int, bool>>  expression  =  (num,num2)=> num < num2;

這個語句包含三個部分: 

  1. 一個宣告Func<int, int, int> function
  2. 一個等號: =
  3. 一個lambda表示式(num,num2)=> num < num2; 

expression 就是一個型別為Expression<T>的表示式樹,可以看出,他並非是一個可執行程式碼,而是一種表示式樹的資料結構。 

 4. 表示式樹結構的構成 

Expression<Func<int, int, bool>>  expression  =  (num,num2)=> num < num2;

通過監視我們定義好的表示式樹,可以看到其構成 

 下面我們對幾個重要屬性說明: 

  • Body: 得到表示式的主體例:(num < num2)    其中,Body中又包含屬性Left和Right  在上例中分別為num和num2
  • Parameters: 得到lambda表示式的引數。 例 {num,num2}
  • NodeType: 獲取樹的節點的ExpressionType。共45種不同值,包含所有表示式節點各種可能的型別。例如返回常量,例如返回引數,例如取兩個值的小值(<),例如取兩個值的大值(>),例如將值相加(+),等等。例:Lambda
  • Type: 獲取表示式的一個靜態型別 例:Func<int, int, bool>  
  • ReturnType:這個是表示式的返回型別   例:bool 

還有一些其他屬性Name、CanReduce等,這些不是很常用。  

5.解析表示式樹 

  我們瞭解了表示式樹結構的組成,解析表示式變得相當容易了,下面我們直接通過一個示例來完成對一個表示式樹的解析:  

//表示式樹(Expression)
Expression<Func<int, int, bool>> expression = (x, y) => x!=0 && x==y+1;

BinaryExpression exr = expression.Body as BinaryExpression;
IReadOnlyList<ParameterExpression> param = expression.Parameters as IReadOnlyList<ParameterExpression>;
BinaryExpression left = exr.Left as BinaryExpression;
BinaryExpression right = exr.Right as BinaryExpression;
ExpressionType exrType = exr.NodeType;

ParameterExpression leftLeft = left.Left as ParameterExpression;
ConstantExpression leftRight = left.Right as ConstantExpression;
ExpressionType leftType = left.NodeType;

ParameterExpression rightLeft = right.Left as ParameterExpression;
BinaryExpression rightRight = right.Right as BinaryExpression;
ExpressionType rightType = right.NodeType;

ParameterExpression rightRightLeft = rightRight.Left as ParameterExpression;
ExpressionType rightRightType = rightRight.NodeType;
ConstantExpression rightRightRight = rightRight.Right as ConstantExpression;          

Console.WriteLine(exr.ToString());

 表示式樹的解析,裡面的元素無非就下面幾種:  

A.BinaryExpression 包含二元運算子的表示式 

B.ParameterExpression命名的參數列達式 ,一般是一組引數集合IReadOnlyList<ParameterExpression> 

C.ConstantExpression常量值的表示式 

D.ExpressionType節點型別 

對於上面示例的表達樹結構,我用圖例的方式展現如下:

  

對於上面的結構,我們可以按上面程式碼中的物件元素變數與之一一對應如下圖:  

 

要點:

本節我們介紹了表示式樹在.NET物件導向程式設計中的作用、表示式樹的建立與解析,相信小夥伴們對錶達式樹這種結構比較瞭解了。

表示式樹(Expression Tree)就是一種使用物件的方式來描述表示式。這也正是.NET一切皆是物件的思想體現。 

下一節我們會介紹動態建立一個表示式樹結構、會舉列說明幾種表示式樹在.NET程式設計中的應用。

==============================================================================================  

 返回目錄

 <如果對你有幫助,記得點一下推薦哦,如有有不明白或錯誤之處,請多交流>  

<對本系列文章閱讀有困難的朋友,請先看《.net 物件導向程式設計基礎》>

<轉載宣告:技術需要共享精神,歡迎轉載本部落格中的文章,但請註明版權及URL>

.NET 技術交流群:467189533    .NET 程式設計

==============================================================================================   

相關文章