Partager via


Arborescences d’expressions (Visual Basic)

Les arborescences d’expressions représentent du code dans une structure de données de type arborescence, où chaque nœud est une expression, par exemple, un appel de méthode ou une opération binaire telle que x < y.

Vous pouvez compiler et exécuter du code représenté par des arborescences d’expressions. Cela 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. Pour plus d’informations sur les arborescences d’expressions dans LINQ, consultez Guide pratique pour utiliser des arborescences d’expressions pour générer des requêtes dynamiques (Visual Basic).

Les arborescences d’expressions sont également utilisées dans le runtime de langage dynamique (DLR) pour fournir une interopérabilité entre les langages dynamiques et le .NET Framework et pour permettre aux enregistreurs du compilateur d’émettre des arborescences d’expressions au lieu du langage intermédiaire commun (CIL). Pour plus d’informations sur le DLR, consultez Vue d’ensemble du runtime de langage dynamique.

Vous pouvez avoir le compilateur C# ou Visual Basic créer une arborescence d’expressions pour vous en fonction d’une expression lambda anonyme, ou vous pouvez créer manuellement des arborescences d’expressions à l’aide de l’espace System.Linq.Expressions de noms.

Création d’arborescences d’expressions à partir d’expressions lambda

Lorsqu’une expression lambda est affectée à une variable de type Expression<TDelegate>, le compilateur émet du code pour générer une arborescence d’expressions qui représente l’expression lambda.

Le compilateur Visual Basic peut générer des arborescences d’expressions uniquement à partir d’expressions lambda (ou d’expressions lambda à ligne unique). Il ne peut pas analyser les lambdas d’instruction (ou les lambda à plusieurs lignes). Pour plus d’informations sur les expressions lambda dans Visual Basic, consultez Expressions lambda.

Les exemples de code suivants montrent comment avoir le compilateur Visual Basic à créer une arborescence d’expressions qui représente l’expression Function(num) num < 5lambda.

Dim lambda As Expression(Of Func(Of Integer, Boolean)) =
    Function(num) num < 5

Création d’arborescences d’expressions à l’aide de l’API

Pour créer des arborescences d’expressions à l’aide de l’API, utilisez la Expression classe. 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, ParameterExpressionqui représente une variable ou un paramètre, ou MethodCallExpressionqui représente un appel de méthode. ParameterExpression, MethodCallExpression, et les autres types spécifiques à l’expression sont également définis dans l’espace de noms System.Linq.Expressions. Ces types dérivent du type Expressionabstrait .

L’exemple de code suivant montre comment créer une arborescence d’expressions qui représente l’expression Function(num) num < 5 lambda à l’aide de l’API.

' Import the following namespace to your project: System.Linq.Expressions

' Manually build the expression tree for the lambda expression num => num < 5.
Dim numParam As ParameterExpression = Expression.Parameter(GetType(Integer), "num")
Dim five As ConstantExpression = Expression.Constant(5, GetType(Integer))
Dim numLessThanFive As BinaryExpression = Expression.LessThan(numParam, five)
Dim lambda1 As Expression(Of Func(Of Integer, Boolean)) =
  Expression.Lambda(Of Func(Of Integer, Boolean))(
        numLessThanFive,
        New ParameterExpression() {numParam})

Dans .NET Framework 4 ou version ultérieure, l’API des arbres d'expression prend également en charge les affectations et les expressions de flux de contrôle, telles que les boucles, les blocs conditionnels et les blocs try-catch. À l’aide de l’API, vous pouvez créer des arborescences d’expressions plus complexes que celles qui peuvent être créées à partir d’expressions lambda par le compilateur Visual Basic. L’exemple suivant montre comment créer une arborescence d’expressions qui calcule la factorielle d’un nombre.

' Creating a parameter expression.
Dim value As ParameterExpression =
    Expression.Parameter(GetType(Integer), "value")

' Creating an expression to hold a local variable.
Dim result As ParameterExpression =
    Expression.Parameter(GetType(Integer), "result")

' Creating a label to jump to from a loop.
Dim label As LabelTarget = Expression.Label(GetType(Integer))

' Creating a method body.
Dim block As BlockExpression = Expression.Block(
    New ParameterExpression() {result},
    Expression.Assign(result, Expression.Constant(1)),
    Expression.Loop(
        Expression.IfThenElse(
            Expression.GreaterThan(value, Expression.Constant(1)),
            Expression.MultiplyAssign(result,
                Expression.PostDecrementAssign(value)),
            Expression.Break(label, result)
        ),
        label
    )
)

' Compile an expression tree and return a delegate.
Dim factorial As Integer =
    Expression.Lambda(Of Func(Of Integer, Integer))(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, qui s’applique également aux versions ultérieures de Visual Studio.

Analyse des arborescences d’expressions

L’exemple de code suivant montre comment l’arborescence d’expressions qui représente l’expression Function(num) num < 5 lambda peut être décomposée en ses parties.

' Import the following namespace to your project: System.Linq.Expressions

' Create an expression tree.
Dim exprTree As Expression(Of Func(Of Integer, Boolean)) = Function(num) num < 5

' Decompose the expression tree.
Dim param As ParameterExpression = exprTree.Parameters(0)
Dim operation As BinaryExpression = exprTree.Body
Dim left As ParameterExpression = operation.Left
Dim right As ConstantExpression = operation.Right

Console.WriteLine(String.Format("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’expressions

Les arborescences d’expressions doivent être immuables. Cela signifie que si vous souhaitez modifier une arborescence d’expressions, vous devez construire une nouvelle arborescence d’expressions en copiant celle existante et en remplaçant les nœuds dans celui-ci. Vous pouvez utiliser un visiteur de l’arborescence d’expressions pour parcourir l’arborescence d’expressions existante. Pour plus d’informations, consultez Guide pratique pour modifier des arborescences d’expressions (Visual Basic).

Compilation d’arborescences d’expressions

Le Expression<TDelegate> type fournit la Compile méthode qui compile le code représenté par une arborescence d’expressions dans un délégué exécutable.

L’exemple de code suivant montre comment compiler une arborescence d’expressions et exécuter le code résultant.

' Creating an expression tree.
Dim expr As Expression(Of Func(Of Integer, Boolean)) =
    Function(num) num < 5

' Compiling the expression tree into a delegate.
Dim result As Func(Of Integer, Boolean) = 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 (Visual Basic).

Voir aussi