筆者最近學了表達式樹這一部分內容,為了加深理解,寫文章鞏固知識,如有錯誤,請評論指出~ 表達式樹的概念 表達式樹的創建有 Lambda法 和 組裝法。 學習表達式樹需要 委托、Lambda、Func<> 基礎。 表達式樹 形狀可以參考 二叉樹。 可以把表達式樹理解成 數學表達式。 數學表達式的所有常 ...
筆者最近學了表達式樹這一部分內容,為了加深理解,寫文章鞏固知識,如有錯誤,請評論指出~
表達式樹的概念
- 表達式樹的創建有 Lambda法 和 組裝法。
- 學習表達式樹需要 委托、Lambda、Func<> 基礎。
- 表達式樹 形狀可以參考 二叉樹。
- 可以把表達式樹理解成 數學表達式。
數學表達式的所有常量、符號為表達式樹的底節點。每一次計算生成的結果是一個結點,或者說他們的共同結點就是他們應該進行的運算。
生成表達式樹
表達式樹的創建有 Lambda表達式法 和 組裝法
為了方便,這裡指定生成的表達式為 ( i * j ) + ( x * y )
他們的運算是這樣的
Lambda 生成表達式樹
在控制台創建應用,需要引入
using System.Linq.Expressions;
1,創建表達式
(系統自動把 Lambda表達式 轉為表達式樹,當然,不是所有的 Lambda表達式都能轉為表達式樹,詳細請參考文章後面的“系統自動把 Lambda表達式 轉為 表達式樹” 一節)
Expression<Func<int, int, int, int, int>> func = (i, j, x, y) => (i * j) + (x * y);
2,輸出系統轉換的表達式
輸入這一行代碼後運行,看看控制台輸出的表達式樹
Console.WriteLine(func);
3,把代碼轉為數據
(把代碼當作數據來使用)
var compile = func.Compile(); //或 Func<int, int, int, int, int> compile = func.Compile();
4,代入運算
int result = compile(12, 13, 14, 15); //把具體數字代入表達式並運算 Console.WriteLine(result); //輸出表達式結果
完整代碼如下
Expression<Func<int, int, int, int, int>> func = (i, j, x, y) => (i * j) + (x * y); Console.WriteLine(func); //輸出表達式 var compile = func.Compile(); //把代碼轉為數據 //或 Func<int, int, int, int, int> compile = func.Compile(); int result = compile(12, 13, 14, 15); //把具體數字代入表達式並運算 Console.WriteLine(result); //輸出表達式結果 Console.ReadKey();
控制台輸出
組裝法生成表達式樹
表達式由 "符號" 和 運算符組成,。
使用 ParameterExpression 類型 來修飾參數,使用 Expression.Parameter(Type type,string name) 實例化參數。
1,生成 a b d 參數
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 是結點名稱,a、b、c、d 是實例名稱。不用留精力思考我上面 a b c d i j x y 的名稱設定。
ParameterExpression 表示創建一個節點,Parameter 表示一個命名的參數表達式,詳細請參考文章後面的 “Expression 參數分類”。
Expression.Parameter(Type type,string name) 表示這個節點的屬性。
2,生成結點
Expression r1 = Expression.Multiply(a, b); //乘法運行 Expression r2 = Expression.Multiply(c, d); //乘法運行
分析:
創建了 ( i * j ) 和 ( x * y ) 兩個運算
Multiply 表示 不進行溢出檢查的乘法運算。Expression 里有 85種 操作方法,更多加減乘除比較大小等操作在文章後面詳細附上,參考 “ 運算操作符” 一節。
3,生成終結點
Expression result = Expression.Add(r1, r2); //相加
4,生成表達式樹、轉換、輸出表達式樹、代入數據進行運算
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("表達式" + 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); //乘法運行 ParameterExpression c = Expression.Parameter(typeof(int), "x"); ParameterExpression d = Expression.Parameter(typeof(int), "y"); Expression r2 = Expression.Multiply(c, d); //乘法運行 Expression result = Expression.Add(r1, r2); //相加 //以上代碼產生結點 //生成表達式 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("表達式" + func); Console.WriteLine(com(12, 12, 13, 13)); Console.ReadKey();
控制台界面
補充說明
1,系統自動把 Lambda表達式 轉為 表達式樹
對 lambda表達式 的要求 只能 由 傳入參數 和 返回參數 兩部分表示。lambda表達式 不能包含其它判斷、迴圈等的代碼。
錯誤舉例
Expression<Func<int, int, int, int, int>> func = (a, b, c, d) => { if (a < 10) { a += 1; } /* * 其它操作代碼 */ return a + b + c + d; };View Code
把那些東西通通刪除,修改後:
Expression<Func<int, int, int, int, int>> func = (a, b, c, d) => a + b + c + d;
這樣的 “最簡” 的 lambda表達式 才能被系統自動轉為表達式樹
2,運算操作符
一般數學上,有加減乘除、取餘、求冪等操作,而在程式中,運算操作符可以有更多的選擇,達 85 種。
筆者這裡給出一張圖列出部分方法。
微軟官方 的操作運算符列表 https://docs.microsoft.com/zh-cn/dotnet/api/system.linq.expressions.expression?view=netframework-4.7.2
估計大家看微軟的文檔會有點不爽~這裡推薦大神翻譯、整理的列表 https://blog.csdn.net/zhuqinfeng/article/details/70168337
3,Expression 參數
以數學 橢圓周長公式:L = 2πb + 4(a-b) ,a 為長半軸,b 為短半軸, 進行舉例
Parameter 類似於 數學的 未知數 如 a 、 b;使用方法
ParameterExpression a = Expression.Parameter(typeof(int), "a")
ParameterExpression b = Expression.Parameter(typeof(int), "b")
Constant 表示一個常數,例如 2πb 中的 2 或者 2π ;使用方法
ConstantExpression define = Expression.Constant(2);
其它更多參數分類 請查看 https://blog.csdn.net/zhuqinfeng/article/details/70168337
這裡附上部分截取圖片
4,Expression 的操作方法
表示加減乘除等運算的方法。以下圖舉例
Multiply(a,b) 為乘法,Add(r1,r2) 為加法。
當然,並沒有這麼簡單,他們都有相關的重載方法和高級的使用用途。
請查看 https://blog.csdn.net/zhuqinfeng/article/details/70168337
這裡給出部分截圖
5,表達式樹的高級用法
表達式樹可以結合 資料庫查詢 或 Linq,衍生很多高級操作。
例如 動態查詢、遍歷表達式樹、轉成成 SQL where 子句等等,限於幅度,筆者不再贅述。
下麵的鏈接可以查看 System.Linq.Expressions 的所有類型對象。https://docs.microsoft.com/zh-cn/dotnet/api/System.Linq.Expressions?view=netframework-4.7.2
好好學習,天天向上~期望 3號面試成功