New Constructs
C# 3.0 supports the capability of handling events inline by assigning or delegating a chunk of code directly where an event handler will be referenced, instead of creating a dedicated method to respond to an event. This approach takes advantage of anonymous methods. The syntax can be a little “too busy” or confusing. The syntax can be cleaned up using lambda expressions, which are cleaner, more simply ways of creating anonymous methods.
The MSDN Library defines a lambda expression as “… an anonymous function that can contain expressions and statements, and can be used to create delegates or expression tree types.” The syntax can be broken down as: arguments to be processed => (goes to) statements to be processed. In the example above, the OrderBy method is passed a student instance (to be evaluated once it is referenced via the foreach loop) which is the object to be processed, then the “goes to” operator (=>)and student.Major, ( the value of the student’s major), which is the statement that is to be processed. The OrderBy method actually considers it like an identity function according to the MSDN Library.
To illustrate lambda expression or more so, the statements to be processed consider the following example.
//First define the major we are looking for
Program._majorToFind = "Physics";
//Now we can loop thru the collection that is returned from casting to a List<Student> collection and using the FindAll method, using the Lambda operator
foreach (var student in _students.ToList<Student>().FindAll
(student => student.Major == Program._majorToFind))
{
Console.WriteLine("{0,-10} \t{1,-10} \t{2,-10} \t{3,-10:d} \t{4,-10:D} ", student.FirstName,
student.LastName, student.Major, student.EnrollmentDate, student.GraduationDate);
}
//Now we utilize the Find method, to find a specific instance with specific data, using the Lambda operator
Program._lastNameToFind = "Valenti";
Student students = _students.ToList<Student>().Find(student => student.LastName == Program._lastNameToFind);
Notice the foreach, the type that is being retrieved is defined as a var which is an anonymous type that is ultimately returned from the Find and FindAll methods of List<T>. Those methods expect to receive a System.Predicate<T>, which is ultimately a delegate or method pointer. As illustrated above, a method pointer can be replaced by an anonymous method which also can be replaced by a lambda expression. The statements to be processed in the lambda expression are looking for student instances with a student Major property value of “Physics” and only return instances with those values.
The same is true for the Find method of List<T>. It requires a method pointer which can be replaced with a lambda expression that returns the student object with the LastName property equal to Program._lastNameToFind.
Your strongly typed collection code can be further reduced than that illustrated in Part 1, by utilizing new constructs added to the c# language. These new objects and constructs actually make it more readable and understandable once you understand how they are read. All the compiler time type checking is maintained and the compiler infers the correct type for the anonymous types used in the lambda expressions.
In Part 3, the lambda expression will be replaced with Language Integrated Queries (Linq).