Arborescences d’expressions (C#)Expression Trees (C#)

Les arborescences d'expressions représentent du code dans une structure de données arborescente, où chaque nœud est une expression, par exemple un appel de méthode ou une opération binaire comme x < y.Expression trees represent code in a tree-like data structure, where each node is an expression, for example, a method call or a binary operation such as x < y.

Vous pouvez compiler et exécuter du code représenté par des arborescences d'expressions.You can compile and run code represented by expression trees. Ceci permet la modification dynamique du code exécutable, l'exécution de requêtes LINQ dans différentes bases de données et la création de requêtes dynamiques.This enables dynamic modification of executable code, the execution of LINQ queries in various databases, and the creation of dynamic queries. Pour plus d'informations sur les arborescences d'expressions dans LINQ, consultez Guide pratique pour utiliser des arborescences d’expressions dans le but de générer des requêtes dynamiques (C#).For more information about expression trees in LINQ, see How to: Use Expression Trees to Build Dynamic Queries (C#).

Les arborescences d’expressions sont également utilisées dans l’environnement d’exécution de langage dynamique (DLR, Dynamic Language Runtime) pour fournir une interopérabilité entre les langages dynamiques et .NET Framework, ainsi que pour permettre aux writers de compilateur d’émettre des arborescences d’expressions au lieu d’utiliser le langage intermédiaire MSIL (Microsoft Intermediate Language).Expression trees are also used in the dynamic language runtime (DLR) to provide interoperability between dynamic languages and the .NET Framework and to enable compiler writers to emit expression trees instead of Microsoft intermediate language (MSIL). Pour plus d’informations sur le DLR, consultez Vue d’ensemble du Dynamic Language Runtime.For more information about the DLR, see Dynamic Language Runtime Overview.

Le compilateur C# ou Visual Basic peut créer pour vous une arborescence d'expressions basée sur une expression lambda anonyme. Vous pouvez aussi créer manuellement des arborescences d'expressions en utilisant l'espace de noms System.Linq.Expressions.You can have the C# or Visual Basic compiler create an expression tree for you based on an anonymous lambda expression, or you can create expression trees manually by using the System.Linq.Expressions namespace.

Création d'arborescences d'expressions à partir d'expressions lambdaCreating Expression Trees from Lambda Expressions

Quand une expression lambda est affectée à une variable de type Expression<TDelegate>, le compilateur produit du code pour générer une arborescence d'expressions qui représente l'expression lambda.When a lambda expression is assigned to a variable of type Expression<TDelegate>, the compiler emits code to build an expression tree that represents the lambda expression.

Le compilateur C# peut générer des arborescences d’expressions seulement à partir d’expressions lambda (ou de lambdas sur une seule ligne).The C# compiler can generate expression trees only from expression lambdas (or single-line lambdas). Ils ne peuvent pas analyser des lambdas d'instruction (ou lambdas multilignes).It cannot parse statement lambdas (or multi-line lambdas). Pour plus d’informations sur les expressions lambda en C#, consultez Expressions lambda.For more information about lambda expressions in C#, see Lambda Expressions.

Les exemples de code suivants montrent comment le compilateur C# crée une arborescence d’expressions qui représente l’expression lambda num => num < 5.The following code examples demonstrate how to have the C# compiler create an expression tree that represents the lambda expression num => num < 5.

Expression<Func<int, bool>> lambda = num => num < 5;  

Création d’arborescences d’expressions à l’aide de l’APICreating Expression Trees by Using the API

Pour créer des arborescences d'expressions à l'aide de l'API, utilisez la classe Expression.To create expression trees by using the API, use the Expression class. Cette classe contient des méthodes de fabrique statiques qui créent des nœuds d'arborescence d'expressions de types spécifiques, par exemple ParameterExpression, qui représente une variable ou un paramètre, ou MethodCallExpression, qui représente un appel de méthode.This class contains static factory methods that create expression tree nodes of specific types, for example, ParameterExpression, which represents a variable or parameter, or MethodCallExpression, which represents a method call. ParameterExpression, MethodCallExpression et les autres types spécifiques à une expression sont également définis dans l'espace de noms System.Linq.Expressions.ParameterExpression, MethodCallExpression, and the other expression-specific types are also defined in the System.Linq.Expressions namespace. Ces types dérivent du type abstrait Expression.These types derive from the abstract type Expression.

L’exemple de code suivant montre comment créer une arborescence d’expressions qui représente l’expression lambda num => num < 5 à l’aide de l’API.The following code example demonstrates how to create an expression tree that represents the lambda expression num => num < 5 by using the API.

// Add the following using directive to your code file:  
// using System.Linq.Expressions;  
  
// Manually build the expression tree for   
// the lambda expression num => num < 5.  
ParameterExpression numParam = Expression.Parameter(typeof(int), "num");  
ConstantExpression five = Expression.Constant(5, typeof(int));  
BinaryExpression numLessThanFive = Expression.LessThan(numParam, five);  
Expression<Func<int, bool>> lambda1 =  
    Expression.Lambda<Func<int, bool>>(  
        numLessThanFive,  
        new ParameterExpression[] { numParam });  

Dans le .NET Framework 4 ou ultérieur, l’API des arborescences d’expressions prend également en charge les affectations et les expressions de flux de contrôle, comme les boucles, les blocs conditionnels et les blocs try-catch.In .NET Framework 4 or later, the expression trees API also supports assignments and control flow expressions such as loops, conditional blocks, and try-catch blocks. À l’aide de l’API, vous pouvez créer des arborescences d’expressions qui sont plus complexes que celles qui peuvent être créées à partir d’expressions lambda par le compilateur C#.By using the API, you can create expression trees that are more complex than those that can be created from lambda expressions by the C# compiler. L’exemple suivant montre comment créer une arborescence d’expressions qui calcule la factorielle d’un nombre.The following example demonstrates how to create an expression tree that calculates the factorial of a number.

// Creating a parameter expression.  
ParameterExpression value = Expression.Parameter(typeof(int), "value");  
  
// Creating an expression to hold a local variable.   
ParameterExpression result = Expression.Parameter(typeof(int), "result");  
  
// Creating a label to jump to from a loop.  
LabelTarget label = Expression.Label(typeof(int));  
  
// Creating a method body.  
BlockExpression block = Expression.Block(  
    // Adding a local variable.  
    new[] { result },  
    // Assigning a constant to a local variable: result = 1  
    Expression.Assign(result, Expression.Constant(1)),  
    // Adding a loop.  
        Expression.Loop(  
    // Adding a conditional block into the loop.  
           Expression.IfThenElse(  
    // Condition: value > 1  
               Expression.GreaterThan(value, Expression.Constant(1)),  
    // If true: result *= value --  
               Expression.MultiplyAssign(result,  
                   Expression.PostDecrementAssign(value)),  
    // If false, exit the loop and go to the label.  
               Expression.Break(label, result)  
           ),  
    // Label to jump to.  
       label  
    )  
);  
  
// Compile and execute an expression tree.  
int factorial = Expression.Lambda<Func<int, int>>(block, value).Compile()(5);  
  
Console.WriteLine(factorial);  
// Prints 120.  

Pour plus d’informations, consultez Génération de méthodes dynamiques avec des arborescences d’expressions dans Visual Studio 2010 (ou version ultérieure).For more information, see Generating Dynamic Methods with Expression Trees in Visual Studio 2010, which also applies to later versions of Visual Studio.

Analyse des arborescences d’expressionsParsing Expression Trees

L’exemple de code suivant montre comment l’arborescence d’expressions qui représente l’expression lambda num => num < 5 peut être décomposée selon ses différentes parties.The following code example demonstrates how the expression tree that represents the lambda expression num => num < 5 can be decomposed into its parts.

// Add the following using directive to your code file:  
// using System.Linq.Expressions;  
  
// Create an expression tree.  
Expression<Func<int, bool>> exprTree = num => num < 5;  
  
// Decompose the expression tree.  
ParameterExpression param = (ParameterExpression)exprTree.Parameters[0];  
BinaryExpression operation = (BinaryExpression)exprTree.Body;  
ParameterExpression left = (ParameterExpression)operation.Left;  
ConstantExpression right = (ConstantExpression)operation.Right;  
  
Console.WriteLine("Decomposed expression: {0} => {1} {2} {3}",  
                  param.Name, left.Name, operation.NodeType, right.Value);  
  
// This code produces the following output:  
  
// Decomposed expression: num => num LessThan 5  

Immuabilité des arborescences d’expressionsImmutability of Expression Trees

Les arborescences d'expressions doivent être immuables.Expression trees should be immutable. Cela signifie que si vous voulez modifier une arborescence d'expressions, vous devez construire une nouvelle arborescence d'expressions en copiant l'arborescence existante et en y remplaçant les nœuds.This means that if you want to modify an expression tree, you must construct a new expression tree by copying the existing one and replacing nodes in it. Vous pouvez utiliser un visiteur d’arborescence d’expressions pour parcourir l’arborescence d’expressions existante.You can use an expression tree visitor to traverse the existing expression tree. Pour plus d’informations, consultez Guide pratique pour Modifier des arborescences d’expressions (C#).For more information, see How to: Modify Expression Trees (C#).

Compilation des arborescences d’expressionsCompiling Expression Trees

Le type Expression<TDelegate> fournit la méthode Compile qui compile le code représenté par une arborescence d'expressions en un délégué exécutable.The Expression<TDelegate> type provides the Compile method that compiles the code represented by an expression tree into an executable delegate.

L’exemple de code suivant montre comment compiler une arborescence d’expressions et exécuter le code résultant.The following code example demonstrates how to compile an expression tree and run the resulting code.

// Creating an expression tree.  
Expression<Func<int, bool>> expr = num => num < 5;  
  
// Compiling the expression tree into a delegate.  
Func<int, bool> result = expr.Compile();  
  
// Invoking the delegate and writing the result to the console.  
Console.WriteLine(result(4));  
  
// Prints True.  
  
// You can also use simplified syntax  
// to compile and run an expression tree.  
// The following line can replace two previous statements.  
Console.WriteLine(expr.Compile()(4));  
  
// Also prints True.  

Pour plus d’informations, consultez Guide pratique pour Exécuter des arborescences d’expressions (C#).For more information, see How to: Execute Expression Trees (C#).

Voir aussiSee also