Alberi delle espressioni (C#)Expression Trees (C#)

Gli alberi delle espressioni rappresentano codice in una struttura dei dati simile a un albero, dove ogni nodo è un'espressione, ad esempio una chiamata al metodo o un'operazione binaria come 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.

È possibile compilare ed eseguire codice rappresentato dagli alberi delle espressioni.You can compile and run code represented by expression trees. In questo modo è possibile modificare dinamicamente codice eseguibile, eseguire query LINQ in vari database e creare query dinamiche.This enables dynamic modification of executable code, the execution of LINQ queries in various databases, and the creation of dynamic queries. Per altre informazioni sulle strutture ad albero in LINQ, vedere Procedura: Usare alberi delle espressioni per la compilazione di query dinamiche (C#).For more information about expression trees in LINQ, see How to: Use Expression Trees to Build Dynamic Queries (C#).

Gli alberi delle espressioni sono anche usati in Dynamic Language Runtime (DLR) per fornire interoperabilità tra linguaggi dinamici e .NET Framework e per consentire ai writer dei compilatori di creare alberi delle espressioni invece di codice 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). Per altre informazioni su DLR, vedere Dynamic Language Runtime Overview (Panoramica su Dynamic Language Runtime).For more information about the DLR, see Dynamic Language Runtime Overview.

È possibile creare un albero delle espressioni tramite il compilatore di C# o di Visual Basic in base a un'espressione lambda anonima o creare tali alberi di espressioni manualmente tramite il nome spazio 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.

Creazione di alberi di espressioni da espressioni lambdaCreating Expression Trees from Lambda Expressions

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

Il compilatore di C# può generare alberi delle espressioni solo da espressioni lambda, o lambda su una sola riga.The C# compiler can generate expression trees only from expression lambdas (or single-line lambdas). Non possono analizzare espressioni lambda dell'istruzione (o le espressioni lambda a più righe).It cannot parse statement lambdas (or multi-line lambdas). Per altre informazioni sulle espressioni lambda in C#, vedere Espressioni lambda.For more information about lambda expressions in C#, see Lambda Expressions.

Gli esempi di codice seguenti illustrano in che modo il compilatore di C# crea un albero delle espressioni che rappresenta l'espressione 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;  

Creazione di alberi delle espressioni tramite l'APICreating Expression Trees by Using the API

Per creare alberi delle espressioni tramite l'API, usare la classe Expression.To create expression trees by using the API, use the Expression class. Questa classe contiene metodi factory statici che creano nodi degli alberi delle espressioni di tipi specifici, ad esempio ParameterExpression, che rappresenta una variabile o un parametro, o MethodCallExpression, che rappresenta una chiamata al metodo.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. Anche ParameterExpression, MethodCallExpression e gli altri tipi specifici delle espressioni sono definiti nello spazio dei nomi System.Linq.Expressions.ParameterExpression, MethodCallExpression, and the other expression-specific types are also defined in the System.Linq.Expressions namespace. Questi tipi derivano dal tipo astratto Expression.These types derive from the abstract type Expression.

L'esempio di codice seguente illustra come creare un albero delle espressioni che rappresenti l'espressione lambda num => num < 5 usando 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 });  

In .NET Framework 4 o nelle versioni successive l'API degli alberi delle espressioni supporta anche assegnazioni ed espressioni del flusso di controllo quali cicli, blocchi condizionali e blocchi 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. Tramite l'API è possibile creare alberi delle espressioni più complessi rispetto a quelli che è possibile creare da espressioni lambda con il compilatore di 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'esempio seguente illustra come creare un albero delle espressioni che calcola il fattoriale di un numero.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.  

Per altre informazioni, vedere l'articolo Generating Dynamic Methods with Expression Trees in Visual Studio 2010 (Generazione di metodi dinamici con alberi delle espressioni in Visual Studio 2010), valido anche per le versioni successive di Visual Studio.For more information, see Generating Dynamic Methods with Expression Trees in Visual Studio 2010, which also applies to later versions of Visual Studio.

Analisi degli alberi delle espressioniParsing Expression Trees

L'esempio di codice seguente illustra come scomporre nei vari componenti l'albero delle espressioni che rappresenta l'espressione lambda num => num < 5.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  

Non modificabilità degli alberi delle espressioniImmutability of Expression Trees

Gli alberi delle espressioni devono essere non modificabili.Expression trees should be immutable. Ciò significa che per modificare un albero delle espressioni è necessario costruirne uno nuovo copiando quello esistente e sostituendone i nodi.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. È possibile usare un visitatore dell'albero delle espressioni per attraversare l'albero delle espressioni esistente.You can use an expression tree visitor to traverse the existing expression tree. Per altre informazioni, vedere Procedura: Modificare alberi delle espressioni (C#).For more information, see How to: Modify Expression Trees (C#).

Compilazione degli alberi delle espressioniCompiling Expression Trees

Il tipo Expression<TDelegate> fornisce il metodo Compile che compila il codice rappresentato da un albero delle espressioni in un delegato eseguibile.The Expression<TDelegate> type provides the Compile method that compiles the code represented by an expression tree into an executable delegate.

L'esempio di codice seguente illustra come compilare un albero delle espressioni ed eseguire il codice risultante.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.  

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

Vedere ancheSee also