LINQ Lists - Anonymous Methods and Lambda Expressions

 

Year: 2005 A.D.
The C# 2.0 specification is released in the month of September. It talks about "new" features. We were introduced with a new "in-line" feature of using delegates. We called it "Anonymous Methods". Needless to say, its named as such because:
- Its Anonymous (no method name is given)
- Its InLine (How can you call something without a name, makes sense doesn't it?)

Year: 2006 A.D.
The C# 3.0 specification is released in the month of May. It talks about new features. Among a number of path breaking innovative ideas, we have something called "Lambda Expressions". It claims to provide more concise, functional syntax for writing anonymous methods.

Lets checkout the basic syntax of Anonymous Methods:

 delegate void D(int x); 
 D d1 = delegate { }; // Ok 
 D d2 = delegate() { }; // Error, signature mismatch 
 D d3 = delegate(long x) { }; // Error, signature mismatch 
 D d4 = delegate(int x) { }; // Ok 
 D d5 = delegate(int x) { return; }; // Ok 
 D d6 = delegate(int x) { return x; }; // Error, return type mismatch 
 delegate void E(out int x); 
 E e1 = delegate { }; // Error, E has an out parameter 
 E e2 = delegate(out int x) { x = 1; }; // Ok 
 E e3 = delegate(ref int x) { x = 1; }; // Error, signature mismatch 
 delegate int P(params int[] a);
 P p1 = delegate { }; // Error, end of block reachable 
 P p2 = delegate { return; }; // Error, return type mismatch 
 P p3 = delegate { return 1; }; // Ok 
 P p4 = delegate { return "Hello"; }; // Error, return type mismatch 
 P p5 = delegate(int[] a) { // Ok 
 return a[0]; }; 
 P p6 = delegate(params int[] a) { // Error, params modifier 
 return a[0]; }; 
 P p7 = delegate(int[] a) { // Error, return type mismatch 
 if (a.Length > 0) 
 return a[0]; 
 return "Hello"; 
 }; 
 delegate object Q(params int[] a); 
 Q q1 = delegate(int[] a) { // Ok 
 if (a.Length > 0) 
 return a[0]; 
 return "Hello"; 
 };

The best example of an anonymous method is when a delegate is used as an Event Handler:

Without Anonymous:

 MyButton.Click += new EventHandler(MyButtonClicked);
 void MyButtonClicked(object sender, EventArgs e)
 {
 MessageBox.Show("Hello World!");
 }

With Anonymous:

 MyButton.Click += delegate{
 MessageBox.Show("Hello World!");
 }

From the above comparison, you can make out that using InLine Functions, we do not need to:
- pass arguments across functions.
- you can use the scope level variables easily.
But, it has tradeoffs which involve code readability and reusability hassles. As the age old saying goes about InLine Functions: Use it efficiently, as its faster than calling functions but slightly difficult to manage.

Lambda Expressions

It is written as a parameter list, followed by the => (slanted lambda?) token, followed by an expression or a statement block.

 class Program
 {
     static void Main(string[] args)
     {
         List<Vehicle> vlist = new List<Vehicle>
                               {
                                   new Vehicle{Make="Mercedes", Model="Benz", Mileage=12},
                                   new Vehicle{Make="Renault", Model="Logan", Mileage=15},
                                   new Vehicle{Make="Honda", Model="Accord", Mileage=12},
                               };
         IEnumerable<Vehicle> vehicles = vlist.Where(v => v.Mileage > 10);
         foreach (Vehicle v in vehicles)
         {
             Console.WriteLine(v.Make);
             Console.WriteLine(v.Model);
             Console.WriteLine(v.Mileage);
             Console.WriteLine("-----------------");
         }
         Console.Read();
     }
 }
  
 public class Vehicle
 {
     public string Make;
     public string Model;
     public int Mileage;
 }

In the above example:
IEnumerable<Vehicle> vehicles = vlist.Where(v => v.Mileage > 10);

The Lambda Expression:
v => v.Mileage > 10

replaces:
new delegate(Vehicle v){
v.Mileage > 10;
}

It can also be replaced by:

 IEnumerable<Vehicle> vehicles = from v in vlist
                                             where v.Mileage > 12
                                             select v;

Try this: The Evolution Of LINQ And Its Impact On The Design Of C#

These samples were created using: Microsoft Visual C# Codename "Orcas" Express Edition