Convert Lambda Expression to Expression Tree in C

In C#, converting a lambda expression into an expression tree allows you to treat code as data rather than executable instructions. This article explains how the C# compiler handles this conversion automatically through the System.Linq.Expressions namespace, illustrates the syntax difference between standard delegates and expression trees, and details how to inspect or compile the resulting tree at runtime.

Implicit Conversion via Type Declaration

The primary way to convert a lambda expression into an expression tree is by assigning the lambda directly to a variable of type Expression<TDelegate>. When the C# compiler encounters an assignment to Expression<TDelegate>, it does not emit IL bytecode for a delegate; instead, it generates the metadata and abstract syntax tree (AST) that represent the lambda.

using System;
using System.Linq.Expressions;

// 1. Compiled Delegate: Represents executable code
Func<int, bool> isEvenDelegate = num => num % 2 == 0;

// 2. Expression Tree: Represents the code structure as data
Expression<Func<int, bool>> isEvenExpression = num => num % 2 == 0;

Explicit Casting

If you are passing a lambda to a method that accepts an object or an untyped parameter, or if you are using the var keyword, you must explicitly cast the lambda to the target Expression<TDelegate> type.

var expression = (Expression<Func<int, int, int>>)((a, b) => a + b);

Inspecting the Expression Tree

Once the lambda is converted into an expression tree, you can traverse its components, such as its parameters, body, and operation types:

Expression<Func<int, bool>> expr = x => x > 5;

// Access parameters
ParameterExpression parameter = expr.Parameters[0]; // 'x'

// Access the body
BinaryExpression body = (BinaryExpression)expr.Body; // 'x > 5'
Expression left = body.Left;                         // 'x'
Expression right = body.Right;                       // '5'
ExpressionType nodeType = body.NodeType;             // GreaterThan

Compiling and Executing at Runtime

An expression tree can be converted back into executable code at any time using the Compile method, which produces an executable delegate:

Expression<Func<int, int, int>> addExpr = (x, y) => x + y;

// Compile the tree to an executable delegate
Func<int, int, int> addFunc = addExpr.Compile();

// Execute the delegate
int result = addFunc(3, 4); // Returns 7

Limitations

The C# compiler can only convert expression lambdas (lambdas with a single expression as the body) into expression trees. Statement lambdas enclosed in curly braces containing blocks, loops, or multiple statements cannot be automatically converted:

// Valid: Expression lambda
Expression<Action<int>> valid = x => Console.WriteLine(x);

// Compiler Error: Statement lambdas cannot be converted to expression trees
// Expression<Action<int>> invalid = x => { Console.WriteLine(x); };