C#學習第29天:表達式樹(Expression Trees)

目錄

什么是表達式樹?

?核心概念

1.表達式樹的構建

2. 表達式樹與Lambda表達式?

3.解析和訪問表達式樹

4.動態條件查詢

表達式樹的優勢

1.動態構建查詢

2.LINQ 提供程序支持:

3.性能優化

4.元數據處理

5.代碼轉換和重寫

適用場景?

代碼復雜性的權衡?


什么是表達式樹?


  • 表達式樹是C#中一種數據結構,用于以樹狀方式表示代碼中的表達式,每個節點代表一個操作(如算術運算、方法調用等)。
  • 它們允許你將代碼本身視為數據結構,能夠在運行時動態地分析、修改和執行代碼。
  • 表達式樹最初是在 .NET 3.5 中引入的,主要用于支持 LINQ(語言集成查詢)。

?核心概念


1.表達式樹的構建

  • 表達式樹的核心類型位于 System.Linq.Expressions 命名空間。
  • 可以手動構建表達式樹,也可以通過Lambda表達式隱式構建。
using System;
using System.Linq.Expressions;class Program
{static void Main(){// 創建一個簡單的表達式:x => x + 1ParameterExpression param = Expression.Parameter(typeof(int), "x");BinaryExpression body = Expression.Add(param, Expression.Constant(1));Expression<Func<int, int>> expression = Expression.Lambda<Func<int, int>>(body, param);// 編譯并執行表達式樹Func<int, int> compiledExpression = expression.Compile();int result = compiledExpression(5);Console.WriteLine($"Result: {result}"); // 輸出:Result: 6}
}

?在這個示例中,我們創建了一個簡單的表達式樹表示 x => x + 1,并將其編譯成可執行代碼。

2. 表達式樹與Lambda表達式?

Lambda表達式可以被編譯為委托,也可以被表達式樹捕獲:

Expression<Func<int, int>> square = x => x * x;

此時,square不是一個委托,而是一棵描述 x * x 計算過程的樹,可用于分析和轉換。

3.解析和訪問表達式樹

表達式樹可以遍歷并分析其結構:

void PrintExpression(Expression exp, int level = 0)
{Console.WriteLine(new string(' ', level * 2) + exp.NodeType + " - " + exp.Type);if (exp is BinaryExpression bin){PrintExpression(bin.Left, level + 1);PrintExpression(bin.Right, level + 1);}else if (exp is ParameterExpression param){Console.WriteLine(new string(' ', (level+1) * 2) + "Parameter: " + param.Name);}
}

4.動態條件查詢

我們有一個 Product 類和一個產品列表。我們希望根據產品的價格動態過濾產品。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;public class Product
{public string Name { get; set; }public decimal Price { get; set; }
}class Program
{static void Main(){// 創建產品列表List<Product> products = new List<Product>{new Product { Name = "Laptop", Price = 1000m },new Product { Name = "Smartphone", Price = 500m },new Product { Name = "Tablet", Price = 300m }};// 動態創建表達式樹來過濾價格大于 400 的產品Func<Product, bool> filter = CreatePriceFilter(400m);// 使用生成的過濾器查詢產品var filteredProducts = products.Where(filter).ToList();foreach (var product in filteredProducts){Console.WriteLine($"Product: {product.Name}, Price: {product.Price}");}}static Func<Product, bool> CreatePriceFilter(decimal minPrice){// 創建參數表達式ParameterExpression param = Expression.Parameter(typeof(Product), "product");// 創建訪問屬性表達式MemberExpression priceProperty = Expression.Property(param, "Price");// 創建常量表達式ConstantExpression constant = Expression.Constant(minPrice);// 創建大于運算符表達式BinaryExpression comparison = Expression.GreaterThan(priceProperty, constant);// 創建 lambda 表達式Expression<Func<Product, bool>> lambda = Expression.Lambda<Func<Product, bool>>(comparison, param);// 編譯表達式樹為可執行代碼return lambda.Compile();}
}

1.設置產品列表:

  • ?我們先定義一個簡單的 Product 類和一個包含幾個產品的列表。

2.創建表達式樹:

  • 參數表達式:ParameterExpression param = Expression.Parameter(typeof(Product), "product"); 創建一個參數,表示傳遞給過濾器的 Product 對象。
  • 屬性訪問表達式:MemberExpression priceProperty = Expression.Property(param, "Price"); 訪問傳遞對象的 Price 屬性。
  • 常量表達式:ConstantExpression constant = Expression.Constant(minPrice); 定義過濾條件中的常量值。
  • 比較表達式:BinaryExpression comparison = Expression.GreaterThan(priceProperty, constant); 創建一個比較表達式,檢查 Price 是否大于 minPrice。
  • lambda 表達式:將上述表達式組合成一個完整的 lambda 表達式,并編譯成可執行代碼。

3.應用表達式:

  • 使用 Where 方法將生成的過濾器應用于產品列表,并輸出結果。

表達式樹的優勢


1.動態構建查詢

  • 表達式樹允許你在運行時構建和修改查詢邏輯。這在需要根據用戶輸入或其他動態數據生成不同查詢條件時特別有用。

2.LINQ 提供程序支持:

  • 表達式樹是 LINQ 提供程序(如 LINQ to SQL、Entity Framework)的基礎,它們將表達式樹解析為底層數據源(如數據庫、XML)的查詢語言。這意味著你可以用相同的代碼生成運行在不同數據源上的查詢。

3.性能優化

  • 在某些情況下,表達式樹可以被編譯和緩存,提高重復執行相同邏輯的性能。

4.元數據處理

  • 表達式樹提供對表達式結構的訪問,這使得分析和處理代碼元數據成為可能。這對于開發動態應用程序或框架尤其有用。

5.代碼轉換和重寫

  • 可以編寫代碼來遍歷和修改表達式樹,用于實現代碼轉換或重寫。這對于構建復雜查詢或分析工具有很大幫助。

適用場景?


  • 動態條件查詢:當應用需要支持用戶定義的動態過濾條件時,表達式樹可以靈活地構建這些條件。
  • 跨平臺查詢:在 LINQ to SQL 或 Entity Framework 中,表達式樹可被翻譯成 SQL 查詢,在數據庫執行。
  • 規則引擎和DSL(領域特定語言):在這些場景中,表達式樹可以用于解析和執行用戶定義的規則或查詢?

代碼復雜性的權衡?


  • 雖然表達式樹代碼在某些情況下顯得復雜,但其提供的靈活性和功能在復雜應用中是非常關鍵的。
  • 如果只是簡單的篩選條件,直接使用 Lambda 表達式或 LINQ 查詢語法更為直接和清晰。

示例1:

假設我們有一個產品列表,用戶可以動態選擇多個條件進行過濾,比如根據名稱、價格范圍或庫存狀態等進行篩選。我們需要在運行時根據用戶輸入組合這些條件。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;public class Product
{public string Name { get; set; }public decimal Price { get; set; }public bool InStock { get; set; }
}class Program
{static void Main(){var products = new List<Product>{new Product { Name = "Laptop", Price = 1000, InStock = true },new Product { Name = "Smartphone", Price = 500, InStock = true },new Product { Name = "Tablet", Price = 300, InStock = false }};// 用戶可以選擇動態條件string searchName = "Laptop";decimal? minPrice = 400;decimal? maxPrice = null;bool? inStock = true;// 創建動態查詢表達式var filter = CreateDynamicFilter<Product>(searchName, minPrice, maxPrice, inStock);// 使用生成的過濾器查詢產品var filteredProducts = products.AsQueryable().Where(filter).ToList();foreach (var product in filteredProducts){Console.WriteLine($"Product: {product.Name}, Price: {product.Price}, InStock: {product.InStock}");}}static Expression<Func<T, bool>> CreateDynamicFilter<T>(string name, decimal? minPrice, decimal? maxPrice, bool? inStock){// 參數表達式var parameter = Expression.Parameter(typeof(T), "product");Expression expression = Expression.Constant(true); // 初始謂詞為 true// 根據 name 動態創建條件if (!string.IsNullOrEmpty(name)){var nameProperty = Expression.Property(parameter, "Name");var nameValue = Expression.Constant(name);var nameExpression = Expression.Equal(nameProperty, nameValue);expression = Expression.AndAlso(expression, nameExpression);}// 根據 minPrice 創建條件if (minPrice.HasValue){var priceProperty = Expression.Property(parameter, "Price");var minPriceValue = Expression.Constant(minPrice.Value);var minPriceExpression = Expression.GreaterThanOrEqual(priceProperty, minPriceValue);expression = Expression.AndAlso(expression, minPriceExpression);}// 根據 maxPrice 創建條件if (maxPrice.HasValue){var priceProperty = Expression.Property(parameter, "Price");var maxPriceValue = Expression.Constant(maxPrice.Value);var maxPriceExpression = Expression.LessThanOrEqual(priceProperty, maxPriceValue);expression = Expression.AndAlso(expression, maxPriceExpression);}// 根據 inStock 創建條件if (inStock.HasValue){var stockProperty = Expression.Property(parameter, "InStock");var stockValue = Expression.Constant(inStock.Value);var stockExpression = Expression.Equal(stockProperty, stockValue);expression = Expression.AndAlso(expression, stockExpression);}// 創建 Lambda 表達式return Expression.Lambda<Func<T, bool>>(expression, parameter);}
}

示例2:

針對上文中只針對價格做篩選的示例,那么我們的篩選過程完全可以簡化成如下表達式

var filteredProducts = products.Where(p => p.Price > 400).ToList();

總結來說,是否使用表達式樹取決于你的具體需求和應用場景。在需要動態處理和復雜邏輯的情況下,表達式樹提供了強大的工具支持,而在簡單場景下,直接使用 Lambda 表達式或常規方法更為合適。希望這能幫助你理解表達式樹的適用場景和優勢!

如果你有其他問題或需要進一步的幫助,請隨時告訴我。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/84368.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/84368.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/84368.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

計算機網絡備忘錄

計算機網絡 - 網絡互聯與互聯網 計算機網絡重點學習本章&#xff0c;屬于核心知識 包含網絡層和傳輸層 的 相關協議 計算機網絡層次重點掌握網絡層與傳輸層。其中網絡層主要是IP協議&#xff0c;解決主機-主機通信&#xff0c;傳輸層主要是TCP/UDP 協議&#xff0c;解決應用-…

跨界破局者魯力:用思辨與創新重塑汽車流通行業標桿

來源&#xff1a;投資家 在汽車流通行業深度變革的浪潮中&#xff0c;東莞東風南方汽車銷售服務有限公司塘廈分公司總經理魯力歷經近二十年行業深耕&#xff0c;構建了一條從汽車銷售顧問到區域運營掌舵者的進階范本。作為東風日產體系內兼具理論建構與實戰穿透力的標桿管理者…

玄機-日志分析-IIS日志分析

1.phpstudy-2018站點日志.(.log文件)所在路徑&#xff0c;提供絕對路徑 2.系統web日志中狀態碼為200請求的數量是多少 3.系統web日志中出現了多少種請求方法 4.存在文件上傳漏洞的路徑是什么(flag{/xxxxx/xxxxx/xxxxxx.xxx} 5.攻擊者上傳并且利用成功的webshell的文件名是什…

微信小程序開發知識點

1. 微信小程序開發知識點 1.1. 公共引用 1.1.1. 公共 wxss 在app.wxss文件下寫入組件樣式&#xff0c;也可使用import方式應用單獨公共樣式&#xff0c;避免了每個頁面單獨引用。 import "./public/wxss/base.wxss";1.1.2. 公共組件 在app.json文件下寫入組件&…

安卓基礎(編譯.Class)

方法安全性維護性開源友好度刪除.java用.class? 極低? 差?代碼混淆 (ProGuard)? 中等? 易?AAR 庫模塊? 高? 易? 對于.class 步驟 1&#xff1a;編譯生成 .class 文件 ??打開終端??&#xff08;Android Studio 底部的 Terminal 標簽頁&#xff09; 導航到你的模塊…

golang常用庫之-go-feature-flag庫(特性開關(Feature Flags))

文章目錄 golang常用庫之-go-feature-flag庫&#xff08;特性開關&#xff08;Feature Flags&#xff09;&#xff09;一、什么是特性開關&#xff08;Feature Flags&#xff09;二、go-feature-flag庫我可以使用 GO Feature Flag 做什么&#xff1f;選擇使用 Open Feature SDK…

微前端 - Module Federation使用完整示例

Angular 框架中 項目結構 main-app/src/app/app.module.tsapp.component.ts micro-app/src/app/app.module.tsapp.component.ts主應用配置 安裝必要依賴&#xff1a; ng add angular-architects/module-federation修改 webpack.config.js&#xff1a; const { share, Shar…

麒麟v10系統的docker重大問題解決-不支持容器名稱解析

今天給客戶在麒麟v10Kylin-Server-V10-SP1下安裝nextcloudonlyoffice的時候出現無法連接onlyoffice的問題,經過分析找到了是docker版本過低的原因,現在把解決思路和步驟分享給大家。 一、問題 用一鍵安裝工具,給客戶裝好了系統,Nextcloud可以正常訪問 但是訪問nextcloud中的o…

PyCharm中運行.py腳本程序

1.最近在弄一個python腳本程序&#xff0c;記錄下運行過程。 2.編寫的python程序如下 # # Copyright 2017 Pixar # # Licensed under the terms set forth in the LICENSE.txt file available at # https://openusd.org/license. # # Check whether this script is being run …

學習資料搜集-ARMv8 cache 操作

【ARM64】【cache/MMU】學習總結_arm64 mmu-CSDN博客 [mmu/cache]-ARMV8的cache的維護指令介紹_data cache set allocation-CSDN博客 https://download.csdn.net/blog/column/12036969/139483584 驗證碼_嗶哩嗶哩 【ARM Cache 與 MMU 系列文章 2 -- Cache Coherence及內存順…

Flutter快速上手,入門教程

目錄 一、參考文檔 二、準備工作 下載Flutter SDK&#xff1a; 配置環境 解決環境報錯 zsh:command not found:flutter 執行【flutter doctor】測試效果 安裝Xcode IOS環境 需要安裝brew&#xff0c;通過brew安裝CocoaPods. 復制命令行&#xff0c;打開終端 分別執行…

八股文——JVM

1. JVM組成 1.1 JVM由哪些部分組成&#xff1f;運行流程&#xff1f; Java Virtual Machine&#xff1a;Java 虛擬機&#xff0c;Java程序的運行環境&#xff08;java二進制字節碼的運行環境&#xff09;好處&#xff1a;一次編寫&#xff0c;到處運行&#xff1b;自動內存管理…

在Pnetlab6上繞過TPM、安全啟動和 RAM 檢查安裝windows 11筆記

筆者本次安裝的windows11的鏡像為: zh-cn_windows_11_enterprise_ltsc_2024_x64_dvd_cff9cd2d.iso 1、創建鏡像目錄并上傳iso文件 mkdir /opt/unetlab/addons/qemu/win-win11x64-2024-LTSC //目錄名稱務必按照官方文檔格式,否則無法識別 目錄創建完成后,將.iso格式鏡像上…

PCL點云庫入門(第18講)——PCL庫點云特征之3DSC特征描述3D shape context descriptor

一、3DSC&#xff08;3D Shape Context&#xff09;特征算法原理 1. 背景 3DSC 是一種描述三維點云局部形狀的特征描述子&#xff0c;受二維 Shape Context 的啟發。它用于捕捉點云某一點局部的幾何分布信息&#xff0c;對點云配準、識別等任務非常有效。 2. 基本思想 3DSC…

SpringBoot+Mysql校園跑腿服務平臺系統源碼

&#x1f497;博主介紹&#x1f497;&#xff1a;?在職Java研發工程師、專注于程序設計、源碼分享、技術交流、專注于Java技術領域和畢業設計? 溫馨提示&#xff1a;文末有 CSDN 平臺官方提供的老師 Wechat / QQ 名片 :) Java精品實戰案例《700套》 2025最新畢業設計選題推薦…

分庫分表的取舍

文章目錄 大數據量下采用**水平分表**的缺點**1. 跨表查詢復雜性與性能下降****2. 數據分布不均衡****3. 分布式事務與一致性問題****4. 擴展性受限****5. 查詢條件限制與索引管理復雜****6. 數據遷移與維護成本高****7. 業務邏輯復雜度增加****總結** shardingJdbc分片策略**1…

Vue3解決“找不到模塊@/components/xxx.vue或其相應的類型聲明ts文件(2307)”

問題 1&#xff1a;如果沒有這個env.d.ts文件&#xff0c;就新建 declare module "*.vue" {import { DefineComponent } from "vue";const component: DefineComponent<{}, {}, any>;export default component; }2&#xff1a;如果有tsconfig.json文…

計算機視覺與深度學習 | 基于MATLAB的圖像特征提取與匹配算法總結

基于MATLAB的圖像特征提取與匹配算法全面指南 圖像特征提取與匹配 基于MATLAB的圖像特征提取與匹配算法全面指南一、圖像特征提取基礎特征類型分類二、點特征提取算法1. Harris角點檢測2. SIFT (尺度不變特征變換)3. SURF (加速魯棒特征)4. FAST角點檢測5. ORB (Oriented FAST …

如何通過API接口獲取淘寶商品列表?操作詳解

一、準備工作 注冊開發者賬號 訪問淘寶開放平臺官網/萬邦開放平臺&#xff0c;完成企業開發者認證&#xff08;個人賬號權限受限&#xff09;&#xff0c;使用已有淘寶賬號可直接登錄。創建應用并填寫基本信息&#xff08;如應用名稱、類型等&#xff09;&#xff0c;系統生成A…

大數據驅動企業決策智能化的路徑與實踐

&#x1f4dd;個人主頁&#x1f339;&#xff1a;慌ZHANG-CSDN博客 &#x1f339;&#x1f339;期待您的關注 &#x1f339;&#x1f339; 一、引言&#xff1a;數據驅動的企業競爭力重構 在這個瞬息萬變的商業時代&#xff0c;“快者勝”的競爭邏輯愈發明顯。企業如何在復雜環…