LINQ and lambdas
LINQ (Language-Integrated Query) is a set of methods, such as Where and Select, that query any sequence: an array, a List<T>, anything that is an IEnumerable<T>. You chain them into a pipeline: a source, some operators, then a loop that uses the results.
Line 1 makes scores, an int[] holding 72, 45, 90, 61. Every array implements IEnumerable<int>: it can hand out its items one at a time, in order. That is all LINQ needs from a source.
s => s >= 60 is a lambda: a tiny unnamed function. Given a score s, it returns true when s is at least 60. Where takes it as a Func<int, bool>, calls it once per item and keeps the items that get true.
Deferred execution
Lines 2 to 4 run no lambda at all. Where and Select only wrap each other and return a query object, so passed is a recipe, not a list: no score has been read yet. This is called deferred execution.
Pulling items through
Line 5 starts the work. foreach asks passed for an item; Select asks Where; Where asks the array, which hands over 72. 72 >= 60 is true, Select makes 72 + 5 = 77, and line 6 prints 77.
Next pull: 45 >= 60 is false, so Where drops it and at once asks the array again. 90 passes, Select makes 95, and line 6 prints it. Items move one at a time; nothing is stored between them.
61 passes and prints as 66. foreach asks once more, but the array has no items left, so the query reports the end and the loop stops. Each score went through the chain exactly once.
Line 7 enumerates passed a second time: every score is read and tested again. ToList stores the results, 77, 95, 66, in a new List<int>. Call ToList when you want the results kept instead of recomputed.
Another way to write it
C# can also write the query with keywords: from s in scores where s >= 60 select s + 5. The compiler turns it into the same Where and Select calls, so it runs exactly the same way.
What happens
// step 1/9 · linq LINQ Language-Integrated Query: methods in System.Linq works on any IEnumerable<T>: arrays, List<T>, ... a query source → operators (Where, Select, ...) → a loop each operator takes a lambda that says what to do with one item
The figure shows Where and Select as two machines. For an array, the .NET library may merge Where followed by Select into one iterator object as an optimisation; your lambdas are still called in the same order, one item at a time. Where and Select are deferred and streaming: they read one item, act on it, and hand it on. A few operators, such as OrderBy, must read the whole source before they can hand out the first item. ToList, ToArray, Count and First run the query at once.