पाठ 14 / 25

LINQ

Query in-memory data with LINQ and understand deferred execution.

Queries as composable methods

LINQ (Language Integrated Query) adds query operators to any IEnumerable<T>: Where (filter), Select (project), OrderBy/ThenBy, GroupBy, Join, Any/All, Count, Sum, First/FirstOrDefault, Distinct, Take/Skip, Chunk and many more. You can write the same query in method syntax (orders.Where(o => o.Total > 500)) or query syntax (from o in orders where o.Total > 500 select o). Most operators use deferred execution: building the query does nothing; it runs when you enumerate it (with foreach, ToList(), Count() and so on), and it runs again each time you enumerate. Call ToList() or ToArray() when you want a snapshot. LINQ to Objects works on in-memory data with delegates; IQueryable<T> providers, such as Entity Framework Core, translate the same operators into SQL.

Grouping and summarising orders

Nothing executes until ToList() is called.

var orders = new List<Order>
{
    new("o1", "Pune", 1200m), new("o2", "Delhi", 300m),
    new("o3", "Pune", 800m),  new("o4", "Delhi", 2500m),
};

var byCity = orders
    .Where(o => o.Total >= 500m)
    .GroupBy(o => o.City)
    .Select(g => new { City = g.Key, Count = g.Count(), Revenue = g.Sum(o => o.Total) })
    .OrderByDescending(x => x.Revenue)
    .ToList();                      // executes here

foreach (var row in byCity)
    Console.WriteLine($"{row.City}: {row.Count} orders, {row.Revenue:C}");

bool anyBig = orders.Any(o => o.Total > 2000m);

record Order(string Id, string City, decimal Total);

First versus FirstOrDefault versus Single

First throws if nothing matches; FirstOrDefault returns null/default; Single throws if there is not exactly one match. Choose deliberately: Single documents that duplicates would be a bug.

त्वरित जाँच: When does a LINQ query like `orders.Where(o => o.Total > 500)` actually run?

  • When the line is executed
  • At compile time
  • Only when the garbage collector runs
  • When it is enumerated, for example by foreach or ToList()
Answer

When it is enumerated, for example by foreach or ToList() — Most LINQ operators are deferred and execute on enumeration.