๐ WAYPOINT LESSON
Anatomy of an expression tree
โญโญโญ advancedโณ 15 min read๐ Lesson 188 of 265
Nodes, visitors, reduction, and what a lambda expression actually becomes as data.
Anatomy of an expression tree
An expression tree is an immutable object graph describing code: every
node has a NodeType, a static Type, and children. x => x >= 5 && x < 100 becomes:
Lambda (Func<int, bool>)
โโโ AndAlso
โโโ GreaterThanOrEqual
โ โโโ Parameter "x"
โ โโโ Constant 5
โโโ LessThan
โโโ Parameter "x"
โโโ Constant 100
Three properties make trees the backbone of LINQ providers:
- Inspectable โ you can walk and read the logic (that is how EF turns your predicate into SQL).
- Rewritable โ
ExpressionVisitorproduces modified copies (that is how providers substitute constants, inline parameters, add tenant filters). - Compilable โ
Compile()emits a real delegate (that is how the rewritten tree becomes executable again).
The decisive C# rule: a lambda assigned to Expression<TDelegate> is
parsed into a tree by the COMPILER; the same lambda assigned to
Func<TDelegate>-shaped delegate types is compiled to IL directly. One
syntax, two worlds โ the target type decides which you get. Note the
boundary: only expressions fit; statements, async, and many operators
(??=, => bodies with blocks) are outside the tree subset.