// Exercise 2: equality, hashing, strings and time (medium) // // STEP 1: Make Sku (a class) usable as a dictionary key and in HashSet: two Skus are equal if their Code is // equal IGNORING case. Override Equals and GetHashCode consistently (use // StringComparer.OrdinalIgnoreCase.GetHashCode(Code)). // STEP 2: SameEmail(a, b): compare emails ignoring case with an explicit ordinal comparison. // STEP 3: ToUtcIso(DateTimeOffset local): return the instant in UTC formatted as "yyyy-MM-ddTHH:mm:ssZ". // STEP 4: CountDistinctQueries(): `query` is a deferred LINQ query with a side effect counter; enumerate it // ONCE (materialize with ToList()) and return (count, sum) so the source is evaluated only once. // // Run with: dotnet run (inside a console project). using System; using System.Collections.Generic; using System.Linq; class Sku { public string Code { get; } public Sku(string code) { Code = code; } // TODO: Equals / GetHashCode } class Program { static int Evaluations; static bool SameEmail(string a, string b) => a == b; // TODO static string ToUtcIso(DateTimeOffset local) => local.ToString("yyyy-MM-ddTHH:mm:ss") + "Z"; // TODO static (int count, int sum) CountAndSum() { IEnumerable query = Enumerable.Range(1, 5).Select(x => { Evaluations++; return x * 10; }); return (query.Count(), query.Sum()); // TODO: evaluate once } static void Main() { int pass = 0, total = 0; void Check(string name, bool ok) { total++; if (ok) pass++; Console.WriteLine($"{(ok ? "PASS" : "FAIL")}: {name}"); } var set = new HashSet { new Sku("ABC-1"), new Sku("abc-1"), new Sku("XYZ") }; Check("HashSet dedupes case-insensitively", set.Count == 2); var stock = new Dictionary { [new Sku("Bowl")] = 3 }; Check("dictionary lookup with an equal key", stock.TryGetValue(new Sku("BOWL"), out var n) && n == 3); Check("emails ignore case", SameEmail("Ana@Example.com", "ana@example.COM") && !SameEmail("a@x.com", "b@x.com")); var tashkent = new DateTimeOffset(2026, 10, 21, 15, 30, 0, TimeSpan.FromHours(5)); Check("UTC conversion", ToUtcIso(tashkent) == "2026-10-21T10:30:00Z"); var (count, sum) = CountAndSum(); Check($"query evaluated once (evaluations {Evaluations})", count == 5 && sum == 150 && Evaluations == 5); Console.WriteLine($"--- {pass}/{total} checks passed ---"); } }