Eine kurze Einführung in Ausdrucksbäume in C#

黄舟
Freigeben: 2017-09-16 11:08:45
Original
2073 Leute haben es durchsucht

Der Ausdrucksbaum ist einer der Kerne von Linq. Warum ist er einer der Kerne von Linq? Da der Ausdrucksbaum dafür sorgt, dass C# nicht mehr nur in IL kompiliert wird, können wir über C# einen Ausdrucksbaum generieren, das Ergebnis als Zwischenformat verwenden und es auf der Zielplattform in die Muttersprache konvertieren. Wie SQL. Auf diese Weise generiert unser häufig verwendetes Linq to SQL SQL.

Der Ausdrucksbaum wurde nach .NET 3.5 eingeführt. Es handelt sich um ein leistungsstarkes und flexibles Tool (z. B. zum Erstellen dynamischer Abfragen in LINQ).

Werfen wir zunächst einen Blick auf die API-Schnittstelle der Expression-Klasse:

namespace System.Linq.Expressions
{
    //
    // 摘要:
    //     以表达式目录树的形式将强类型 lambda 表达式表示为数据结构。此类不能被继承。
    //
    // 类型参数:
    //   TDelegate:
    //     System.Linq.Expressions.Expression`1 表示的委托的类型。
    public sealed class Expression<TDelegate> : LambdaExpression
    {
        //
        // 摘要:
        //     将表达式树描述的 lambda 表达式编译为可执行代码,并生成表示该 lambda 表达式的委托。
        //
        // 返回结果:
        //     一个 TDelegate 类型的委托,它表示由 System.Linq.Expressions.Expression`1 描述的已编译的 lambda 表达式。
        public TDelegate Compile();
        //
        // 摘要:
        //     生成表示 lambda 表达式的委托。
        //
        // 参数:
        //   debugInfoGenerator:
        //     编译器用于标记序列点并批注局部变量的调试信息生成器。
        //
        // 返回结果:
        //     包含 lambda 的已编译版本的委托。
        public TDelegate Compile(DebugInfoGenerator debugInfoGenerator);
        //
        // 摘要:
        //     创建一个与此表达式类似的新表达式,但使用所提供的子级。如果所有子级都相同,则将返回此表达式。
        //
        // 参数:
        //   body:
        //     结果的 System.Linq.Expressions.LambdaExpression.Body 属性。
        //
        //   parameters:
        //     结果的 System.Linq.Expressions.LambdaExpression.Parameters 属性。
        //
        // 返回结果:
        //     此表达式(如果未更改任何子级),或带有更新的子级的表达式。
        public Expression<TDelegate> Update(Expression body, IEnumerable<ParameterExpression> parameters);
        protected internal override Expression Accept(ExpressionVisitor visitor);
    }
}
Nach dem Login kopieren

Die Syntax des Ausdrucksbaums lautet wie folgt:


Expression<Func<type,returnType>> = (param) => lamdaexpresion;
Nach dem Login kopieren

Zum Beispiel:


Expression<Func<int, int, int>> expr = (x, y) => x+y;
Nach dem Login kopieren

Wir führen den obigen Code aus und zeigen diesen Ausdrucksbaum im VS-Debug-Modus an:

Sie können sehen, dass der Ausdrucksbaum hauptsächlich aus den folgenden vier Teilen besteht:

1 Körperteil

2 . Parameterteil

3. NodeType-Knotentyp

4. Lambda-Ausdruckstyp

Im obigen Code , der Hauptteil ist: x+y, die Parameter sind (x, y), NodeType ist ein Lambda-Ausdruck und der Rückgabewert ist int

Der Hauptteil kann ein Ausdruck sein, aber er kann keine Anweisungen enthalten. Beispiel: Ich definiere einen Delegaten und der Lambda-Ausdruck kann so geschrieben werden:


Func<int, int, int> func = (x, y) => x + y;
Nach dem Login kopieren
kann auch so geschrieben werden:


Func<int, int, int> func = (x, y) => { return x + y; };
Nach dem Login kopieren
Im Ausdrucksbaumtyp kann jedoch nur die erste Schreibweise verwendet werden. Wenn die zweite Schreibweise verwendet wird, wird ein Kompilierungsfehler gemeldet:

Das Lambda Ausdruck mit einem Anweisungshauptteil kann nicht in einen Ausdrucksbaum umgewandelt werden.

Zusätzlich zur oben genannten Schreibmethode kann der Ausdrucksbaum auch folgendermaßen geschrieben werden:

ParameterExpression pex1 = Expression.Parameter(typeof(int), "x");//第一个参数
ParameterExpression pex2 = Expression.Parameter(typeof(int), "y");//第二个参数

BinaryExpression bexp = Expression.Add(pex1, pex2);//加法

var lambdaExp = Expression.Lambda<Func<int, int, int>>(bexp, new ParameterExpression[] {pex1,pex2 });
Nach dem Login kopieren


Im VS-Debugging-Modus können Sie sehen, dass die von den beiden Schreibmethoden generierten Ausdrucksbäume identisch sind

Kompilieren Sie den Ausdrucksbaum in einen Delegaten

LambdaExpression ist ein von Expression abgeleiteter Typ. Die generische Klasse Expression ist von LambdaExpression abgeleitet, wobei der generische Parameter TDelegate ein Delegattyp sein muss.

LambdaExpression verfügt über eine Compile-Methode, die einen Delegaten des entsprechenden Typs erstellt. Die Compile-Methode von Expression gibt einen Delegaten vom Typ TDelegate zurück. Schauen wir uns das folgende Beispiel an:

Expression<Func<int, int, int>> expr = (x, y) => x + y;

ParameterExpression pex1 = Expression.Parameter(typeof(int), "x");//第一个参数
ParameterExpression pex2 = Expression.Parameter(typeof(int), "y");//第二个参数

BinaryExpression bexp = Expression.Add(pex1, pex2);//主体,加法

//使用Expression.Lambda方法,创建一个委托类型已知的Expression
Expression<Func<int,int,int>> lambdaExp 
    = Expression.Lambda<Func<int, int, int>>(bexp, new ParameterExpression[] { pex1, pex2 });

Func<int,int,int> tDelegate = lambdaExp.Compile();//编译成委托

Console.WriteLine(tDelegate(1, 3));

Console.Read();
Nach dem Login kopieren
Wir führen den obigen Code aus und das Ergebnis ist: 4. Wir haben viel Code geschrieben, der im Wesentlichen das Ergebnis von 1+3 mithilfe eines Ausdrucksbaums berechnet.

Das obige ist der detaillierte Inhalt vonEine kurze Einführung in Ausdrucksbäume in C#. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage