Delegates and lambdas
A delegate is a type whose values are methods. Func<int, bool> is a ready-made delegate type in .NET: it fits any method that takes an int and returns a bool. Line 2 declares isBig with that type.
x => x > limit is a lambda expression: a method written in place, with no name. Left of => is the parameter, x; right is the body, whose value is returned. The compiler infers x is an int from Func<int, bool>.
Objects on the heap
When line 2 runs, a new delegate object is made on the heap; delegates are reference types. It remembers which method to call: the lambda's. isBig now holds a reference to that object, not the code itself.
The lambda uses limit, a local variable from outside it, so limit is captured. The compiler keeps limit in a hidden closure object, and the delegate's Target points to it. Line 1 already stored 5 there.
Line 3 makes an array of four ints, 3, 8, 1, 9, with a collection expression (square brackets, new in C# 12). An array is an object too, so it lives on the heap. The question for each element: is it bigger than limit?
Calling it
Line 4 passes isBig to LINQ's Count method, like any other argument. Count's parameter has type Func<int, bool>, so isBig fits. Passing a delegate passes behaviour: Count decides when to call it.
Count calls isBig once for each element; each call runs the lambda with limit read from the closure. 3: false, 8: true, 1: false, 9: true. Two trues, so Count returns 2.
Line 5, Console.WriteLine(n), prints 2: two of the four numbers are bigger than 5. So far isBig works like an ordinary method that Count was given.
Captured variables
Line 6 sets limit to 2. That writes the very variable the lambda captured, in the closure. C# captures the variable itself, not a copy of its value, so isBig will now compare with 2.
Line 7 counts again with the same isBig. Each call reads limit when it runs, now 2: 3: true, 8: true, 1: false, 9: true. Count returns 3 and the console shows 3.
Action<T> is the delegate type for methods that return nothing. A lambda can have a block body in braces. A named method fits too: nums.Count(IsEven). One delegate can hold several methods with +=, which is how events work.
What happens
// step 1/11 · delegate Func<int, bool> a delegate type: int in, bool out Func<T, TResult> built into .NET (namespace System) fits: bool IsEven(int x), bool IsBig(int x), ... Func<int, bool> isBig = x => x > limit; isBig can hold (a reference to) any method of that shape
The closure object is how the C# compiler implements captured variables today: it generates a hidden class with limit as a field, and line 1 writes that field. Its name and shape are compiler details; the language only promises that the lambda and main share one variable. Delegate.Target and Delegate.Method are real properties. For this capturing lambda, Target is the closure object; for a lambda that captures nothing, the compiler may reuse one cached delegate object instead of making a new one.