Linq之Expression高階篇(常用表示式型別)
目錄
寫在前面
首先回顧一下上篇文章的內容,上篇文章介紹了表示式樹的解析和編譯。如果忘記了,可以通過下面系列文章提供的入口進行復習。這篇文章將介紹常見的表示式型別。
常見的表示式型別都有個共同的基類Expression。建立這些型別的物件,是通過API的方式建立的(也就是Expression的靜態方法),首先引入名稱空間:
1 using System.Linq.Expressions;
系列文章
變量表達式
在表示式樹中使用ParameterExpression或者ParameterExpression表示式表示變數型別,下面看一個例子,我們定義一個int型別的變數i:
// ParameterExpression表示命名的引數表示式。 ParameterExpression i = Expression.Parameter(typeof(int),"i");
或者使用
1 ParameterExpression j = Expression.Variable(typeof(int), "j");
通過f12轉到定義,發現這兩個方法的註釋幾乎是一樣的。靜態方法Parameter第一個引數:定義的引數型別,第二個引數:為引數名稱。
常量表達式
在表示式樹中使用ConstantExpression表示式表示具有常量值的表示式。,看一個例子,我們定義一個int型別的常量5.並將該值賦值給上面定義的變數i
1 // ParameterExpression表示命名的引數表示式。 2 ParameterExpression i = Expression.Parameter(typeof(int), "i"); 3 //ParameterExpression j = Expression.Variable(typeof(int), "j"); 4 ConstantExpression constExpr = Expression.Constant(5, typeof(int)); 5 //建立一個表示賦值運算的 System.Linq.Expressions.BinaryExpression 6 //表示包含二元運算子的表示式。 7 BinaryExpression binaryExpression = Expression.Assign(i, constExpr);
Constrant方法第一個引數:常量,第二個引數為什麼型別的常量。
這裡提到了BinaryExpression表示式,該表示式標識包含二元運算子的表示式,類似與=,>這樣的二元表示式都可以使用BinaryExpression表示式來表示。
除錯模式下,在自動視窗檢視當前表示式的DebugView屬性,這個屬性在調試表達式樹的時候是非常有用的:
變數:
常量:
二元表示式:
通過觀察上面的圖,可知變數除錯模式下DebugView屬性將顯示前面帶有“$”符號的 ParameterExpression 變數名稱。那麼如果引數沒有名稱,則會為其分配一個自動生成的名稱,例如 $var1 或 $var2(這裡不再舉例)。
條件表示式
在很多時候,我們都需要使用條件表示式來過濾一些資料,然後返回滿足條件的資料,在表示式中有這樣一些表示式滿足你的需求。
常見運算子
>,>=
<,<=
if....then:如果滿足條件那麼..
if...then...else:如果滿足條件執行某某程式碼,否則執行另外的邏輯
一個例子
IfThenElse方法
1 public static ConditionalExpression IfThenElse( 2 Expression test, 3 Expression ifTrue, 4 Expression ifFalse 5 )
1 bool test = true; 2 ConditionalExpression codition = Expression.IfThenElse( 3 //條件 4 Expression.Constant(test), 5 //如果條件為true,呼叫WriteLine方法輸出“條件為true” 6 Expression.Call( 7 null, 8 typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }), 9 Expression.Constant("條件為true") 10 ), 11 //如果條件false 12 Expression.Call( 13 null, 14 typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }), 15 Expression.Constant("條件為false") 16 ) 17 ); 18 //編譯表示式樹,輸出結果 19 Expression.Lambda<Action>(codition).Compile()();
輸出結果
例子描述:條件test包裝為常量表達式,因為test為true,所以執行iftrue的表示式,並呼叫WriteLine方法打印出資訊。
賦值表示式
=
還以上面為變數i賦值的例子為例
1 ParameterExpression i = Expression.Parameter(typeof(int), "i"); 2 //ParameterExpression j = Expression.Variable(typeof(int), "j"); 3 ConstantExpression constExpr = Expression.Constant(5, typeof(int)); 4 // 建立一個表示賦值運算的 System.Linq.Expressions.BinaryExpression 5 //表示包含二元運算子的表示式。 6 BinaryExpression binaryExpression = Expression.Assign(i, constExpr);
+=
1 BinaryExpression b2 = Expression.AddAssign(i, constExpr);
-=
1 BinaryExpression b3 = Expression.SubtractAssign(i, constExpr);
*=
BinaryExpression b4 = Expression.MultiplyAssign(i, constExpr);
/=
1 BinaryExpression b5= Expression.DivideAssign(i, constExpr);
舉一個例子
1 ParameterExpression i = Expression.Parameter(typeof(int), "i"); 2 BlockExpression block = Expression.Block( 3 new[] { i }, 4 //賦初值 i=5 5 Expression.Assign(i, Expression.Constant(5, typeof(int))), 6 //i+=5 10 7 Expression.AddAssign(i, Expression.Constant(5, typeof(int))), 8 //i-=5 5 9 Expression.SubtractAssign(i, Expression.Constant(5, typeof(int))), 10 //i*=5 25 11 Expression.MultiplyAssign(i, Expression.Constant(5, typeof(int))), 12 //i/=5 5 13 Expression.DivideAssign(i, Expression.Constant(5, typeof(int))) 14 ); 15 Console.WriteLine(Expression.Lambda<Func<int>>(block).Compile()());
結果
二元運算子表示式
在上面也提到了部分二元運算子表示式,類似加減乘除這樣的運算子,對於二元運算子,就不再舉例。這些返回的表示式樹,都可以使用BinaryExpression來接收,或者使用基類Expression接收,或者更省事,使用var關鍵字。
一元運算子表示式
類似++,--運算子
i++等價於i=i+1,運算順序就是i先加1,然後再賦值給i。在表示式書中使用Expression的PostIncrementAssign方法來進行自增或者自減操作。返回結果為UnaryExpression型別,同樣可以使用基類Expression接收,或者var。
迴圈表示式
在表示式樹中使用Expression的Loop方法實現迴圈。
塊表示式
在前面的文章中,也說了不能使用Lambda方式建立帶塊級的表示式樹,不然會有如下的錯誤
通過API的方式可以建立塊級表示式樹,其中Expression的Block方法功不可沒。例如上面的加減乘除的例子中,可以包括多個Expression。
那麼,下面就舉一個包含自增的一元表示式,迴圈的表示式塊,並輸出結果。
輸出1-100之間的所有偶數。
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //變數i 6 ParameterExpression i = Expression.Parameter(typeof(int), "i"); 7 //跳出迴圈 8 LabelTarget label = Expression.Label(); 9 BlockExpression block = Expression.Block( 10 new[] { i }, 11 //為i賦初值 12 Expression.Assign(i, Expression.Constant(1, typeof(int))), 13 Expression.Loop( 14 Expression.IfThenElse( 15 //如果i<=100 16 Expression.LessThanOrEqual(i, Expression.Constant(100, typeof(int))), 17 //如果為true.進入迴圈體 18 Expression.Block( 19 Expression.IfThen( 20 //條件i%2==0; 21 Expression.Equal(Expression.Modulo(i, Expression.Constant(2, typeof(int))), 22 Expression.Constant(0, typeof(int))), 23 Expression.Call(typeof(Console).GetMethod("WriteLine", 24 new Type[] { typeof(int) }), new[] { i })), 25 //i++ 26 Expression.PostIncrementAssign(i) 27 ), 28 //如果i>100 29 Expression.Break(label)), 30 label 31 )); 32 Expression.Lambda<Action>(block).Compile()(); 33 Console.Read(); 34 } 35 }
結果
總結
本篇文章介紹了幾種常見的表示式型別,當然,還有很多並沒有列出,比如switch case,try catch等。如果在專案中需要建立複雜的表示式樹,Expression的靜態方法Block是必不可少的。希望通過本篇的學習,對你瞭解Expression有所幫助。
參考文章
https://msdn.microsoft.com/zh-cn/library/dd323961(v=vs.110).aspx
https://msdn.microsoft.com/zh-cn/library/bb397951.aspx
相關推薦
Linq之Expression高階篇(常用表示式型別)
目錄 寫在前面 系列文章 變量表達式 常量表達式 條件表示式 賦值表示式 迴圈表示式 塊表示式 總結 寫在前面 首先回顧一下上篇文章的內容,上篇文章介紹了表示式樹的解析和編譯。如果忘記了,可以通過下面系列文章提供的入口進行復習。這篇文章將介紹常見的表示式型別。 常見的表示式型別都有個共同的基類Expre
JavaScript學習之小白篇(十-BOM學習)
好好學習 ,天天向上。Are you ready? 一、設定或獲取元素節點物件的屬性 1. setAttribute() 2. getattribute() 3. removeAttribute() 二、outerHTML : 獲取元素節點物件的全部內容,包含當前節點 innerTe
JavaScript學習之小白篇(九-BOM學習)
好好學習 ,天天向上。Are you ready? 一、什麼是BOM? 瀏覽器物件模型。 二、BOM中的頂級物件是什麼? window 三、window下的子物件有哪些? document/history/location/frames/navigator/screen 四、如何跳轉
ORACLE學習第七篇(常用處理函式)
一、常用聚合函式 求最大值:select max(sal) from emp ; 求最小值:select min(sal) from emp ; 求平均值:select avg(sal) from emp ; Sum 求和:select sum(sal) from emp ; Count
VC之控制元件篇(白喬原創)
1 使用Windows標準控制元件 1.1 常見控制元件列表 Windows標準控制元件即普通控制元件,撰寫此文時,筆者每天面對的Word就帶了一臉的控制元件,當然你肯定也熟悉:字型選擇下拉框、工具欄、滾動條、狀態列,如此等等。 常見的Windows標準控制元件在VC裡
ARM處理器學習之--GPIO操作篇(gnu link script)
1:主要內容 本文主要介紹了VMA、LMA的相關概念,gnu link script的作用和使用方法。 2:引言 我們程式設計師剛開始學習編寫程式時,都會接觸到一個 " *.C " 檔案要經過編譯、連結等過程才能變成可以執行的程式。至於這裡的連結到底
Shader學習之Cg語言二(Cg資料型別)
由於在用Cg語言寫程式碼的時候,沒有好用的編輯器,也不可以像Java,C++,C#這類語言的斷點除錯,所有邏輯需要寫得很小心,變數名字也需要自己全部記住,相當於在文字編輯器上寫程式碼,這樣一些資料型別名稱很容易寫錯,因此我記錄下來,當自己忘記後方便查詢。
Android-NDK開發之基礎--Android JNI開發高階篇(JNI中的常用方法)
有關Android JNI開發中比較強大和有用的功能就是從JNI層建立、構造Java的類或執行Java層的方法獲取屬性等操作。 一、類的相關操作 1. jclass FindClass(JNIEnv *env, const char *name); 查詢類
探索ASP.NET MVC5系列之~~~3.檢視篇(下)---包含常用表單和暴力解猜防禦
其實任何資料裡面的任何知識點都無所謂,都是不重要的,重要的是學習方法,自行摸索的過程(不妥之處歡迎指正) 這幾天忙著幫別人普及安全,今天就把這篇文章結束掉,明天講下 “過度提交” 的防禦。這次開篇就激烈點==》爆破演示: 開啟Burp 設定監聽埠==》8080 設定一下代理:
Salesforce學習之路-developer篇(五)Aura元件原理及常用屬性
很喜歡曾經看到的一句話:以輸出倒逼輸入。以輸出的形式強制自己學習,確實是高效的學習方式,真的很棒。以下僅為個人學習理解,如有錯誤,歡迎指出,共同學習。 1. 什麼是Lightning Component框架? Lightning Component框架是一個UI框架,用於為移動和
構建之法--探索篇(一)
構建 編寫 裏的 set namespace 對象 之前 定義 時也 問題一: 在Cust中無法找到telephone的get方法,這裏是因為我之前沒有telephone的成員變量,加上之後有沒有寫telephone的get方法; 解決方案:只要在Cust這個類裏面,加上
linux學習之進程篇(二)
通過 passwd 查看 現在 替換 cnblogs exe -1 stdio.h 進程原語 1.fork #include<unistd.h> pid_t fork(void); fork 子進程復制父進程,子進程和父進程的PID是不一樣的,在
Spring Boot 入門之持久層篇(三)
imp 配置文件 bat catch map ann 文件 save values 原文地址:Spring Boot 入門之持久層篇(三) 博客地址:http://www.extlight.com 一、前言 上一篇《Spring Boot 入門之 Web 篇(二)》介紹
運維學python之爬蟲中級篇(五)數據存儲(無數據庫版)
就是 erro mage name 打印 反序 lis object Circul 本篇主要介紹,爬取html數據後,將html的正文內容存儲為json或csv格式。 1 json格式存儲 選定要爬取的網站後,我們利用之前學過的內容,如:Beautiful Soup、xpa
運維學python之爬蟲中級篇(七)Sqlite3
pro odin any /dev/ 裏的 連接 oracle postgresq pycharm 前文已經講過無數據庫版本操作(csv,json),今天我們要開始講有數據庫版本的操作,首先就是sqlite3。 1 介紹 SQLite是一個C庫,它提供了一個輕量級的基於磁盤
運維學python之爬蟲中級篇(九)Python3 MySQL 數據庫連接
結束 學python ofo 如何 res 2.7 獲取數據 執行 mail 最近因為年底,連續兩個項目要投產上線,又趕上公司年會,忙的要死,更新有些慢,見諒。今天要說一說python如何對mysql進行操作。在 Python3.x 版本中用於連接 MySQL 服務器的庫與
React學習筆記之react基礎篇(1)
lis fun tst struct pan 流程 普通 如果 是把 一.React特點歸納 1.聲明式的視圖層:React 模板寫在 JS 文件中,而不是 html 的 <script> 標簽中。能使用所有 JS 語法,而不只有模板語法,所以更加靈活。
React學習筆記之react基礎篇(2)
應用場景 組件 單元 ren provide form 實例 show wid 上一節我已經對React中基本的組件操作進行了說明,這一節我將對組件的一些附加屬性(如:組件的生命周期和組件的樣式)以及一些其他功能進行講解 一.組件的樣式 1.外部CSS樣式表: /
ROS2GO之系統升級篇(Ubuntu 18.04 + ROS 1 Melodic + ROS 2 Bouncy + V-Rep等)
本教程風險極大,請不要輕易嘗試。當然此篇方法適用於任何想從Ubuntu 16.04升級到18.04(10年超長期支援)的使用者。 ----過程如下::---- [email protected]:~$ sudo apt update [e
資料結構與演算法之連結串列篇(上)
連結串列作為一種基礎的資料結構之一,我們會常常使用到它,接下來就讓我們一起學習吧。 1、連結串列的經典應用場景: LRU快取淘汰演算法。 2、快取是一種提高資料讀取效能的技術,在硬體設計、軟體開發中都有著非常廣泛的應用,比如常見的CPU快取、資料庫快取、瀏覽器快取等等。