Monday, June 7, 2010

Transformation of delegates to Lambda

                 Lambda expressions are equivalent to delegates that we are using. To see how lambda expressions evolved, we have to start from basics –

C# 1.1 creating delegates

  1:   1: namespace Generics
  2:   2: {
  3:   3: 
  4:   4:     //Declare delegate
  5:   5:     public delegate void Message(string message); 
  6:   6: 
  7:   7:     class Lambda
  8:   8:     {
  9:   9:         public Message myMessage { get; set; }
 10:  10:         public Lambda()
 11:  11:         {
 12:  12:             //Define delegate
 13:  13:             myMessage = new Message(MessageLogic);
 14:  14:             //Invoke delegate
 15:  15:             myMessage("Hello");
 16:  16:         }
 17:  17: 
 18:  18:         public void MessageLogic(string message)
 19:  19:         {
 20:  20:             Console.WriteLine(message);
 21:  21:         }
 22:  22:     }
 23:  23: 
 24:  24: }
 25:  25: 
 26:  26: 

When we declare –

    public delegate void Message(string message);  

Compiler is declaring (generating) a type ‘Message’ which inherits from class ‘Delegate’. In this class an invoke method will be defined with the signature we are providing in the declaration line (In our case it is a void method that accepts a string).

Our focus is on line –

myMessage = new Message(MessageLogic);

This definition actually instantiates the class declared by compiler and passes the address of method, that suits the delegate signature, to the constructor

C# 2.0 delegates inference  

We can declare delegate as -

Message myMessage = new Message(MessageLogic);

But from the variable’s ‘myMessage’ type (here it is Message), compiler can infer the type of delegate to be passed. So we can avoid specifying it explicitly –

Message myMessage = MessageLogic;

 

C# 2.0 anonymous methods

In above example –

  1: Message myMessage = MessageLogic; 
  2: public void MessageLogic(string message) 
  3: { 
  4:    Console.WriteLine(message); 
  5: } 
  6: 
  7: 
  8: 

 

When we use anonymous method, we are defining the method on the fly-

Message myMessage = delegate(string message) { Console.WriteLine(message); };

Using this statement, compiler generates a method with the definition provided and create a delegate for it and assigns it to the variable ‘myMessage’ used.

 

C# 3.5 lambda expressions

 In anonymous method –

Message myMessage = delegate(string message) { Console.WriteLine(message); };

When we use lambda expression we don’t have to use keyword ‘delegate’ and compiler knows it is going to be a delegate

Message myMessage = (string message) => { Console.WriteLine(message); };

‘=>’ is pronounced as ‘goes to’

C# 3.5 lambda expression type inference    

Message myMessage = (string message) => { Console.WriteLine(message); };

From the variable type (Message), compiler knows what parameter types are going into the method. So we don’t have to specify the type separately

Message myMessage = (message) => { Console.WriteLine(message); };

 

C# 3.5 lambda expression enhancements

 Message myMessage = (message) => { Console.WriteLine(message); };

If there is only one argument for the method, then we can remove braces –

Message myMessage = message => { Console.WriteLine(message); };

Consider the case as follows –

  1: public delegate int Message(string message); 
  2: Message myMessage = delegate(string message) { return message.Length; }; 
  3: 
  4: 
  5: 

In this expression there is only one statement in function definition and that is a return statement. So we don’t have to use curly braces and ‘return’ keyword

Message myMessage = message => message.Length;

 

Example:

 List<string> list = new List<string> { "Hello", "World" };

From this list I need to filter items contains ‘r’

 Where

You can see that ‘Where’ is accepting a delegate of type ‘Func<string,bool>’.

Func and Action are two delegate types provided by framework. Former can be used for functions (return is there) and latter for methods (void type)

 

So Func<string,bool> means it is a delegate that accepts string parameter and returns a bool value.

IEnumerable<string> selectedList = list.Where(i => i.Contains("r"));

We passed delegate as ‘i => i.Contains("r")’, this means inside the ‘Where’ method, it takes each item in the collection ‘list’ and apply our delegate. From our anonymous method we are returning true only for items that contains ’r’. If function returns true, that item will be added to the output collection ‘selectedList’.

In effect we get a collection with one item ‘World’

So what ever we were doing in the past is actually happening now also. The only difference is compiler exposes some easy ways for us to do things and the head ache of converting it to actual definitions is taken by more intelligent compiler.

We can look forward for more intelligent compiler that reduces developers work.

 

 

 

 

 

 

 

 

 

1 comment: