C#idiomatic C#
expression-trees-executioncsharp/advanced-topics/expression-trees

Advanced

Execute expression trees

Learn about executing expression trees by converting them into executable Intermediate Language (IL) instructions.

  • page csharp/advanced-topics/expression-trees/expression-trees-execution
  • updated 03/06/2023

An expression tree is a data structure that represents some code. It isn't compiled and executable code. If you want to execute the .NET code represented by an expression tree, you must convert it into executable IL instructions. Executing an expression tree may return a value, or it may just perform an action such as calling a method.

Only expression trees that represent lambda expressions can be executed. Expression trees that represent lambda expressions are of type System.Linq.Expressions.LambdaExpression or System.Linq.Expressions.Expression. To execute these expression trees, call the System.Linq.Expressions.LambdaExpression.Compile method to create an executable delegate, and then invoke the delegate.

If an expression tree doesn't represent a lambda expression, you can create a new lambda expression that has the original expression tree as its body, by calling the [System.Linq.Expressions.Expression.Lambda`%28System.Linq.Expressions.Expression%2CSystem.Collections.Generic.IEnumerable%7BSystem.Linq.Expressions.ParameterExpression%7D%29](https://learn.microsoft.com/en-us/dotnet/api/system.linq.expressions.expression.lambda--1%28system.linq.expressions.expression%2csystem.collections.generic.ienumerable%7bsystem.linq.expressions.parameterexpression%7d%29) method. Then, you can execute the lambda expression as described earlier in this section.

Lambda expressions to functions

You can convert any LambdaExpression, or any type derived from LambdaExpression into executable IL. Other expression types can't be directly converted into code. This restriction has little effect in practice. Lambda expressions are the only types of expressions that you would want to execute by converting to executable intermediate language (IL). (Think about what it would mean to directly execute a System.Linq.Expressions.ConstantExpression. Would it mean anything useful?) Any expression tree that is a System.Linq.Expressions.LambdaExpression, or a type derived from LambdaExpression can be converted to IL. The expression type System.Linq.Expressions.Expression is the only concrete example in the .NET Core libraries. It's used to represent an expression that maps to any delegate type. Because this type maps to a delegate type, .NET can examine the expression, and generate IL for an appropriate delegate that matches the signature of the lambda expression. The delegate type is based on the expression type. You must know the return type and the argument list if you want to use the delegate object in a strongly typed manner. The LambdaExpression.Compile() method returns the Delegate type. You have to cast it to the correct delegate type to have any compile-time tools check the argument list or return type.

In most cases, a simple mapping between an expression and its corresponding delegate exists. For example, an expression tree represented by Expression<Func<int>> would be converted to a delegate of the type Func<int>. For a lambda expression with any return type and argument list, there exists a delegate type that is the target type for the executable code represented by that lambda expression.

The System.Linq.Expressions.LambdaExpression type contains System.Linq.Expressions.LambdaExpression.Compile and System.Linq.Expressions.LambdaExpression.CompileToMethod members that you would use to convert an expression tree to executable code. The Compile method creates a delegate. The CompileToMethod method updates a System.Reflection.Emit.MethodBuilder object with the IL that represents the compiled output of the expression tree.

Optionally, you can also provide a System.Runtime.CompilerServices.DebugInfoGenerator that receives the symbol debugging information for the generated delegate object. The DebugInfoGenerator provides full debugging information about the generated delegate.

You would convert an expression into a delegate using the following code:

sample · csharpdocs/csharp/advanced-topics/expression-trees/snippets/RunExpressionTrees.csConvertToDelegate

csharp
using System.Linq.Expressions;

public static class RunExpressionTrees
{
    public static void ConvertToDelegate()
    {
        // <ConvertToDelegate>
        Expression<Func<int>> add = () => 1 + 2;
        var func = add.Compile(); // Create Delegate
        var answer = func(); // Invoke Delegate
        Console.WriteLine(answer);
        // </ConvertToDelegate>
    }

    public static void CreateExpressionTree()
    {
        // <CreateExpressionTree>
        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.
        // </CreateExpressionTree>
    }

    public static void BuildExpressionTree()
    {
        // <ConvertToFund>
        // The expression tree to execute.
        BinaryExpression be = Expression.Power(Expression.Constant(2d), Expression.Constant(3d));

        // Create a lambda expression.
        Expression<Func<double>> le = Expression.Lambda<Func<double>>(be);

        // Compile the lambda expression.
        Func<double> compiledExpression = le.Compile();

        // Execute the lambda expression.
        double result = compiledExpression();

        // Display the result.
        Console.WriteLine(result);

        // This code produces the following output:
        // 8
        // </ConvertToFund>
    }

    // <CreateBoundFunc>
    private static Func<int, int> CreateBoundFunc()
    {
        var constant = 5; // constant is captured by the expression tree
        Expression<Func<int, int>> expression = (b) => constant + b;
        var rVal = expression.Compile();
        return rVal;
    }
    // </CreateBoundFunc>

    // <CreateBoundResource>
    private static Func<int, int> CreateBoundResource()
    {
        using (var constant = new Resource()) // constant is captured by the expression tree
        {
            Expression<Func<int, int>> expression = (b) => constant.Argument + b;
            var rVal = expression.Compile();
            return rVal;
        }
    }
    // </CreateBoundResource>
}

// <ResourceClass>
public class Resource : IDisposable
{
    private bool _isDisposed = false;
    public int Argument
    {
        get
        {
            if (!_isDisposed)
                return 5;
            else throw new ObjectDisposedException("Resource");
        }
    }

    public void Dispose()
    {
        _isDisposed = true;
    }
}
// </ResourceClass>

The following code example demonstrates the concrete types used when you compile and execute an expression tree.

sample · csharpdocs/csharp/advanced-topics/expression-trees/snippets/RunExpressionTrees.csCreateExpressionTree

csharp
using System.Linq.Expressions;

public static class RunExpressionTrees
{
    public static void ConvertToDelegate()
    {
        // <ConvertToDelegate>
        Expression<Func<int>> add = () => 1 + 2;
        var func = add.Compile(); // Create Delegate
        var answer = func(); // Invoke Delegate
        Console.WriteLine(answer);
        // </ConvertToDelegate>
    }

    public static void CreateExpressionTree()
    {
        // <CreateExpressionTree>
        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.
        // </CreateExpressionTree>
    }

    public static void BuildExpressionTree()
    {
        // <ConvertToFund>
        // The expression tree to execute.
        BinaryExpression be = Expression.Power(Expression.Constant(2d), Expression.Constant(3d));

        // Create a lambda expression.
        Expression<Func<double>> le = Expression.Lambda<Func<double>>(be);

        // Compile the lambda expression.
        Func<double> compiledExpression = le.Compile();

        // Execute the lambda expression.
        double result = compiledExpression();

        // Display the result.
        Console.WriteLine(result);

        // This code produces the following output:
        // 8
        // </ConvertToFund>
    }

    // <CreateBoundFunc>
    private static Func<int, int> CreateBoundFunc()
    {
        var constant = 5; // constant is captured by the expression tree
        Expression<Func<int, int>> expression = (b) => constant + b;
        var rVal = expression.Compile();
        return rVal;
    }
    // </CreateBoundFunc>

    // <CreateBoundResource>
    private static Func<int, int> CreateBoundResource()
    {
        using (var constant = new Resource()) // constant is captured by the expression tree
        {
            Expression<Func<int, int>> expression = (b) => constant.Argument + b;
            var rVal = expression.Compile();
            return rVal;
        }
    }
    // </CreateBoundResource>
}

// <ResourceClass>
public class Resource : IDisposable
{
    private bool _isDisposed = false;
    public int Argument
    {
        get
        {
            if (!_isDisposed)
                return 5;
            else throw new ObjectDisposedException("Resource");
        }
    }

    public void Dispose()
    {
        _isDisposed = true;
    }
}
// </ResourceClass>

The following code example demonstrates how to execute an expression tree that represents raising a number to a power by creating a lambda expression and executing it. The result, which represents the number raised to the power, is displayed.

sample · csharpdocs/csharp/advanced-topics/expression-trees/snippets/RunExpressionTrees.csConvertToFund

csharp
using System.Linq.Expressions;

public static class RunExpressionTrees
{
    public static void ConvertToDelegate()
    {
        // <ConvertToDelegate>
        Expression<Func<int>> add = () => 1 + 2;
        var func = add.Compile(); // Create Delegate
        var answer = func(); // Invoke Delegate
        Console.WriteLine(answer);
        // </ConvertToDelegate>
    }

    public static void CreateExpressionTree()
    {
        // <CreateExpressionTree>
        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.
        // </CreateExpressionTree>
    }

    public static void BuildExpressionTree()
    {
        // <ConvertToFund>
        // The expression tree to execute.
        BinaryExpression be = Expression.Power(Expression.Constant(2d), Expression.Constant(3d));

        // Create a lambda expression.
        Expression<Func<double>> le = Expression.Lambda<Func<double>>(be);

        // Compile the lambda expression.
        Func<double> compiledExpression = le.Compile();

        // Execute the lambda expression.
        double result = compiledExpression();

        // Display the result.
        Console.WriteLine(result);

        // This code produces the following output:
        // 8
        // </ConvertToFund>
    }

    // <CreateBoundFunc>
    private static Func<int, int> CreateBoundFunc()
    {
        var constant = 5; // constant is captured by the expression tree
        Expression<Func<int, int>> expression = (b) => constant + b;
        var rVal = expression.Compile();
        return rVal;
    }
    // </CreateBoundFunc>

    // <CreateBoundResource>
    private static Func<int, int> CreateBoundResource()
    {
        using (var constant = new Resource()) // constant is captured by the expression tree
        {
            Expression<Func<int, int>> expression = (b) => constant.Argument + b;
            var rVal = expression.Compile();
            return rVal;
        }
    }
    // </CreateBoundResource>
}

// <ResourceClass>
public class Resource : IDisposable
{
    private bool _isDisposed = false;
    public int Argument
    {
        get
        {
            if (!_isDisposed)
                return 5;
            else throw new ObjectDisposedException("Resource");
        }
    }

    public void Dispose()
    {
        _isDisposed = true;
    }
}
// </ResourceClass>

Execution and lifetimes

You execute the code by invoking the delegate created when you called LambdaExpression.Compile(). The preceding code, add.Compile(), returns a delegate. You invoke that delegate by calling func(), which executes the code.

That delegate represents the code in the expression tree. You can retain the handle to that delegate and invoke it later. You don't need to compile the expression tree each time you want to execute the code it represents. (Remember that expression trees are immutable, and compiling the same expression tree later creates a delegate that executes the same code.)

Caveats

Compiling a lambda expression to a delegate and invoking that delegate is one of the simplest operations you can perform with an expression tree. However, even with this simple operation, there are caveats you must be aware of.

Lambda Expressions create closures over any local variables that are referenced in the expression. You must guarantee that any variables that would be part of the delegate are usable at the location where you call Compile, and when you execute the resulting delegate. The compiler ensures that variables are in scope. However, if your expression accesses a variable that implements IDisposable, it's possible that your code might dispose of the object while it's still held by the expression tree.

For example, this code works fine, because int doesn't implement IDisposable:

sample · csharpdocs/csharp/advanced-topics/expression-trees/snippets/RunExpressionTrees.csCreateBoundFunc

csharp
using System.Linq.Expressions;

public static class RunExpressionTrees
{
    public static void ConvertToDelegate()
    {
        // <ConvertToDelegate>
        Expression<Func<int>> add = () => 1 + 2;
        var func = add.Compile(); // Create Delegate
        var answer = func(); // Invoke Delegate
        Console.WriteLine(answer);
        // </ConvertToDelegate>
    }

    public static void CreateExpressionTree()
    {
        // <CreateExpressionTree>
        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.
        // </CreateExpressionTree>
    }

    public static void BuildExpressionTree()
    {
        // <ConvertToFund>
        // The expression tree to execute.
        BinaryExpression be = Expression.Power(Expression.Constant(2d), Expression.Constant(3d));

        // Create a lambda expression.
        Expression<Func<double>> le = Expression.Lambda<Func<double>>(be);

        // Compile the lambda expression.
        Func<double> compiledExpression = le.Compile();

        // Execute the lambda expression.
        double result = compiledExpression();

        // Display the result.
        Console.WriteLine(result);

        // This code produces the following output:
        // 8
        // </ConvertToFund>
    }

    // <CreateBoundFunc>
    private static Func<int, int> CreateBoundFunc()
    {
        var constant = 5; // constant is captured by the expression tree
        Expression<Func<int, int>> expression = (b) => constant + b;
        var rVal = expression.Compile();
        return rVal;
    }
    // </CreateBoundFunc>

    // <CreateBoundResource>
    private static Func<int, int> CreateBoundResource()
    {
        using (var constant = new Resource()) // constant is captured by the expression tree
        {
            Expression<Func<int, int>> expression = (b) => constant.Argument + b;
            var rVal = expression.Compile();
            return rVal;
        }
    }
    // </CreateBoundResource>
}

// <ResourceClass>
public class Resource : IDisposable
{
    private bool _isDisposed = false;
    public int Argument
    {
        get
        {
            if (!_isDisposed)
                return 5;
            else throw new ObjectDisposedException("Resource");
        }
    }

    public void Dispose()
    {
        _isDisposed = true;
    }
}
// </ResourceClass>

The delegate has captured a reference to the local variable constant. That variable is accessed at any time later, when the function returned by CreateBoundFunc executes.

However, consider the following (rather contrived) class that implements System.IDisposable:

sample · csharpdocs/csharp/advanced-topics/expression-trees/snippets/RunExpressionTrees.csResourceClass

csharp
using System.Linq.Expressions;

public static class RunExpressionTrees
{
    public static void ConvertToDelegate()
    {
        // <ConvertToDelegate>
        Expression<Func<int>> add = () => 1 + 2;
        var func = add.Compile(); // Create Delegate
        var answer = func(); // Invoke Delegate
        Console.WriteLine(answer);
        // </ConvertToDelegate>
    }

    public static void CreateExpressionTree()
    {
        // <CreateExpressionTree>
        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.
        // </CreateExpressionTree>
    }

    public static void BuildExpressionTree()
    {
        // <ConvertToFund>
        // The expression tree to execute.
        BinaryExpression be = Expression.Power(Expression.Constant(2d), Expression.Constant(3d));

        // Create a lambda expression.
        Expression<Func<double>> le = Expression.Lambda<Func<double>>(be);

        // Compile the lambda expression.
        Func<double> compiledExpression = le.Compile();

        // Execute the lambda expression.
        double result = compiledExpression();

        // Display the result.
        Console.WriteLine(result);

        // This code produces the following output:
        // 8
        // </ConvertToFund>
    }

    // <CreateBoundFunc>
    private static Func<int, int> CreateBoundFunc()
    {
        var constant = 5; // constant is captured by the expression tree
        Expression<Func<int, int>> expression = (b) => constant + b;
        var rVal = expression.Compile();
        return rVal;
    }
    // </CreateBoundFunc>

    // <CreateBoundResource>
    private static Func<int, int> CreateBoundResource()
    {
        using (var constant = new Resource()) // constant is captured by the expression tree
        {
            Expression<Func<int, int>> expression = (b) => constant.Argument + b;
            var rVal = expression.Compile();
            return rVal;
        }
    }
    // </CreateBoundResource>
}

// <ResourceClass>
public class Resource : IDisposable
{
    private bool _isDisposed = false;
    public int Argument
    {
        get
        {
            if (!_isDisposed)
                return 5;
            else throw new ObjectDisposedException("Resource");
        }
    }

    public void Dispose()
    {
        _isDisposed = true;
    }
}
// </ResourceClass>

If you use it in an expression as shown in the following code, you get a System.ObjectDisposedException when you execute the code referenced by the Resource.Argument property:

sample · csharpdocs/csharp/advanced-topics/expression-trees/snippets/RunExpressionTrees.csCreateBoundResource

csharp
using System.Linq.Expressions;

public static class RunExpressionTrees
{
    public static void ConvertToDelegate()
    {
        // <ConvertToDelegate>
        Expression<Func<int>> add = () => 1 + 2;
        var func = add.Compile(); // Create Delegate
        var answer = func(); // Invoke Delegate
        Console.WriteLine(answer);
        // </ConvertToDelegate>
    }

    public static void CreateExpressionTree()
    {
        // <CreateExpressionTree>
        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.
        // </CreateExpressionTree>
    }

    public static void BuildExpressionTree()
    {
        // <ConvertToFund>
        // The expression tree to execute.
        BinaryExpression be = Expression.Power(Expression.Constant(2d), Expression.Constant(3d));

        // Create a lambda expression.
        Expression<Func<double>> le = Expression.Lambda<Func<double>>(be);

        // Compile the lambda expression.
        Func<double> compiledExpression = le.Compile();

        // Execute the lambda expression.
        double result = compiledExpression();

        // Display the result.
        Console.WriteLine(result);

        // This code produces the following output:
        // 8
        // </ConvertToFund>
    }

    // <CreateBoundFunc>
    private static Func<int, int> CreateBoundFunc()
    {
        var constant = 5; // constant is captured by the expression tree
        Expression<Func<int, int>> expression = (b) => constant + b;
        var rVal = expression.Compile();
        return rVal;
    }
    // </CreateBoundFunc>

    // <CreateBoundResource>
    private static Func<int, int> CreateBoundResource()
    {
        using (var constant = new Resource()) // constant is captured by the expression tree
        {
            Expression<Func<int, int>> expression = (b) => constant.Argument + b;
            var rVal = expression.Compile();
            return rVal;
        }
    }
    // </CreateBoundResource>
}

// <ResourceClass>
public class Resource : IDisposable
{
    private bool _isDisposed = false;
    public int Argument
    {
        get
        {
            if (!_isDisposed)
                return 5;
            else throw new ObjectDisposedException("Resource");
        }
    }

    public void Dispose()
    {
        _isDisposed = true;
    }
}
// </ResourceClass>

The delegate returned from this method has closed over the constant object, which has been disposed of. (It's been disposed, because it was declared in a using statement.)

Now, when you execute the delegate returned from this method, you have an ObjectDisposedException thrown at the point of execution.

It does seem strange to have a runtime error representing a compile-time construct, but that's the world you enter when you work with expression trees.

There are numerous permutations of this problem, so it's hard to offer general guidance to avoid it. Be careful about accessing local variables when defining expressions, and be careful about accessing state in the current object (represented by this) when creating an expression tree returned via a public API.

The code in your expression may reference methods or properties in other assemblies. That assembly must be accessible when the expression is defined, when it's compiled, and when the resulting delegate is invoked. You're met with a ReferencedAssemblyNotFoundException in cases where it isn't present.

Summary

Expression Trees that represent lambda expressions can be compiled to create a delegate that you can execute. Expression trees provide one mechanism to execute the code represented by an expression tree.

The Expression Tree does represent the code that would execute for any given construct you create. As long as the environment where you compile and execute the code matches the environment where you create the expression, everything works as expected. When that doesn't happen, the errors are predictable, and they're caught in your first tests of any code using the expression trees.