1. 程式人生 > >Linq之Expression高階篇(常用表示式型別)

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

相關推薦

LinqExpression高階常用表示式型別

目錄 寫在前面 系列文章 變量表達式 常量表達式 條件表示式 賦值表示式 迴圈表示式 塊表示式 總結 寫在前面 首先回顧一下上篇文章的內容,上篇文章介紹了表示式樹的解析和編譯。如果忘記了,可以通過下面系列文章提供的入口進行復習。這篇文章將介紹常見的表示式型別。 常見的表示式型別都有個共同的基類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學習路-developerAura元件原理及常用屬性

很喜歡曾經看到的一句話:以輸出倒逼輸入。以輸出的形式強制自己學習,確實是高效的學習方式,真的很棒。以下僅為個人學習理解,如有錯誤,歡迎指出,共同學習。   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快取、資料庫快取、瀏覽器快取等等。