Chapter 4. Supporting LINQ in C# 3.0Generics, delegates, and anonymous methods in C# 2.0 provide insight into how LINQ is supported in C# 3.0. Let's consider once again the problem of finding all doctors living within the Chicago city limits. As shown earlier, here's the obvious approach using foreach: List<Doctor> inchicago = new List<Doctor>(); foreach (Doctor d in doctors) if (d.City == "Chicago") inchicago.Add(d); A more elegant approach currently available in C# 2.0 is to take advantage of the collection's FindAll method, which can be passed a delegate to a function that determines whether the doctor resides in Chicago: public delegate bool Predicate<T>(T obj); // pre-defined in .NET 2.0 public bool IsInChicago(Doctor obj) // notice how this matches delegate signature { return obj.City == "Chicago"; } . . . List<Doctor> inchicago = doctors.FindAll(new Predicate<Doctor>(this.IsInChicago)); FindAll iterates through the collection, building a new collection containing those objects for which the delegate-invoked function returns true. A more succinct version passes an anonymous method to FindAll: List<Doctor> inchicago = doctors.FindAll(delegate(Doctor d) { return d.City == "Chicago"; } ); The {} denote the body of the anonymous method; notice these fall within the scope of the () in the call to FindAll. The signature of the anonymous methodin this case a Boolean function with a single Doctor argumentis type-checked by the compiler to ensure that it matches the definition of the argument to FindAll. The compiler then translates this version into an explicit delegate-based version, assigning a unique name to the underlying method: private static bool b__0(Doctor d) { return d.City == "Chicago"; } List<Doctor> inchicago = doctors.FindAll( new Predicate<Doctor>(b__0) ); While this has nothing to do with LINQ per se, this approach of translating from one abstraction to another exemplifies how LINQ integrates into C# 3.0. |