程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C# 表達式樹Expression Trees的知識梳理

C# 表達式樹Expression Trees的知識梳理

編輯:C#入門知識

C# 表達式樹Expression Trees的知識梳理。本站提示廣大學習愛好者:(C# 表達式樹Expression Trees的知識梳理)文章只能為提供參考,不一定能成為您想要的結果。以下是C# 表達式樹Expression Trees的知識梳理正文


目錄

簡介 Lambda 表達式創立表達式樹 API 創立表達式樹 解析表達式樹 表達式樹的永世性 編譯表達式樹 執行表達式樹 修正表達式樹 調試

簡介

表達式樹以樹形數據構造表示代碼,其中每一個節點都是一種表達式,比方辦法調用和 x < y 這樣的二元運算等。

你可以對表達式樹中的代碼停止編輯和運算。這樣可以靜態修正可執行代碼、在不同數據庫中執行 LINQ 查詢以及創立靜態查詢。

表達式樹還能用於靜態言語運轉時 (DLR) 以提供靜態言語和 .NET Framework 之間的互操作性。

一、Lambda 表達式創立表達式樹

若 lambda 表達式被分配給 Expression<TDelegate> 類型的變量,則編譯器可以發射代碼以創立表示該 lambda 表達式的表達式樹。 

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

下列代碼示例運用關鍵字 Expression創立表示 lambda 表達式:

 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 創立表達式樹

經過 API 創立表達式樹需求運用Expression 類

下列代碼示例展現如何經過 API 創立表示 lambda 表達式:num => num == 0

//經過 Expression 類創立表達式樹
 // lambda:num => num == 0
 ParameterExpression pExpression = Expression.Parameter(typeof(int)); //參數:num
 ConstantExpression cExpression = Expression.Constant(0); //常量:0
 BinaryExpression bExpression = Expression.MakeBinary(ExpressionType.Equal, pExpression, cExpression); //表達式:num == 0
 Expression<Func<int, bool>> lambda = Expression.Lambda<Func<int, bool>>(bExpression, pExpression); //lambda 表達式:num => num == 0

代碼運用Expression 類的靜態辦法停止創立。

三、解析表達式樹

下列代碼示例展現如何分解表示 lambda 表達式 num => num == 0 的表達式樹。

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

四、表達式樹永世性

表達式樹應具有永世性(相似字符串)。這意味著假如你想修正某個表達式樹,則必需復制該表達式樹然後交換其中的節點來創立一個新的表達式樹。  你可以運用表達式樹訪問者遍歷現有表達式樹。第七節引見了如何修正表達式樹。

五、編譯表達式樹

Expression<TDelegate> 類型提供了 Compile 辦法以將表達式樹表示的代碼編譯成可執行委托。

//創立表達式樹
 Expression<Func<string, int>> funcExpression = msg => msg.Length;
 //表達式樹編譯成委托
 var lambda = funcExpression.Compile();
 //調用委托
 Console.WriteLine(lambda("Hello, World!"));
 //語法簡化
 Console.WriteLine(funcExpression.Compile()("Hello, World!"));

六、執行表達式樹

執行表達式樹能夠會前往一個值,也能夠僅執行一個操作(例如調用辦法)。

只能執行表示 lambda 表達式的表達式樹。表示 lambda 表達式的表達式樹屬於 LambdaExpression 或 Expression<TDelegate> 類型。若要執行這些表達式樹,需求調用 Compile 辦法來創立一個可執行委托,然後調用該委托。

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

七、修正表達式樹

該類承繼 ExpressionVisitor 類,經過 Visit 辦法直接調用 VisitBinary 辦法將 != 交換成 ==。基類辦法結構相似於傳入的表達式樹的節點,但這些節點將其子目錄樹交換為訪問器遞歸生成的表達式樹。 

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>
 /// 不等表達式樹訪問器
 /// </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) //重新弄個表達式:用 != 替代 ==
  : base.VisitBinary(node);
 }
 }
 }

八、調試

8.1 參數表達式

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

圖8-1

圖8-2

從 DebugView 可知,假如參數沒有稱號,則會為其分配一個自動生成的稱號。

 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 多了個後綴 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 表達式沒有稱號,則會為其分配一個自動生成的稱號。

以上就是本文的全部內容,希望本文的內容對大家的學習或許任務能帶來一定的協助,同時也希望多多支持!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved