// Exercise 3: deferred execution + Join (hardest) // // Part A: implement BuildDeferredQuery to return an UN-MATERIALIZED // `IEnumerable` (a Where clause only — do NOT call ToList/ToArray) // that filters `source` to values greater than `threshold`. Because it's // deferred, mutating `source` AFTER calling this method but BEFORE // enumerating the returned query must still be visible when it's enumerated // (see theory section 5). // // Part B: implement JoinOrdersWithCustomers using LINQ's Join to combine // orders with their customer's name, producing strings like // "Alice bought Book". // // Run with: dotnet run (inside a console project) or paste into a Main method. using System; using System.Collections.Generic; using System.Linq; class Program { #pragma warning disable IDE0060 static IEnumerable BuildDeferredQuery(List source, int threshold) { // TODO: return source.Where(n => n > threshold) directly — do NOT // materialize with ToList()/ToArray() here, or the deferred-mutation // check below will fail. return Enumerable.Empty(); } static List JoinOrdersWithCustomers( List<(int CustomerId, string Item)> orders, List<(int Id, string Name)> customers) { // TODO: use orders.Join(customers, o => o.CustomerId, c => c.Id, // (o, c) => $"{c.Name} bought {o.Item}") and materialize to a List. return new List(); } #pragma warning restore IDE0060 static void Main() { int pass = 0, total = 0; // Part A: deferred execution var numbers = new List { 1, 5, 10 }; var query = BuildDeferredQuery(numbers, 3); numbers.Add(20); // mutate AFTER building the query, BEFORE enumerating var materialized = query.ToList(); total++; var expectedDeferred = new List { 5, 10, 20 }; if (materialized.SequenceEqual(expectedDeferred)) { Console.WriteLine("PASS: deferred query sees the post-build mutation"); pass++; } else Console.WriteLine("FAIL: deferred query sees the post-build mutation, got [" + string.Join(", ", materialized) + "]"); // Part B: join var orders = new List<(int CustomerId, string Item)> { (1, "Book"), (2, "Pen"), (1, "Laptop") }; var customers = new List<(int Id, string Name)> { (1, "Alice"), (2, "Bob") }; var joined = JoinOrdersWithCustomers(orders, customers); total++; var expectedJoined = new List { "Alice bought Book", "Bob bought Pen", "Alice bought Laptop" }; if (joined.SequenceEqual(expectedJoined)) { Console.WriteLine("PASS: orders joined with customer names"); pass++; } else Console.WriteLine("FAIL: orders joined with customer names, got [" + string.Join(", ", joined) + "]"); Console.WriteLine($"--- {pass}/{total} checks passed ---"); } }