Condividi tramite


Alberi delle espressioni (Visual Basic)

Gli alberi delle espressioni rappresentano il codice in una struttura di dati simile ad albero, in cui ogni nodo è un'espressione, ad esempio una chiamata al metodo o un'operazione binaria, ad x < yesempio .

È possibile compilare ed eseguire codice rappresentato dagli alberi delle espressioni. Ciò consente la modifica dinamica del codice eseguibile, l'esecuzione di query LINQ in vari database e la creazione di query dinamiche. Per altre informazioni sugli alberi delle espressioni in LINQ, vedere Procedura: Usare alberi delle espressioni per compilare query dinamiche (Visual Basic).For more information about expression trees in LINQ, see How to: Use Expression Trees to Build Dynamic Queries (Visual Basic).

Gli alberi delle espressioni vengono usati anche in DLR (Dynamic Language Runtime) per garantire l'interoperabilità tra i linguaggi dinamici e .NET Framework e per consentire ai writer del compilatore di generare alberi delle espressioni anziché common intermediate language (CIL). Per ulteriori informazioni su DLR, vedere Panoramica del Dynamic Language Runtime.

È possibile fare in modo che il compilatore C# o Visual Basic crei un albero delle espressioni automaticamente in base a un'espressione lambda anonima, oppure è possibile creare manualmente alberi delle espressioni usando lo spazio dei nomi System.Linq.Expressions.

Creazione di alberi delle espressioni da espressioni lambda

Quando un'espressione lambda viene assegnata a una variabile di tipo Expression<TDelegate>, il compilatore genera codice per compilare un albero delle espressioni che rappresenta l'espressione lambda.

Il compilatore Visual Basic può generare alberi delle espressioni solo da espressioni lambda (o espressioni lambda a riga singola). Non può analizzare le lambda di espressione (o lambda multi-linea). Per altre informazioni sulle espressioni lambda in Visual Basic, vedere Espressioni lambda.

Negli esempi di codice seguenti viene illustrato come fare in modo che il compilatore Visual Basic crei un albero delle espressioni che rappresenta l'espressione Function(num) num < 5lambda .

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

Creazione di alberi delle espressioni tramite l'API

Per creare alberi delle espressioni usando l'API, usare la Expression classe . Questa classe contiene metodi factory statici che creano nodi dell'albero delle espressioni di tipi specifici, ad esempio , ParameterExpressionche rappresenta una variabile o un parametro o MethodCallExpression, che rappresenta una chiamata al metodo. ParameterExpression, MethodCallExpression, e gli altri tipi specifici dell'espressione sono anche definiti nel System.Linq.Expressions namespace. Questi tipi derivano dal tipo Expressionastratto .

Nell'esempio di codice seguente viene illustrato come creare un albero delle espressioni che rappresenta l'espressione Function(num) num < 5 lambda usando 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})

In .NET Framework 4 o versione successiva, l'API degli alberi delle espressioni supporta anche le assegnazioni e le espressioni del flusso di controllo, ad esempio cicli, blocchi condizionali e try-catch blocchi. Usando l'API, è possibile creare alberi delle espressioni più complessi rispetto a quelli che possono essere creati da espressioni lambda dal compilatore Visual Basic. Nell'esempio seguente viene illustrato come creare un albero delle espressioni che calcola il fattoriale di un numero.

' 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.

Per altre informazioni, vedere Generazione di metodi dinamici con alberi delle espressioni in Visual Studio 2010, che si applica anche alle versioni successive di Visual Studio.

Analisi degli alberi delle espressioni

Nell'esempio di codice seguente viene illustrato come l'albero delle espressioni che rappresenta l'espressione Function(num) num < 5 lambda può essere scomposto nelle relative parti.

' 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

Immutabilità degli alberi delle espressioni

Gli alberi delle espressioni non devono essere modificabili. Ciò significa che se si desidera modificare un albero delle espressioni, è necessario costruire un nuovo albero delle espressioni copiando quello esistente e sostituendo i nodi in esso contenuti. È possibile usare un visitatore dell'albero delle espressioni per attraversare l'albero delle espressioni esistente. Per altre informazioni, vedere Procedura: Modificare alberi delle espressioni (Visual Basic).For more information, see How to: Modify Expression Trees (Visual Basic).

Compilazione di alberi delle espressioni

Il Expression<TDelegate> tipo fornisce il Compile metodo che compila il codice rappresentato da un albero delle espressioni in un delegato eseguibile.

Nell'esempio di codice seguente viene illustrato come compilare un albero delle espressioni ed eseguire il codice risultante.

' 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.

Per altre informazioni, vedere Procedura: Eseguire alberi delle espressioni (Visual Basic).For more information, see How to: Execute Expression Trees (Visual Basic).

Vedere anche