C#表達(dá)式樹講解
表達(dá)式樹的概念
- 表達(dá)式樹的創(chuàng)建有 Lambda法 和 組裝法。
- 學(xué)習(xí)表達(dá)式樹需要 委托、Lambda、Func<> 基礎(chǔ)。
- 表達(dá)式樹 形狀可以參考二叉樹。
- 可以把表達(dá)式樹理解成 數(shù)學(xué)表達(dá)式。
數(shù)學(xué)表達(dá)式的所有常量、符號為表達(dá)式樹的底節(jié)點(diǎn)。每一次計(jì)算生成的結(jié)果是一個(gè)結(jié)點(diǎn),或者說他們的共同結(jié)點(diǎn)就是他們應(yīng)該進(jìn)行的運(yùn)算。
生成表達(dá)式樹
表達(dá)式樹的創(chuàng)建有 Lambda表達(dá)式法
和 組裝法
為了方便,這里指定生成的表達(dá)式為 ( i * j ) + ( x * y )
他們的運(yùn)算是這樣的
Lambda 生成表達(dá)式樹
在控制臺創(chuàng)建應(yīng)用,需要引入
using System.Linq.Expressions;
1,創(chuàng)建表達(dá)式
(系統(tǒng)自動把 Lambda表達(dá)式 轉(zhuǎn)為表達(dá)式樹,當(dāng)然,不是所有的 Lambda表達(dá)式都能轉(zhuǎn)為表達(dá)式樹,詳細(xì)請參考文章后面的“系統(tǒng)自動把 Lambda表達(dá)式 轉(zhuǎn)為 表達(dá)式樹” 一節(jié))
Expression<Func<int, int, int, int, int>> func = (i, j, x, y) => (i * j) + (x * y);
2,輸出系統(tǒng)轉(zhuǎn)換的表達(dá)式
輸入這一行代碼后運(yùn)行,看看控制臺輸出的表達(dá)式樹
Console.WriteLine(func);
3,把代碼轉(zhuǎn)為數(shù)據(jù)
(把代碼當(dāng)作數(shù)據(jù)來使用)
var compile = func.Compile(); //或 Func<int, int, int, int, int> compile = func.Compile();
4,代入運(yùn)算
int result = compile(12, 13, 14, 15); //把具體數(shù)字代入表達(dá)式并運(yùn)算 Console.WriteLine(result); //輸出表達(dá)式結(jié)果
完整代碼如下
Expression<Func<int, int, int, int, int>> func = (i, j, x, y) => (i * j) + (x * y); Console.WriteLine(func); //輸出表達(dá)式 var compile = func.Compile(); //把代碼轉(zhuǎn)為數(shù)據(jù) //或 Func<int, int, int, int, int> compile = func.Compile(); int result = compile(12, 13, 14, 15); //把具體數(shù)字代入表達(dá)式并運(yùn)算 Console.WriteLine(result); //輸出表達(dá)式結(jié)果 Console.ReadKey();
控制臺輸出
組裝法生成表達(dá)式樹
表達(dá)式由 "符號" 和 運(yùn)算符組成,。
使用ParameterExpression
類型 來修飾參數(shù),使用Expression.Parameter(Type type,string name)
實(shí)例化參數(shù)。
1,生成 a b d 參數(shù)
ParameterExpression a = Expression.Parameter(typeof(int), "i"); ParameterExpression b = Expression.Parameter(typeof(int), "j"); ParameterExpression c = Expression.Parameter(typeof(int), "x"); ParameterExpression d = Expression.Parameter(typeof(int), "y");
分析:
i、j、x、y是結(jié)點(diǎn)名稱,a、b、c、d是實(shí)例名稱。不用留精力思考我上面 a b c d i j x y 的名稱設(shè)定。
ParameterExpression 表示創(chuàng)建一個(gè)節(jié)點(diǎn),Parameter表示一個(gè)命名的參數(shù)表達(dá)式,詳細(xì)請參考文章后面的 “Expression 參數(shù)分類”。
Expression.Parameter(Type type,string name) 表示這個(gè)節(jié)點(diǎn)的屬性。
2,生成結(jié)點(diǎn)
Expression r1 = Expression.Multiply(a, b); //乘法運(yùn)行 Expression r2 = Expression.Multiply(c, d); //乘法運(yùn)行
分析:
創(chuàng)建了 ( i * j ) 和 ( x * y ) 兩個(gè)運(yùn)算
Multiply 表示不進(jìn)行溢出檢查的乘法運(yùn)算。Expression 里有 85種 操作方法,更多加減乘除比較大小等操作在文章后面詳細(xì)附上,參考 “ 運(yùn)算操作符” 一節(jié)。
3,生成終結(jié)點(diǎn)
Expression result = Expression.Add(r1, r2); //相加
4,生成表達(dá)式樹、轉(zhuǎn)換、輸出表達(dá)式樹、代入數(shù)據(jù)進(jìn)行運(yùn)算
Expression<Func<int, int, int, int, int>> func = Expression.Lambda<Func<int, int, int, int, int>>(result, a, b, c, d); var com = func.Compile(); Console.WriteLine("表達(dá)式" + func); Console.WriteLine(com(12, 12, 13, 13));
完整代碼如下
ParameterExpression a = Expression.Parameter(typeof(int), "i"); ParameterExpression b = Expression.Parameter(typeof(int), "j"); Expression r1 = Expression.Multiply(a, b); //乘法運(yùn)行 ParameterExpression c = Expression.Parameter(typeof(int), "x"); ParameterExpression d = Expression.Parameter(typeof(int), "y"); Expression r2 = Expression.Multiply(c, d); //乘法運(yùn)行 Expression result = Expression.Add(r1, r2); //相加 //以上代碼產(chǎn)生結(jié)點(diǎn) //生成表達(dá)式 Expression<Func<int, int, int, int, int>> func = Expression.Lambda<Func<int, int, int, int, int>>(result, a, b, c, d); var com = func.Compile(); Console.WriteLine("表達(dá)式" + func); Console.WriteLine(com(12, 12, 13, 13)); Console.ReadKey();
控制臺界面
補(bǔ)充說明
1,系統(tǒng)自動把 Lambda表達(dá)式 轉(zhuǎn)為 表達(dá)式樹
對 lambda表達(dá)式 的要求 只能 由 傳入?yún)?shù) 和 返回參數(shù) 兩部分表示。lambda表達(dá)式 不能包含其它判斷、循環(huán)等的代碼。
錯誤舉例
Expression<Func<int, int, int, int, int>> func = (a, b, c, d) => { if (a < 10) { a += 1; } /* * 其它操作代碼 */ return a + b + c + d; };
把那些東西通通刪除,修改后:
Expression<Func<int, int, int, int, int>> func = (a, b, c, d) => a + b + c + d;
這樣的 “最簡” 的 lambda表達(dá)式 才能被系統(tǒng)自動轉(zhuǎn)為表達(dá)式樹
2,運(yùn)算操作符
一般數(shù)學(xué)上,有加減乘除、取余、求冪等操作,而在程序中,運(yùn)算操作符可以有更多的選擇,達(dá) 85 種。
筆者這里給出一張圖列出部分方法。
微軟官方 的操作運(yùn)算符列表https://docs.microsoft.com/zh-cn/dotnet/api/system.linq.expressions.expression?view=netframework-4.7.2
估計(jì)大家看微軟的文檔會有點(diǎn)不爽~這里推薦大神翻譯、整理的列表http://chabaoo.cn/article/234265.htm
3,Expression 參數(shù)
以數(shù)學(xué)橢圓周長公式:L = 2πb + 4(a-b) ,a 為長半軸,b 為短半軸, 進(jìn)行舉例
Parameter 類似于 數(shù)學(xué)的 未知數(shù) 如 a 、 b;使用方法
ParameterExpression a = Expression.Parameter(typeof(int), "a")
ParameterExpression b = Expression.Parameter(typeof(int), "b")
Constant 表示一個(gè)常數(shù),例如2πb 中的 2 或者 2π;使用方法
ConstantExpression define = Expression.Constant(2);
其它更多參數(shù)分類 請查看http://chabaoo.cn/article/234265.htm
這里附上部分截取圖片
4,Expression 的操作方法
表示加減乘除等運(yùn)算的方法。以下圖舉例
Multiply(a,b) 為乘法,Add(r1,r2)為加法。
當(dāng)然,并沒有這么簡單,他們都有相關(guān)的重載方法和高級的使用用途。
請查看http://chabaoo.cn/article/234265.htm
這里給出部分截圖
5,表達(dá)式樹的高級用法
表達(dá)式樹可以結(jié)合 數(shù)據(jù)庫查詢 或 Linq,衍生很多高級操作。
例如 動態(tài)查詢、遍歷表達(dá)式樹、轉(zhuǎn)成成SQL where 子句等等,限于幅度,筆者不再贅述。
下面的鏈接可以查看 System.Linq.Expressions 的所有類型對象。https://docs.microsoft.com/zh-cn/dotnet/api/System.Linq.Expressions?view=netframework-4.7.2
到此這篇關(guān)于C#表達(dá)式樹講解的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#實(shí)現(xiàn)listview Group收縮擴(kuò)展的方法
這篇文章主要介紹了C#實(shí)現(xiàn)listview Group收縮擴(kuò)展的方法,結(jié)合實(shí)例形式分析了listview控件的相關(guān)使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2016-03-03C#實(shí)現(xiàn)websocket雙向通信的示例代碼
本文基于WebSocketSharp實(shí)現(xiàn)了websocket雙向通信,除基本的客戶端向服務(wù)端發(fā)送消息外,也支持客戶端向指定的客戶端發(fā)送消息、群發(fā)消息,其他協(xié)議可自定義,廢話不多說,直接上干貨,需要的朋友可以參考下2024-06-06基于WPF實(shí)現(xiàn)描點(diǎn)導(dǎo)航功能
這篇文章主要為大家詳細(xì)介紹了如何基于WPF實(shí)現(xiàn)描點(diǎn)導(dǎo)航功能,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以了解一下2025-06-06C#實(shí)現(xiàn)獲取設(shè)置IP地址小工具
c# 開發(fā),方便更改IP地址。由于公司和家里的ip設(shè)置不一樣,公司要求手動設(shè)置,在家可以自動獲取IP,切都是無線網(wǎng)絡(luò),為了方便操作,故做了這個(gè)小工具!2015-06-06