Árboles de expresión (C#)Expression Trees (C#)

Los árboles de expresión representan el código en una estructura de datos en forma de árbol donde cada nodo es una expresión, por ejemplo, una llamada a método o una operación binaria como 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.

El código representado en árboles de expresión se puede compilar y ejecutar.You can compile and run code represented by expression trees. Esto permite realizar cambios dinámicos en el código ejecutable, ejecutar consultas LINQ en varias bases de datos y crear consultas dinámicas.This enables dynamic modification of executable code, the execution of LINQ queries in various databases, and the creation of dynamic queries. Para más información sobre los árboles de expresión en LINQ, consulte Cómo: Usar árboles de expresión para crear consultas dinámicas (C#).For more information about expression trees in LINQ, see How to: Use Expression Trees to Build Dynamic Queries (C#).

Los árboles de expresión también se usan en Dynamic Language Runtime (DLR) para proporcionar interoperabilidad entre los lenguajes dinámicos y .NET Framework y, asimismo, para permitir que los programadores de compiladores emitan árboles de expresión en lugar de Lenguaje intermedio de Microsoft (MSIL).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). Para obtener más información sobre el entorno DLR, vea Dynamic Language Runtime Overview (Información general sobre Dynamic Language Runtime).For more information about the DLR, see Dynamic Language Runtime Overview.

Puede hacer que el compilador de Visual Basic o de C# cree un árbol de expresión en función de una expresión lambda anónima, o bien puede crear árboles de expresión manualmente usando el espacio de nombres 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.

Crear árboles de expresión a partir de expresiones lambdaCreating Expression Trees from Lambda Expressions

Cuando una expresión lambda se asigna a una variable de tipo Expression<TDelegate>, el compilador emite código para crear un árbol de expresión que represente la expresión 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.

El compilador de C# puede generar árboles de expresión solo a partir de lambdas de expresión (o de lambdas de una sola línea).The C# compiler can generate expression trees only from expression lambdas (or single-line lambdas). No pueden analizar lambdas de instrucción (o lambdas de varias líneas).It cannot parse statement lambdas (or multi-line lambdas). Para obtener más información sobre las expresiones lambda en C#, consulte Expresiones lambda.For more information about lambda expressions in C#, see Lambda Expressions.

Los siguientes ejemplos de código muestran cómo crear un árbol de expresión que represente la expresión lambda num => num < 5 con el compilador de C#.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;  

Crear árboles de expresión mediante la APICreating Expression Trees by Using the API

Para crear árboles de expresión mediante la API, use la clase Expression.To create expression trees by using the API, use the Expression class. Esta clase contiene métodos de fábrica estáticos que crean nodos de árbol de expresión de tipos específicos, como, por ejemplo, ParameterExpression, que representa una variable o un parámetro, o MethodCallExpression, que representa una llamada a método.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 y los demás tipos específicos de expresión también se definen en el espacio de nombres System.Linq.Expressions.ParameterExpression, MethodCallExpression, and the other expression-specific types are also defined in the System.Linq.Expressions namespace. Estos tipos se derivan del tipo abstracto Expression.These types derive from the abstract type Expression.

En el siguiente ejemplo de código se muestra cómo crear un árbol de expresión que represente la expresión lambda num => num < 5 mediante la 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 });  

En .NET Framework 4 y versiones posteriores, la API de árboles de expresión admite también asignaciones y expresiones de flujo de control como bucles, bloques condicionales y bloques 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. Con la API, se pueden crear árboles de expresión más complejos que los que pueden crear el compilador de C# a partir de expresiones lambda.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. En el siguiente ejemplo se indica cómo crear un árbol de expresión que calcula el factorial de un número.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.  

Para obtener más información, consulte Generating Dynamic Methods with Expression Trees in Visual Studio 2010 (Generar métodos dinámicos con árboles de expresión en Visual Studio 2010), que también se aplica a las últimas versiones de 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.

Analizar árboles de expresiónParsing Expression Trees

En el siguiente ejemplo de código se muestra cómo la expresión del árbol que representa la expresión lambda num => num < 5 se puede descomponer en partes.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  

Inmutabilidad de los árboles de expresiónImmutability of Expression Trees

Los árboles de expresión deben ser inmutables.Expression trees should be immutable. Esto significa que, si desea modificar un árbol de expresión, deberá construir un nuevo árbol de expresión copiando el ya existente y reemplazando los nodos que hay en él.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. Puede usar un visitante de árbol de expresión para recorrer el árbol de expresión existente.You can use an expression tree visitor to traverse the existing expression tree. Para obtener más información, vea Cómo: Modificar árboles de expresión (C#).For more information, see How to: Modify Expression Trees (C#).

Compilar árboles de expresiónCompiling Expression Trees

El tipo Expression<TDelegate> proporciona el método Compile que compila el código representado por un árbol de expresión en un delegado ejecutable.The Expression<TDelegate> type provides the Compile method that compiles the code represented by an expression tree into an executable delegate.

En el siguiente ejemplo de código se indica cómo compilar un árbol de expresión y ejecutar el código resultante.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.  

Para obtener más información, vea Cómo: Ejecutar árboles de expresión (C#).For more information, see How to: Execute Expression Trees (C#).

Vea tambiénSee also