Advanced LINQ & Deferred Execution
Prerequisites: Advanced generics & constraints
LINQ's GroupBy and aggregate operators cover the same ground as
Java's stream Collectors:
record Person(string Name, string City);
List<Person> people = new() {
new("Ada", "London"),
new("Grace", "New York"),
new("Al", "London"),
};
var byCity = people.GroupBy(p => p.City);
foreach (var group in byCity) {
Console.WriteLine($"{group.Key}: {group.Count()}");
}
string names = string.Join(", ", people.Select(p => p.Name));
Most LINQ operators are deferred — building byCity above
doesn't actually run the grouping until something enumerates it
(the foreach). Calling .ToList() forces immediate
execution, useful when a query's source data might change before
you're ready to use the results.
Common mistakes
- Building a LINQ query inside a loop that also modifies the underlying collection, then enumerating it afterward — deferred execution means the query sees the collection's state at enumeration time, not when it was written.