Strutture ad albero dell'espressione
Aggiornamento: novembre 2007
Le strutture ad albero dell'espressione rappresentano codice a livello di linguaggio sotto forma di dati. I dati vengono archiviati in una struttura a forma di albero. Ogni nodo nella struttura ad albero dell'espressione rappresenta un'espressione, ad esempio una chiamata al metodo o un'operazione binaria quale x < y.
Nella figura seguente viene illustrato un esempio di espressione e la relativa rappresentazione sotto forma di struttura ad albero dell'espressione. Le diverse parti dell'espressione sono visualizzate con colori diversi per indicare la corrispondenza con il rispettivo nodo nella struttura ad albero dell'espressione. Vengono illustrati anche i diversi tipi di nodi della struttura ad albero dell'espressione.
Nell'esempio di codice seguente viene illustrato come la struttura ad albero dell'espressione che rappresenta l'espressione lambda num => num < 5 (C#) o Function(num) num < 5 (Visual Basic) possa essere scomposta 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(ByVal 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
MsgBox(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
// 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
*/
Compilazione di strutture ad albero dell'espressione
Nello spazio dei nomi System.Linq.Expressions è disponibile un'API per la compilazione manuale di strutture ad albero dell'espressione. La classe Expression contiene metodi factory statici che creano nodi della struttura ad albero dell'espressione di tipi specifici, ad esempio ParameterExpression che rappresenta un'espressione di parametri denominati o MethodCallExpression che rappresenta una chiamata al metodo. ParameterExpression, MethodCallExpression e gli altri tipi di struttura ad albero dell'espressione specifici dell'espressione vengono inoltre definiti nello spazio dei nomi System.Linq.Expressions. Tali tipi derivano dal tipo astratto Expression.
Il compilatore è inoltre in grado di compilare automaticamente una struttura ad albero dell'espressione che, in questo caso, ha sempre origine in un nodo di tipo Expression<TDelegate>; ovvero il relativo nodo radice rappresenta un'espressione lambda.
Nell'esempio di codice seguente vengono illustrati due modi per creare una struttura ad albero dell'espressione che rappresenta l'espressione lambda num => num < 5 (C#) o Function(num) num < 5 (Visual Basic).
' 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})
' Let the compiler generate the expression tree for
' the lambda expression num => num < 5.
Dim lambda2 As Expression(Of Func(Of Integer, Boolean)) = Function(ByVal num) num < 5
// 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 });
// Let the compiler generate the expression tree for
// the lambda expression num => num < 5.
Expression<Func<int, bool>> lambda2 = num => num < 5;
Immutabilità delle strutture ad albero dell'espressione
Le strutture ad albero dell'espressione sono immutabili. Ciò significa che se si desidera modificare una struttura ad albero dell'espressione, è necessario costruirne una nuova copiando quella esistente e modificandola. Per attraversare la struttura ad albero dell'espressione esistente, è possibile utilizzare un visitatore della struttura a albero dell'espressione. Per ulteriori informazioni, vedere Procedura: implementare un visitatore della struttura ad albero dell'espressione e Procedura: modificare strutture ad albero dell'espressione.
Espressioni lambda
Quando un'espressione lambda viene assegnata a una variabile di tipo Expression<TDelegate>, il compilatore genera una struttura ad albero dell'espressione che rappresenta l'espressione lambda. Ad esempio, alcuni metodi dell'operatore di query standard definiti nella classe Queryable dispongono di parametri di tipo Expression<TDelegate>. Quando si chiamano questi metodi, è possibile passare un'espressione lambda per fare in modo che il compilatore generi una struttura ad albero dell'espressione.
Il tipo Expression<TDelegate> fornisce il metodo Compile che compila il codice rappresentato dalla struttura ad albero dell'espressione in un delegato eseguibile. Tale codice eseguibile è equivalente al codice eseguibile che sarebbe stato generato se l'espressione lambda fosse stata assegnata in origine a un tipo delegato.
Nota: |
---|
Solo le strutture ad albero dell'espressione che rappresentano funzioni, vale a dire Expression<TDelegate> e il relativo tipo padre LambdaExpression, possono essere compilate in codice eseguibile. Per eseguire altri tipi di strutture ad albero dell'espressione, è necessario eseguirne prima il wrapping in un nodo LambdaExpression. È possibile ottenere tale LambdaExpression chiamando il metodo Lambda e passando la struttura ad albero dell'espressione come argomento. |
Vedere anche
Attività
Procedura: eseguire strutture ad albero dell'espressione
Procedura: modificare strutture ad albero dell'espressione
Procedura: implementare un visitatore della struttura ad albero dell'espressione
Concetti
Strutture ad albero dell'espressione in LINQ