What is a lambda expression, and what is a closure?

C# Delegates & Events Basic Fresher1–2 Yrs2–3 Yrs Conceptual 2 min read

Quick Answer

A lambda is an inline anonymous function: x => x * 2. It becomes a delegate (Func/Action) or, for LINQ providers, an Expression<T>. A closure is created when a lambda uses a variable from the enclosing scope — the compiler “captures” that variable so it stays alive as long as the lambda does.

A lambda is just an inline anonymous function — x => x * 2 — that the compiler turns into a delegate, or an expression tree for something like EF. A closure happens when that lambda references a variable from outside itself; the compiler captures that variable so it lives as long as the lambda does. The important detail is that capture is by reference, so if the outer variable changes later, the lambda sees the new value. That's the source of the old for-loop bug where every lambda ends up seeing the last value — you fix it by copying the loop variable into a local inside the loop.

  • Expression lambda: x => x + 1. Statement lambda: x => { Log(x); return x + 1; }.
  • Captured variables are captured by reference, not by value — the closure sees later changes.
  • The classic loop bug (pre-C# 5 for foreach, still possible with for): capturing the loop variable in every iteration's lambda so they all share one variable and see the final value. Fix with a local copy inside the loop.
  • Closures allocate a small compiler-generated class on the heap; a lambda that captures nothing is cached as a static delegate.

C# — closure capture
int factor = 2;
Func<int, int> scale = n => n * factor;   // captures 'factor'
factor = 10;
Console.WriteLine(scale(5));               // 50, not 10 — sees the new value

var actions = new List<Action>();
for (int i = 0; i < 3; i++)
{
    int copy = i;                          // capture a fresh local
    actions.Add(() => Console.Write(copy)); // prints 0 1 2
}