亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C# 表達(dá)式樹(shù)Expression Trees的知識(shí)梳理

 更新時(shí)間:2017年01月04日 11:40:41   作者:反骨仔(二五仔)  
本篇文章主要介紹了表達(dá)式樹(shù) Expression Trees的基礎(chǔ)知識(shí):Lambda 表達(dá)式創(chuàng)建表達(dá)式樹(shù);API 創(chuàng)建表達(dá)式樹(shù);編譯表達(dá)式樹(shù);執(zhí)行表達(dá)式樹(shù);修改表達(dá)式樹(shù)等等,具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧

目錄

  • 簡(jiǎn)介
  • Lambda 表達(dá)式創(chuàng)建表達(dá)式樹(shù)
  • API 創(chuàng)建表達(dá)式樹(shù)
  • 解析表達(dá)式樹(shù)
  • 表達(dá)式樹(shù)的永久性
  • 編譯表達(dá)式樹(shù)
  • 執(zhí)行表達(dá)式樹(shù)
  • 修改表達(dá)式樹(shù)
  • 調(diào)試

簡(jiǎn)介

表達(dá)式樹(shù)以樹(shù)形數(shù)據(jù)結(jié)構(gòu)表示代碼,其中每一個(gè)節(jié)點(diǎn)都是一種表達(dá)式,比如方法調(diào)用和 x < y 這樣的二元運(yùn)算等。

你可以對(duì)表達(dá)式樹(shù)中的代碼進(jìn)行編輯和運(yùn)算。這樣能夠動(dòng)態(tài)修改可執(zhí)行代碼、在不同數(shù)據(jù)庫(kù)中執(zhí)行 LINQ 查詢(xún)以及創(chuàng)建動(dòng)態(tài)查詢(xún)。

表達(dá)式樹(shù)還能用于動(dòng)態(tài)語(yǔ)言運(yùn)行時(shí) (DLR) 以提供動(dòng)態(tài)語(yǔ)言和 .NET Framework 之間的互操作性。

一、Lambda 表達(dá)式創(chuàng)建表達(dá)式樹(shù)

若 lambda 表達(dá)式被分配給 Expression<TDelegate> 類(lèi)型的變量,則編譯器可以發(fā)射代碼以創(chuàng)建表示該 lambda 表達(dá)式的表達(dá)式樹(shù)。 

C# 編譯器只能從表達(dá)式 lambda (或單行 lambda)生成表達(dá)式樹(shù)。

下列代碼示例使用關(guān)鍵字 Expression創(chuàng)建表示 lambda 表達(dá)式:

 Expression<Action<int>> actionExpression = n => Console.WriteLine(n);
 Expression<Func<int, bool>> funcExpression1 = (n) => n < 0;
 Expression<Func<int, int, bool>> funcExpression2 = (n, m) => n - m == 0;

二、API 創(chuàng)建表達(dá)式樹(shù)

通過(guò) API 創(chuàng)建表達(dá)式樹(shù)需要使用Expression 類(lèi)

下列代碼示例展示如何通過(guò) API 創(chuàng)建表示 lambda 表達(dá)式:num => num == 0

//通過(guò) Expression 類(lèi)創(chuàng)建表達(dá)式樹(shù)
 // lambda:num => num == 0
 ParameterExpression pExpression = Expression.Parameter(typeof(int)); //參數(shù):num
 ConstantExpression cExpression = Expression.Constant(0); //常量:0
 BinaryExpression bExpression = Expression.MakeBinary(ExpressionType.Equal, pExpression, cExpression); //表達(dá)式:num == 0
 Expression<Func<int, bool>> lambda = Expression.Lambda<Func<int, bool>>(bExpression, pExpression); //lambda 表達(dá)式:num => num == 0

代碼使用Expression 類(lèi)的靜態(tài)方法進(jìn)行創(chuàng)建。

三、解析表達(dá)式樹(shù)

下列代碼示例展示如何分解表示 lambda 表達(dá)式 num => num == 0 的表達(dá)式樹(shù)。

Expression<Func<int, bool>> funcExpression = num => num == 0;
 //開(kāi)始解析
 ParameterExpression pExpression = funcExpression.Parameters[0]; //lambda 表達(dá)式參數(shù)
 BinaryExpression body = (BinaryExpression)funcExpression.Body; //lambda 表達(dá)式主體:num == 0
 Console.WriteLine($"解析:{pExpression.Name} => {body.Left} {body.NodeType} {body.Right}");

四、表達(dá)式樹(shù)永久性

表達(dá)式樹(shù)應(yīng)具有永久性(類(lèi)似字符串)。這意味著如果你想修改某個(gè)表達(dá)式樹(shù),則必須復(fù)制該表達(dá)式樹(shù)然后替換其中的節(jié)點(diǎn)來(lái)創(chuàng)建一個(gè)新的表達(dá)式樹(shù)。  你可以使用表達(dá)式樹(shù)訪問(wèn)者遍歷現(xiàn)有表達(dá)式樹(shù)。第七節(jié)介紹了如何修改表達(dá)式樹(shù)。

五、編譯表達(dá)式樹(shù)

Expression<TDelegate> 類(lèi)型提供了 Compile 方法以將表達(dá)式樹(shù)表示的代碼編譯成可執(zhí)行委托。

//創(chuàng)建表達(dá)式樹(shù)
 Expression<Func<string, int>> funcExpression = msg => msg.Length;
 //表達(dá)式樹(shù)編譯成委托
 var lambda = funcExpression.Compile();
 //調(diào)用委托
 Console.WriteLine(lambda("Hello, World!"));
 //語(yǔ)法簡(jiǎn)化
 Console.WriteLine(funcExpression.Compile()("Hello, World!"));

六、執(zhí)行表達(dá)式樹(shù)

執(zhí)行表達(dá)式樹(shù)可能會(huì)返回一個(gè)值,也可能僅執(zhí)行一個(gè)操作(例如調(diào)用方法)。

只能執(zhí)行表示 lambda 表達(dá)式的表達(dá)式樹(shù)。表示 lambda 表達(dá)式的表達(dá)式樹(shù)屬于 LambdaExpressionExpression<TDelegate> 類(lèi)型。若要執(zhí)行這些表達(dá)式樹(shù),需要調(diào)用 Compile 方法來(lái)創(chuàng)建一個(gè)可執(zhí)行委托,然后調(diào)用該委托。

const int n = 1;
 const int m = 2;
 //待執(zhí)行的表達(dá)式樹(shù)
 BinaryExpression bExpression = Expression.Add(Expression.Constant(n), Expression.Constant(m));
 //創(chuàng)建 lambda 表達(dá)式
 Expression<Func<int>> funcExpression = Expression.Lambda<Func<int>>(bExpression);
 //編譯 lambda 表達(dá)式
 Func<int> func = funcExpression.Compile();
 //執(zhí)行 lambda 表達(dá)式
 Console.WriteLine($"{n} + {m} = {func()}");

七、修改表達(dá)式樹(shù)

該類(lèi)繼承 ExpressionVisitor 類(lèi),通過(guò) Visit 方法間接調(diào)用 VisitBinary 方法將 != 替換成 ==。基類(lèi)方法構(gòu)造類(lèi)似于傳入的表達(dá)式樹(shù)的節(jié)點(diǎn),但這些節(jié)點(diǎn)將其子目錄樹(shù)替換為訪問(wèn)器遞歸生成的表達(dá)式樹(shù)。 

internal class Program
 {
 private static void Main(string[] args)
 {
 Expression<Func<int, bool>> funcExpression = num => num == 0;
 Console.WriteLine($"Source: {funcExpression}");
 var visitor = new NotEqualExpressionVisitor();
 var expression = visitor.Visit(funcExpression);
 Console.WriteLine($"Modify: {expression}");
 Console.Read();
 }
 /// <summary>
 /// 不等表達(dá)式樹(shù)訪問(wèn)器
 /// </summary>
 public class NotEqualExpressionVisitor : ExpressionVisitor
 {
 public Expression Visit(BinaryExpression node)
 {
 return VisitBinary(node);
 }
 protected override Expression VisitBinary(BinaryExpression node)
 {
 return node.NodeType == ExpressionType.Equal
  ? Expression.MakeBinary(ExpressionType.NotEqual, node.Left, node.Right) //重新弄個(gè)表達(dá)式:用 != 代替 ==
  : base.VisitBinary(node);
 }
 }
 }

八、調(diào)試

8.1 參數(shù)表達(dá)式

 ParameterExpression pExpression1 = Expression.Parameter(typeof(string));
 ParameterExpression pExpression2 = Expression.Parameter(typeof(string), "msg");

圖8-1

圖8-2

從 DebugView 可知,如果參數(shù)沒(méi)有名稱(chēng),則會(huì)為其分配一個(gè)自動(dòng)生成的名稱(chēng)。

 const int num1 = 250;
 const float num2 = 250;
 ConstantExpression cExpression1 = Expression.Constant(num1);
 ConstantExpression cExpression2 = Expression.Constant(num2);

圖8-3

圖8-4

從 DebugView 可知,float 比 int 多了個(gè)后綴 F。

 Expression lambda1 = Expression.Lambda<Func<int>>(Expression.Constant(250));
 Expression lambda2 = Expression.Lambda<Func<int>>(Expression.Constant(250), "CustomName", null);

圖8-5

圖8-6

觀察 DebugView ,如果 lambda 表達(dá)式?jīng)]有名稱(chēng),則會(huì)為其分配一個(gè)自動(dòng)生成的名稱(chēng)。

以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!

相關(guān)文章

  • c#菜單動(dòng)態(tài)合并的實(shí)現(xiàn)方法

    c#菜單動(dòng)態(tài)合并的實(shí)現(xiàn)方法

    這篇文章主要介紹了c#菜單動(dòng)態(tài)合并的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • C#中關(guān)于double.ToString()的用法

    C#中關(guān)于double.ToString()的用法

    這篇文章主要介紹了C#中關(guān)于double.ToString()的用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • DataTable的AcceptChanges()和RejectChanges()方法介紹并實(shí)現(xiàn)DataGridView數(shù)據(jù)增、刪、改

    DataTable的AcceptChanges()和RejectChanges()方法介紹并實(shí)現(xiàn)DataGridView

    這篇文章介紹了DataTable的AcceptChanges()和RejectChanges()方法并實(shí)現(xiàn)DataGridView數(shù)據(jù)增、刪、改,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-02-02
  • c# base64轉(zhuǎn)字符串實(shí)例

    c# base64轉(zhuǎn)字符串實(shí)例

    這篇文章主要介紹了c# base64轉(zhuǎn)字符串實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • 在Winform動(dòng)態(tài)啟動(dòng)、控制臺(tái)命令行的方法

    在Winform動(dòng)態(tài)啟動(dòng)、控制臺(tái)命令行的方法

    winForm 程序輸出類(lèi)型為 windows 程序(不是命令行程序)在運(yùn)行時(shí)想輸入一些信息編譯開(kāi)發(fā)調(diào)試,如何實(shí)現(xiàn)這一功能
    2013-02-02
  • C#操作 JSON方法匯總

    C#操作 JSON方法匯總

    本文給大家匯總了一下使用C#操作Json的方法,非常的簡(jiǎn)單實(shí)用,有需要的小伙伴可以參考下
    2015-10-10
  • c#獲取客戶端IP地址(考慮代理)

    c#獲取客戶端IP地址(考慮代理)

    這篇文章主要介紹了c#獲取客戶端IP地址(考慮代理),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • C# 使用modbus 讀取PLC 寄存器地址的方法

    C# 使用modbus 讀取PLC 寄存器地址的方法

    今天通過(guò)本文給大家介紹C# 使用modbus 讀取PLC 寄存器地址的方法,使用的組件Nmodbus,文中通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2021-10-10
  • 簡(jiǎn)單聊聊C#字符串構(gòu)建利器StringBuilder

    簡(jiǎn)單聊聊C#字符串構(gòu)建利器StringBuilder

    因?yàn)镾tring類(lèi)型代表不可變字符串,所以無(wú)法對(duì)當(dāng)前String類(lèi)型實(shí)例進(jìn)行處理.所以FCL提供了System.Text.StringBuilder類(lèi)型,下面這篇文章主要給大家介紹了關(guān)于C#字符串構(gòu)建利器StringBuilder的相關(guān)資料,需要的朋友可以參考下
    2022-03-03
  • WPF實(shí)現(xiàn)授權(quán)碼顯示密文并支持換行

    WPF實(shí)現(xiàn)授權(quán)碼顯示密文并支持換行

    這篇文章主要為大家詳細(xì)介紹了如何使用WPF實(shí)現(xiàn)授權(quán)碼顯示密文并支持換行,文中的示例代碼講解詳細(xì),有需要的小伙伴可以參考一下
    2024-10-10

最新評(píng)論