Une brève introduction aux arbres d'expression en C#

黄舟
Libérer: 2017-09-16 11:08:45
original
2072 Les gens l'ont consulté

L'arbre d'expression peut être considéré comme l'un des cœurs de Linq. Pourquoi est-il l'un des cœurs de Linq ? Étant donné que l'arborescence d'expression fait que C# ne se contente plus de compiler en IL, nous pouvons générer une arborescence d'expression via C#, utiliser le résultat comme format intermédiaire et le convertir dans le langage natif sur la plate-forme cible. Tel que SQL. C'est ainsi que notre Linq to SQL couramment utilisé génère du SQL.

L'arbre d'expression a été introduit après .NET 3.5. Il s'agit d'un outil puissant et flexible (comme celui utilisé pour construire des requêtes dynamiques dans LINQ).

Jetons d'abord un œil à l'interface API de la classe Expression :

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);
    }
}
Copier après la connexion

La syntaxe de l'arbre d'expression est la suivante :


Expression<Func<type,returnType>> = (param) => lamdaexpresion;
Copier après la connexion

Par exemple :


Expression<Func<int, int, int>> expr = (x, y) => x+y;
Copier après la connexion

Nous exécutons le code ci-dessus et visualisons cet arbre d'expression en mode débogage VS :

Vous pouvez constater que l'arbre d'expression est principalement composé des quatre parties suivantes :

1. Partie du corps

2. .Partie Paramètres

3. Type de nœud NodeType

4. , le corps principal est : x+y, les paramètres sont (x, y), NodeType est une expression Lambda et la valeur de retour est int

La partie principale peut être une expression, mais elle ne peut pas contenir d'instructions. Par exemple : je définis un délégué, et l'expression Lambda peut s'écrire comme ceci :


peut aussi s'écrire comme ceci :

Func<int, int, int> func = (x, y) => x + y;
Copier après la connexion


Cependant, dans le type arbre d'expression, seule la première façon d'écrire peut être utilisée. Si la deuxième façon d'écrire est utilisée, une erreur de compilation sera signalée :

Le lambda. l'expression avec un corps d'instruction ne peut pas être convertie en un arbre d'expression
Func<int, int, int> func = (x, y) => { return x + y; };
Copier après la connexion
.

En plus de la manière d'écrire ci-dessus, l'arbre d'expression peut également s'écrire comme ceci :

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 });
Copier après la connexion

En mode débogage VS, vous pouvez voir que les arbres d'expression générés par les deux méthodes d'écriture sont les mêmes

Compilez l'arbre d'expression dans un délégué

LambdaExpression est un type dérivé de Expression . La classe générique Expression est dérivée de LambdaExpression, où le paramètre générique TDelegate doit être un type délégué.

LambdaExpression possède une méthode Compile qui crée un délégué du type approprié. La méthode Compile de Expression renvoie un délégué de type TDelegate. Jetons un coup d'œil à l'exemple suivant :

Nous exécutons le code ci-dessus et le résultat est : 4. Nous avons écrit beaucoup de code, qui calculait essentiellement le résultat de 1+3 à l'aide d'un arbre d'expression.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal