C 表示式樹

2021-10-05 16:23:51 字數 3654 閱讀 7815

在使用 ef 開中我們經常使用 xx.where(p=>p.name="張三") 查詢資料,之把能這樣是因為 ef 框架會把這些c#**轉成sql語句, 其中主要用到的就是表示式樹,今天就來學習一下表示式樹。

func func = (a, b) => a +b;

expressionint,int,int>> expression = (a, b) => a + b;

上面分別是 func 委託和表示式樹,看上去很相似,左邊只多了 expression<> 右邊完全一樣,其實還是有很大區別的,對於委託我們只能傳遞引數來呼叫,內部的**在程式執行中是無從得知的,而表示式樹在這點上相反,表示式樹是一種資料結構,可以通過 c# **清晰的獲取內部的細節。

上面的例子中是使用 lambda 為表示式樹賦值,其實還有另一種寫法

parameterexpression parametera = expression.parameter(typeof(int),"a"

);parameterexpression parameterb = expression.parameter(typeof(int),"b"

);binaryexpression binaryexpression =expression.add(parametera, parameterb);

expression

int, int, int>> expression = expression.lambdaint, int, int>>(binaryexpression,parametera,parameterb);

上面的例子對應於第一種寫法,第一種寫法是語法糖,其實編譯器最終生成還是這種**,可以通過反編譯軟體來驗證。

認識一下表示式樹的主要部分

body:表示式主體,例子中是二元表示式,常用的還有

nodetype:節點型別,例子中是 lambda ,常用還有的+,-,*,/,>,=,

parameters:表示式的引數,a 和 b

console.writeline(expression.body);

console.writeline(expression.nodetype);

console.writeline(expression.parameters[

0]);

console.writeline(expression.parameters[

1]);

輸出是

(a + b)

lambdaab

body 的型別是 expression,例子中的是二元表示式,所以要轉換成 binaryexpression 類來檢視資訊

binaryexpression binaryexpression =(binaryexpression)expression.body;

console.writeline(binaryexpression.left);

console.writeline(binaryexpression.right);

console.writeline(binaryexpression.nodetype);

輸出是a

badd

剛才是乙個簡單表示式,再來看兩個複雜點的,經過第一次解析後 left 和 right 就是第一種解析的表示式,可以把 left 和 right 再解析一次,最終完全解析,不管多複雜的表示式都可以像這樣解析出來

上面的例子只是為了了解表示式樹結構,用這種方法解析存在兩個問題

一是 binaryexpression 這裡固定了只能解析二元表示式,如果是其它表示式就會報錯

二是不知道需要解析多少層才解析完

要解析表示式樹要用 c# 裡的 expressionvisitor 類,這個類就是專門解析表示式樹的,它是乙個抽象類,需要建個類繼承它,使用過程如下,首先呼叫父類 visit 方法,在 visit 中會判斷表示式的型別是一元(對應visitunary)、二元(對應visitbinary),常量(對應visitconstant)、引數(對應visitparameter)等表示式,然後就會進對應的解析方法中支解析,比如二元表示式的解析方法就是 visitbinary,然後我們重寫 visitbinary 

下面是使用 expressionvisitor 解析表示式樹的例子,這麼說並不完全對,解析**是 expressionvisitor 已經寫好的,我們做的只解析過程中加入一些自己的**而已

最後來實現乙個簡單的由表示式樹生成sql語句的功能

class

myvisitor : expressionvisitor

protected

override

expression visitbinary(binaryexpression node)

public

string

getsqlstring()

protected

override

expression visitconstant(constantexpression node)

else

return

base

.visitconstant(node);

}protected

override

expression visitparameter(parameterexpression node)

return

base

.visitparameter(node);

}protected

override

expression visitmember(memberexpression node)

public

string

expressiontypetosql(expressiontype expressiontype)}}

expressionbool>> expression = p=>p.name=="

張三"&&p.name!="李四"

;myvisitor myvisitor = new

myvisitor();

myvisitor.visit(expression);

console.writeline(myvisitor.getsqlstring());

寫得有點亂,忘見諒

表示式 表示式樹 表示式求值

總時間限制 1000ms 記憶體限制 65535kb 描述 眾所周知,任何乙個表示式,都可以用一棵表示式樹來表示。例如,表示式a b c,可以表示為如下的表示式樹 a b c 現在,給你乙個中綴表示式,這個中綴表示式用變數來表示 不含數字 請你將這個中綴表示式用表示式二叉樹的形式輸出出來。輸入輸入分...

Lambda表示式表示式樹

在c 3.0中,繼匿名方法之後出現了lambda 表示式,使表達更為簡潔 快捷。lambda 表示式使用lambda 運算子 來定義,語法如下 引數列表 lambda 運算子的左邊是輸入引數,定義lambda表示式的接收引數列表,右邊包含表示式或語句塊,表示將表示式的值或語句塊返回的值傳給左邊的引數...

C 表示式樹Expression

表示式相加 常量表示式 expression firstarg expression.constant 2 expression secondarg expression.constant 4 相加 expression addexpression expression.add firstarg,s...