C# 表達式樹 創建、生成、使用、lambda轉成表達式樹~表達式樹的知識詳解

来源:https://www.cnblogs.com/whuanle/archive/2018/11/29/10039237.html
-Advertisement-
Play Games

筆者最近學了表達式樹這一部分內容,為了加深理解,寫文章鞏固知識,如有錯誤,請評論指出~ 表達式樹的概念 表達式樹的創建有 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號面試成功


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 什麼是列表 定義: 能裝對象的對象 在python中使用 [] 來描述列表, 內部元素用逗號隔開. 對數據類型沒有要求 列表存在索引和切片. 和字元串是一樣的. 2. 相關的增刪改查操作 添加: 1. append() 追加 2. insert(位置, 元素) 插入指定元素到指定位置 刪除: ...
  • 題意 "題目鏈接" Sol 神仙題Orzzzz 題目可以轉化為從$\leqslant M$的質數中選出$N$個$xor$和為$0$的方案數 這樣就好做多了 設$f(x) = [x \text{是質數}]$ $n$次異或FWT即可 快速冪優化一下,中間不用IFWT,最後轉一次就行(~~然而並不知道為什 ...
  • 1.進程同步/串列(鎖) 進程之間數據不共用,但共用同一套文件系統,所以訪問同一個文件,或同一個列印終端,沒有問題,但共用帶來的是競爭容易錯亂,如搶票時。這就需讓進程一個個的進去保證數據安全,也就是加鎖處理,Lock 併發,效率高,但是競爭同一個文件時,導致數據混亂 加鎖,由併發改成了串列,犧牲了運 ...
  • 最後來看看前面一直說的 Engine(工作引擎) ,工作引擎介面是 在`ServiceProvider IServiceProviderEngine`介面和其實現類的整體結構 IServiceProviderEngine類型繼承關係 繼承了 介面,也就是說工作引擎也具有 GetService() 方 ...
  • ​這篇文章還是回到實際的基礎封裝過程實現層面,用一個小東西來演示如何在常見業務代碼中梳理職責 ...
  • 第一篇:把代碼連接到容器 第二篇:定製Docker鏡像 第三篇:發佈鏡像 第四篇:容器間的連接 Docker Compose簡介 Compose是一個用來定義和運行多容器Docker應用的工具。使用Compose的時候,你可以使用一個YAML文件來配置你應用的服務。然後根據配置,使用一個命令即可創建 ...
  • Audio Graph AudioGraph 是 Windows.Media.Audio 命名空間下提供的音頻處理介面之一。 可以通過 AudioGraph 的靜態方法 CreateAsync 來實例化一個 AudioGraph 對象,實例化的時候需要傳入一個參數 AudioGraphSetting ...
  • 輸入參數P1,P2代表PLC中浮點數儲存的兩個寄存器獲取的數據 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...