C sharp - Expression Trees in C#

Expression Trees allow you to represent code as data.
Instead of executing a method immediately, you can store its structure in a tree format and inspect, modify, or execute it later.

They are mainly used in:

  • LINQ providers (like Entity Framework)

  • Dynamic query generation

  • Rule engines

  • Compilers and code analyzers


1. Normal Code vs Expression Tree

Normal Lambda (Compiled and Executed)

Func<int, int> square = x => x * x;
Console.WriteLine(square(5));  // 25

Here:

  • Code is compiled into IL

  • It executes directly


Expression Tree Version

using System.Linq.Expressions;

Expression<Func<int, int>> squareExpr = x => x * x;

Here:

  • The lambda is not executed

  • It is converted into a tree structure


2. What Does the Tree Look Like?

For:

x => x * x

The structure is:

Lambda
 └── Multiply
     ├── Parameter (x)
     └── Parameter (x)

Each part is represented by an object:

  • ParameterExpression

  • BinaryExpression

  • LambdaExpression


3. Compiling an Expression Tree

To execute it:

var compiled = squareExpr.Compile();
Console.WriteLine(compiled(5));  // 25

Important:

  • Expression Tree → needs .Compile() to execute

  • Normal Func → executes directly


4. Why Expression Trees Are Important

They allow inspection of code logic.

Example:
Entity Framework uses them to translate C# code into SQL.

var result = db.Users.Where(u => u.Age > 18);

The lambda u => u.Age > 18 becomes an Expression Tree.

EF reads it and converts it into:

SELECT * FROM Users WHERE Age > 18

Without expression trees, this translation is impossible.


5. Building Expression Trees Manually

You can construct them programmatically.

ParameterExpression param = Expression.Parameter(typeof(int), "x");

BinaryExpression body = Expression.Multiply(param, param);

Expression<Func<int, int>> lambda =
    Expression.Lambda<Func<int, int>>(body, param);

var compiled = lambda.Compile();
Console.WriteLine(compiled(4));  // 16

This is how dynamic query engines work internally.


6. Common Expression Types

Type Purpose
ParameterExpression Represents variable
ConstantExpression Represents constant value
BinaryExpression +, -, *, /
MethodCallExpression Calling methods
LambdaExpression Full lambda structure

7. Expression Trees vs Delegates

Delegate (Func) Expression Tree
Executes directly Stores structure
Cannot inspect logic Can inspect and modify
Faster Slightly slower
Used for runtime execution Used for dynamic analysis

8. Limitations

Expression Trees:

  • Cannot represent all C# syntax

  • No loops like for, while

  • Limited statement support

  • Designed mainly for expressions, not full methods


9. Real-World Uses

  1. Entity Framework

  2. LINQ Providers

  3. Dynamic filtering systems

  4. Code generation tools

  5. Rule engines

  6. ORMs


10. Advanced Concept: Expression Visitors

C# provides ExpressionVisitor class.

It allows:

  • Traversing

  • Modifying

  • Rewriting expression trees

Example use case:
Automatically modify all x > 18 to x > 21.

This is powerful for:

  • Security filters

  • Multi-tenant applications

  • Query rewriting