網(wǎng)站首頁 編程語言 正文
前言
我們書接上文,我們在了解LINQ下面有說到在本地查詢IEnumerbale主要是用委托來作為傳參,而解析型查詢
IQueryable則用Expression來作為傳參:
public static IEnumerable<T> Where<T>(this IEnumerable<T> enumable, Func<T, bool> func) public static IQueryable<T> Where<T>(this IQueryable<T> queryable, Expression<Func<T, bool>> func)
那么我們就來聊聊有關(guān)表達式Expression里面的東西吧
Expression與Expression Tree
首先我們來寫下一些代碼:
Expression<Func<int, int>> expression = (num) => num + 5; Console.WriteLine($"NodeType:{expression.NodeType}"); Console.WriteLine($"Body:{expression.Body}"); Console.WriteLine($"Body Type: {expression.Body.GetType()}"); Console.WriteLine($"Body NodeType: {expression.Body.NodeType}");
輸出如下:
NodeType:Lambda
Body:(num + 5)
Body Type: System.Linq.Expressions.SimpleBinaryExpression
Body NodeType: Add
我們將expression轉(zhuǎn)為LambdaExpression看看都有啥:
if (expression.NodeType == ExpressionType.Lambda) { var lambda = (LambdaExpression)expression; var parameter = lambda.Parameters.Single(); Console.WriteLine($"parameter.Name:{parameter.Name}"); Console.WriteLine($"parameter.Type:{parameter.Type}"); Console.WriteLine($"parameter.ReturnType:{lambda.ReturnType}"); }
輸出如下:
parameter.Name:num
parameter.Type:System.Int32
parameter.ReturnType:System.Int32
由于我們知道expression.Body是BinaryExpression,那么我們就將其轉(zhuǎn)為它,然后我們繼續(xù)看下去:
if (expression.Body.NodeType == ExpressionType.Add) { var binaryExpreesion = (BinaryExpression)expression.Body; Console.WriteLine($"Left Type:{binaryExpreesion.Left.GetType()}"); Console.WriteLine($"Left NodeType:{binaryExpreesion.Left.NodeType}"); Console.WriteLine($"Right Type:{binaryExpreesion.Right.GetType()}"); Console.WriteLine($"Right NodeType:{binaryExpreesion.Right.NodeType}"); if (binaryExpreesion.Left is ParameterExpression parameterExpreesion) { Console.WriteLine($"parameterExpreesion.Name:{parameterExpreesion.Name}"); Console.WriteLine($"parameterExpreesion.Type:{parameterExpreesion.Type}"); } if (binaryExpreesion.Right is ConstantExpression constantExpreesion) { Console.WriteLine($"constantExpreesion.Value:{constantExpreesion.Value}" ); } }
輸出如下:
Left Type:System.Linq.Expressions.PrimitiveParameterExpression`1[System.Int32]
Left NodeType:Parameter
Right Type:System.Linq.Expressions.ConstantExpression
Right NodeType:Constant
parameterExpreesion.Name:num
parameterExpreesion.Type:System.Int32
constantExpreesion.Value:5
最后我們將表達式樹轉(zhuǎn)為委托:
var @delegate = expression.Compile(); Console.WriteLine(@delegate?.Invoke(2));
輸出:
7 //2+5
實際上,通過Expression<Func<int, int>> expression = (num) => num + 5;,賦值后的expression 變成了一個表達式樹,它的結(jié)構(gòu)是這樣的:
而有意思的是二元表達式樹BinaryExpression是一個二叉樹,而LambdaExpression則是一個支持參數(shù)的表達式,能夠通過其Parameters屬性知道傳入的參數(shù)的類型和數(shù)量,通過ReturnType知道返回值是什么類型
而我們再看看整個關(guān)于Expression的繼承關(guān)系鏈:
因此,我們也可以顯式的通過各自Expreesion的實現(xiàn)子類來創(chuàng)建跟lambda表達式一樣的結(jié)果:
var parameterExpreesion1 = Expression.Parameter(typeof(int), "num"); BinaryExpression binaryExpression1 = Expression.MakeBinary(ExpressionType.Add, parameterExpreesion1, Expression.Constant(5)); Expression<Func<int, int>> expression1 = Expression.Lambda<Func<int, int>>(binaryExpression1, parameterExpreesion1); if (expression1.Body.NodeType == ExpressionType.Add) { var binaryExpreesion1 = (BinaryExpression)expression1.Body; Console.WriteLine($"Left Type:{binaryExpreesion1.Left.GetType()}"); Console.WriteLine($"Left NodeType:{binaryExpreesion1.Left.NodeType}"); Console.WriteLine($"Right Type:{binaryExpreesion1.Right.GetType()}"); Console.WriteLine($"Right NodeType:{binaryExpreesion1.Right.NodeType}"); if (binaryExpreesion1.Left is ParameterExpression parameterExpreesion2) { Console.WriteLine($"parameterExpreesion.Name:{parameterExpreesion2.Name}"); Console.WriteLine($"parameterExpreesion.Type:{parameterExpreesion2.Type}"); } if (binaryExpreesion1.Right is ConstantExpression constantExpreesion1) { Console.WriteLine($"constantExpreesion.Value:{constantExpreesion1.Value}"); } var @delegate1 = expression1.Compile(); Console.WriteLine(@delegate1(2));
輸出結(jié)果:
Left Type:System.Linq.Expressions.PrimitiveParameterExpression`1[System.Int32]
Left NodeType:Parameter
Right Type:System.Linq.Expressions.ConstantExpression
Right NodeType:Constant
parameterExpreesion.Name:num
parameterExpreesion.Type:System.Int32
constantExpreesion.Value:5
result:7
我們則發(fā)現(xiàn),結(jié)果是一模一樣的,但是費勁了很多,因此用lamda構(gòu)建表達式樹是一個非常愉快的語法糖,讓你能夠愉快的在使用表達式和表達式樹
參考
- 《C#7.0核心技術(shù)指南》
源碼
BlogCodeSample/ExpressionSample at main · ZhengDaoWang/BlogCodeSample
總結(jié)
原文鏈接:https://www.cnblogs.com/ryzen/p/15674630.html
相關(guān)推薦
- 2022-07-19 Python數(shù)據(jù)分析?Pandas?Series對象操作_python
- 2022-04-10 Python實現(xiàn)讀取excel中的圖片功能_python
- 2022-06-25 pytorch中permute()函數(shù)用法補充說明(矩陣維度變化過程)_python
- 2022-07-14 android實現(xiàn)多點觸摸效果_Android
- 2022-04-08 Python裝飾器中@property使用詳解_python
- 2022-11-02 React組件實例三大屬性state?props?refs使用詳解_React
- 2022-06-07 關(guān)于python調(diào)用c++動態(tài)庫dll時的參數(shù)傳遞問題_C 語言
- 2023-02-27 python實現(xiàn)定時任務(wù)的八種方式總結(jié)_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支