Phase 10 of 30 · Topic 10.3

Expression Trees (`Expression<Func<T>>`) vs Compiled Delegates

1Concept

While `Func<T>` compiles to executable IL, `Expression<Func<T>>` compiles to an Abstract Syntax Tree (AST) data structure that ORMs (EF Core) can parse and translate into raw SQL.

2Architecture Diagram

Expression<Func<User, bool>> expr = u => u.Age > 18;
       │
   [ BinaryExpression (GreaterThan) ]
   ├── Left:  [ MemberExpression (u.Age) ]
   └── Right: [ ConstantExpression (18) ]
       │
       ▼
   Parsed by EF Core Provider ──> Emits: "SELECT * FROM Users WHERE Age > 18" 

3Code Example

C# 13 & .NET 9
using System;
using System.Linq.Expressions;

public class ExpressionTreeDemo
{
    public static void Main()
    {
        // Expression Tree (Data representation of code)
        Expression<Func<int, bool>> isAdultExpr = age => age >= 18;

        Console.WriteLine($"Node Type: {isAdultExpr.NodeType}");
        Console.WriteLine($"Body: {isAdultExpr.Body}");
        Console.WriteLine($"Parameters: {isAdultExpr.Parameters[0].Name}");

        // Compile to runnable delegate at runtime
        Func<int, bool> compiled = isAdultExpr.Compile();
        Console.WriteLine($"Execution Result for Age 21: {compiled(21)}");
    }
}

4Expected Output

Node Type: Lambda
Body: (age >= 18)
Parameters: age
Execution Result for Age 21: True

5Key Takeaways

  • Expression trees represent code as data inspectable at runtime.
  • `IQueryable<T>` operates on `Expression<Func<T>>` for server-side SQL translation.
  • Calling `.Compile()` at runtime is expensive; cache compiled delegates.