Udostępnij za pośrednictwem


Expression Trees

Expression trees represent language-level code in the form of data. The data is stored in a tree-shaped structure. Each node in the expression tree represents an expression, for example a method call or a binary operation such as x < y.

The following illustration shows an example of an expression and its representation in the form of an expression tree. The different parts of the expression are color coded to match the corresponding expression tree node in the expression tree. The different types of the expression tree nodes are also shown.

Expression tree diagram

The following code example demonstrates how the expression tree that represents the lambda expression num => num < 5 (C#) or Function(num) num < 5 (Visual Basic) can be decomposed into its parts.

' 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
*/

Building Expression Trees

The System.Linq.Expressions namespace provides an API for building expression trees manually. The Expression class contains static factory methods that create expression tree nodes of specific types, for example a ParameterExpression, which represents a named parameter expression, or a MethodCallExpression, which represents a method call. ParameterExpression, MethodCallExpression, and the other expression-specific expression tree types are also defined in the System.Linq.Expressions namespace. These types derive from the abstract type Expression.

The compiler can also build an expression tree for you. A compiler-generated expression tree is always rooted in a node of type Expression<TDelegate>; that is, its root node represents a lambda expression.

The following code example demonstrates two ways to create an expression tree that represents the lambda expression num => num < 5 (C#) or 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;

Immutability of Expression Trees

Expression trees are immutable. This means that if you want to modify an expression tree, you must construct a new expression tree by copying the existing one and modifying it. You can use an expression tree visitor to traverse the existing expression tree. For more information, see How to: Implement an Expression Tree Visitor and How to: Modify Expression Trees.

Lambda Expressions

When a lambda expression is assigned to a variable of type Expression<TDelegate>, the compiler emits an expression tree that represents the lambda expression. For example, some standard query operator methods that are defined in the Queryable class have parameters of type Expression<TDelegate>. When you call these methods, you can pass in a lambda expression and the compiler will generate an expression tree.

The Expression<TDelegate> type provides the Compile method, that compiles the code represented by the expression tree into an executable delegate. This executable code is equivalent to the executable code that would have been generated had the lambda expression been assigned to a delegate type originally.

Note

Only those expression trees that represent functions, namely Expression<TDelegate> and its parent type LambdaExpression, can be compiled into executable code. To execute other types of expression trees, you must first wrap them in a LambdaExpression node. You can obtain such a LambdaExpression by calling the Lambda method and passing the expression tree as the argument.

See Also

Tasks

How to: Execute Expression Trees

How to: Modify Expression Trees

How to: Implement an Expression Tree Visitor

Concepts

Expression Trees in LINQ

Lambda Expressions

Reference

Lambda Expressions (C# Programming Guide)

System.Linq.Expressions