Friday, January 25, 2013

Lambda Expression, Statement Lambda, Action Delegate, Func Delegate, Differences Between Action and Func and Instantiating Delegates with Lambda

Continuing from last page:
Lambda expressions or statement lamda can be passed where a delegate is expected.

Lamda expressions may or may not expect input parameters and have an expression to right of lambda that may evaluate to a return value.

      Func<int, int, int, int, int> hello = (a, b, c, d) => a + b + c + d;

   here a,b,c,d are input parameters and return type is int which is result of e
xpression (a+b+c+d). 

In above lambda expression is assigned to Func delegate which accepts 4 input parameters of type 'int' and return type is 'int' again.


We have to make sure, lambda expressions input is convertible to delegate's input type & return of lambda is convertible to delegate's return type.



In above case (a+b+c+d) will be of type of int which is same of Func<int,int,int,int,int TResult> delegate's return type i.e. int.



Lambda expression can also contain statements to right of lamda that might not return any value.


           Action<int> mm = (a) => Console.WriteLine("EEE");
      mm(5);

In above example right side of expression does not evaluate to anything though it accepts a parameter 'a'. This is assigned to default Action<int> delegate which does not expect any return type, but has an input parameter of type 'int'.


Now let us see what is a statement lambda. Statement lambda is similar to lambda expression but statement(s)/expression to the right of lambda is enclosed in {} braces.
They can contain multiple statement since they are enclosed in braces. Braces also indicate scope /block of lambda statement. 


                Action<int> actw = (a) => 
            {
                string s = "square = " + a * a;
                s = s + " - new";
                Console.WriteLine(s); 
            }

Here we are assigning statement lambda to a delegate that has single input parameter of type int. We are not returning anything from lambda but redirecting the square of number to console.


We use lambda and anonymous methods only in simple scenarios where a set of simple statements can be passed in method, instead of having dedicated method of handling or instantiating delegate.
In below example, I'm invoking a delegate and assigning a statement lambda for callback. Here having a callback method that would just print completion status would not make much sense and hence I replaced it with a lambda expression which outputs the delegate's method execution status in the callback.
Here AsyncCallback expects a method that accepts IAsyncResult parameter and return type is void. Our statement lambda accepts this IAsyncResult  as input and returns nothing and hence can be passed in as method that is expected by AsyncCallback.


        public static void ExecuteDelegate(Func<int, int, int, int, int> hello)
        {
                hello.BeginInvoke(2, 3, 4, 5,                
                   new AsyncCallback((asyncresult) => {  
                          Console.WriteLine("Completed = " +  
                                    asyncresult.IsCompleted); }),                
                                  null);
        }


Till now I have only use Func<> and Action<> delegates but lambda can be used for any delegate of matching return and input types. Func and Action are the delegates provided by default by the framework to avoid overhead of writing our own delegates for general cases. These delegates are generic they are extended to accept 0, 1, 2, 3 or more parameters. Number of input parameters that are accepted by both delegates was 0 to 4 in .NET 3.5.


Main difference between Action delegate and Func delegate is,


Action - delegate that does not have return value and accepts up-to four input parameters. (.NET 3.5)
Action also can encapsulate a method that take no input and no return value. 

Types:
Action
Action<in T1> - in represents input parameter.
Action<in T1,in T2>
Action<in T1,in T2,in T3>
Action<in T1,in T2,in T3,in T4>

Func<TResult> - Func delegate is used when we have a return value but input parameter list is optional. Func delegate can encapsulate method that returns a value and accepts no input. Func can encapsulate methods that have 0 - 4 in put parameters and return a value. Last value in parameter list represents the return type.

Func<TResult> - TResult represrents return type.
Func<in T1, out TResult> 
...............


delegate void PrintCharsDelegate(string s);


PrintCharsDelegate del = (s) =>
                   {
                       Console.WriteLine("Encryted String for {0} = ", s);
                              foreach (char ch in s)
                              {                                                   
                                                   Console.Write((char)((int)ch+1));
                              }
                   };
del("Hello");



Here statement lambda which encrypts the given string, is assigned to delegate which accepts string and returns nothing.

Anonymous methods are very similar to statement lambdas. They can be used to instantiate delegates just like statement lambda. We will see them in another article




No comments:

Post a Comment