成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

C# 表達(dá)式樹 (Expression Trees) 詳解

開發(fā) 前端
若 lambda 表達(dá)式被分配給 ??Expression<TDelegate>?? 類型的變量,則編譯器可以發(fā)射代碼以創(chuàng)建表示該 lambda 表達(dá)式的表達(dá)式樹。C# 編譯器只能從表達(dá)式 lambda (或單行 lambda)生成表達(dá)式樹。

表達(dá)式樹以樹形數(shù)據(jù)結(jié)構(gòu)表示代碼,其中每一個節(jié)點都是一種表達(dá)式,比如方法調(diào)用和 x < y 這樣的二元運算等。你可以對表達(dá)式樹中的代碼進(jìn)行編輯和運算。這樣能夠動態(tài)修改可執(zhí)行代碼、在不同數(shù)據(jù)庫中執(zhí)行 LINQ 查詢以及創(chuàng)建動態(tài)查詢。表達(dá)式樹還能用于動態(tài)語言運行時 (DLR) 以提供動態(tài)語言和 .NET Framework 之間的互操作性。

Lambda 表達(dá)式創(chuàng)建表達(dá)式樹

若 lambda 表達(dá)式被分配給 Expression<TDelegate> 類型的變量,則編譯器可以發(fā)射代碼以創(chuàng)建表示該 lambda 表達(dá)式的表達(dá)式樹。C# 編譯器只能從表達(dá)式 lambda (或單行 lambda)生成表達(dá)式樹。

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

using System.Linq.Expressions;

namespace AppExpressionTrees
{
    internal class Program
    {
        static void Main(string[] args)
        {
            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;

            Console.WriteLine(actionExpression);
            Console.WriteLine(funcExpression1);
            Console.WriteLine(funcExpression2);
        }
    }
}

圖片圖片

API 創(chuàng)建表達(dá)式樹

通過 API 創(chuàng)建表達(dá)式樹需要使用 Expression 類。下列代碼示例展示如何通過 API 創(chuàng)建表示 lambda 表達(dá)式 num => num == 0

using System;
using System.Linq.Expressions;

class Program
{
    static void Main()
    {
        // 通過 Expression 類創(chuàng)建表達(dá)式樹
        // 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

        Console.WriteLine(lambda);
    }
}

圖片圖片

另一個例子:創(chuàng)建一個簡單的加法表達(dá)式

using System.Linq.Expressions;

namespace AppExpressionTrees
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // 創(chuàng)建表達(dá)式樹:num1 + num2
            ParameterExpression num1 = Expression.Parameter(typeof(int), "num1");
            ParameterExpression num2 = Expression.Parameter(typeof(int), "num2");
            BinaryExpression addExpression = Expression.Add(num1, num2);
            Expression<Func<int, int, int>> lambda = Expression.Lambda<Func<int, int, int>>(addExpression, num1, num2);

            Console.WriteLine(lambda);
            Console.WriteLine(lambda.Compile().Invoke(1, 2));
        }
    }
}

圖片圖片

解析表達(dá)式樹

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

using System;
using System.Linq.Expressions;

class Program
{
    static void Main()
    {
        Expression<Func<int, bool>> funcExpression = num => num == 0;

        // 開始解析
        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á)式

using System;
using System.Linq.Expressions;

class Program
{
    static void Main()
    {
        Expression<Func<int, int, int>> funcExpression = (num1, num2) => num1 + num2;

        // 開始解析
        ParameterExpression pExpression1 = funcExpression.Parameters[0]; // 第一個參數(shù)
        ParameterExpression pExpression2 = funcExpression.Parameters[1]; // 第二個參數(shù)
        BinaryExpression body = (BinaryExpression)funcExpression.Body; // lambda 表達(dá)式主體:num1 + num2

        Console.WriteLine($"解析:{pExpression1.Name} + {pExpression2.Name} => {body.Left} {body.NodeType} {body.Right}");
    }
}

圖片圖片

表達(dá)式樹的永久性

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

編譯表達(dá)式樹

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

using System;
using System.Linq.Expressions;

class Program
{
    static void Main()
    {
        // 創(chuàng)建表達(dá)式樹
        Expression<Func<string, int>> funcExpression = msg => msg.Length;

        // 表達(dá)式樹編譯成委托
        var lambda = funcExpression.Compile();

        // 調(diào)用委托
        Console.WriteLine(lambda("Hello, World!"));

        // 語法簡化
        Console.WriteLine(funcExpression.Compile()("Hello, World!"));
    }
}

圖片圖片

另一個例子:編譯加法表達(dá)式

using System;
using System.Linq.Expressions;

class Program
{
    static void Main()
    {
        // 創(chuàng)建表達(dá)式樹:num1 + num2
        ParameterExpression num1 = Expression.Parameter(typeof(int), "num1");
        ParameterExpression num2 = Expression.Parameter(typeof(int), "num2");
        BinaryExpression addExpression = Expression.Add(num1, num2);
        Expression<Func<int, int, int>> lambda = Expression.Lambda<Func<int, int, int>>(addExpression, num1, num2);

        // 編譯表達(dá)式樹
        var compiledLambda = lambda.Compile();

        // 調(diào)用委托
        Console.WriteLine(compiledLambda(3, 4)); // 輸出:7
    }
}

圖片圖片

執(zhí)行表達(dá)式樹

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

using System;
using System.Linq.Expressions;

class Program
{
    static void Main()
    {
        constint n = 1;
        constint m = 2;

        // 待執(zhí)行的表達(dá)式樹
        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()}");
    }
}

另一個例子:執(zhí)行字符串長度表達(dá)式

using System;
using System.Linq.Expressions;

class Program
{
    static void Main()
    {
        // 創(chuàng)建表達(dá)式樹:msg => msg.Length
        ParameterExpression msg = Expression.Parameter(typeof(string), "msg");
        MemberExpression length = Expression.Property(msg, "Length");
        Expression<Func<string, int>> lambda = Expression.Lambda<Func<string, int>>(length, msg);

        // 編譯表達(dá)式樹
        var compiledLambda = lambda.Compile();

        // 執(zhí)行 lambda 表達(dá)式
        Console.WriteLine(compiledLambda("Hello, World!")); // 輸出:13
    }
}

圖片圖片

修改表達(dá)式樹

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

using System;
using System.Linq.Expressions;

class Program
{
    static void Main()
    {
        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}");
    }

    publicclass 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) // 重新弄個表達(dá)式:用 != 代替 ==
                : base.VisitBinary(node);
        }
    }
}

圖片圖片

另一個例子:將加法修改為乘法

using System;
using System.Linq.Expressions;

class Program
{
    static void Main()
    {
        Expression<Func<int, int, int>> funcExpression = (num1, num2) => num1 + num2;
        Console.WriteLine($"Source: {funcExpression}");

        var visitor = new MultiplyExpressionVisitor();
        var expression = visitor.Visit(funcExpression);

        Console.WriteLine($"Modify: {expression}");
    }

    publicclass MultiplyExpressionVisitor : ExpressionVisitor
    {
        public Expression Visit(BinaryExpression node)
        {
            return VisitBinary(node);
        }

        protected override Expression VisitBinary(BinaryExpression node)
        {
            return node.NodeType == ExpressionType.Add
                ? Expression.MakeBinary(ExpressionType.Multiply, node.Left, node.Right) // 重新弄個表達(dá)式:用 * 代替 +
                : base.VisitBinary(node);
        }
    }
}

總結(jié)

以上內(nèi)容詳細(xì)介紹了 C# 中表達(dá)式樹的相關(guān)知識,并提供了具體的示例代碼,以幫助開發(fā)者更深入地理解這一重要概念。表達(dá)式樹是 C# 中一種強大的工具,它允許開發(fā)者以樹形結(jié)構(gòu)表示代碼邏輯,從而可以在運行時對代碼進(jìn)行分析、修改甚至動態(tài)生成。這種特性在許多場景下非常有用,例如構(gòu)建動態(tài)查詢(如 LINQ to SQL)、實現(xiàn)自定義解析器或優(yōu)化運行時性能。

希望這些內(nèi)容能夠為你提供清晰的指導(dǎo),幫助你更好地理解和使用表達(dá)式樹。無論你是初學(xué)者還是有一定經(jīng)驗的開發(fā)者,都可以從中獲得啟發(fā),并進(jìn)一步探索表達(dá)式樹在各種復(fù)雜場景中的潛力。通過不斷實踐和嘗試,相信你會更加熟練地運用這一強大工具,提升代碼的靈活性和效率。

責(zé)任編輯:武曉燕 來源: 技術(shù)老小子
相關(guān)推薦

2009-08-07 15:41:39

C#正規(guī)表達(dá)式

2009-08-27 09:57:50

C# Lambda表達(dá)

2009-08-03 17:27:14

C#正則表達(dá)式

2009-08-20 16:23:32

C#正則表達(dá)式語法

2010-09-14 14:05:42

C#委托

2009-09-14 13:57:20

C# Lambda表達(dá)Lambda表達(dá)式

2009-08-27 09:44:59

C# Lambda表達(dá)

2009-04-09 09:19:25

C#規(guī)則表達(dá)式.NET

2024-03-25 13:46:12

C#Lambda編程

2009-08-17 13:56:28

C#正則表達(dá)式入門

2009-08-07 15:16:10

C#正則表達(dá)式

2009-08-26 16:17:23

C# Lambda表達(dá)

2009-08-14 16:50:59

C#正則表達(dá)式語法

2009-07-09 09:51:07

Lambda表達(dá)式C#

2009-08-11 13:00:41

C#正則表達(dá)式

2009-08-13 15:24:27

C#正則表達(dá)式

2009-08-11 16:03:13

C#運算符

2022-01-14 07:56:39

C#動態(tài)查詢

2024-12-16 07:33:45

C#正則表達(dá)式

2021-08-31 07:19:41

Lambda表達(dá)式C#
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 欧美日韩黄色一级片 | 亚洲人在线播放 | 狠狠天天| 九九热精品视频 | 91在线精品秘密一区二区 | 欧美一区免费在线观看 | 亚洲激情综合 | 亚洲午夜在线 | 91在线精品一区二区 | 日韩中文字幕网 | 精品视频一区二区三区在线观看 | 国产成人99久久亚洲综合精品 | 久久久久久久久久久久久九 | 伊人天堂网| 久久精品中文 | 日本在线播放一区二区 | 国产精品久久久久久久免费大片 | 久久精品小短片 | 蜜臀久久99精品久久久久久宅男 | 欧美1页| 欧美成人a∨高清免费观看 色999日韩 | 欧美乱大交xxxxx另类电影 | 久久99精品视频 | 91精品国产一区二区三区蜜臀 | 亚洲三级免费看 | 成年人在线观看视频 | 免费一看一级毛片 | 国产精品久久久久久久免费观看 | 成在线人视频免费视频 | 久久久久久久久国产成人免费 | 欧美日日 | 久久中文高清 | 成人免费视频网 | 亚洲午夜av久久乱码 | 亚洲视频免费在线观看 | 一级免费在线视频 | www.玖玖玖 | 99精品久久久久 | 午夜影院网站 | 成人教育av | 精品国产99 |