Delegates, Anonymous Methods, Lambda Expressions and Advantage, Built-in Delegates (Func, Action, Predicate), Examples

The world have started moving from object oriented programming to functional programming.  The Lambda Expressions in C# is definitely providing many advantages like reduced code and speed above the traditional programming.  Learning Lambda Expressions and the built-in methods in C# is not too hard, but requires sincere efforts. 

Power of Lambda

It is for sure that Lambda will reduce the code and execution time.

For example consider the case where a list contains numbers from 1 to 10, You wanted to print the numbers divisible by 2.

The code will be:

List<int> list = new List<int>(new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } );

           

foreach(int number in list)

if ((number %2)== 0)

            Console.WriteLine(number.ToString());

 

The same code for iterating, checking and displaying is combined using Lambda Expressions in one line as following:

list.Where(x => x > 0).ToList().ForEach(x => Console.WriteLine(x.ToString()));

Here we have reduced the code from 3 lines to 1 and the coding efforts too.  Above that, it is very interesting to use Lambda expressions.  Believe me!!

So I would like to start from the first step towards Lambda Expressions – that is delegates.  Learning one concept per day would be more easier and give more confidence in using it.

Delegates

Delegate is a type that references a method.  Same like a class variable can refer to an object instance, we can assign methods to the delegate variable.  It was a feature introduced in C# 2.0.

Example:

  public delegate void SimpleDelegate();

 

        static void Main(string[] args)

        {

            SimpleDelegate simpleDelegate = SimpleMethod;

            simpleDelegate();

 

            Console.ReadKey();

        }

 

        public static void SimpleMethod()

        {

            Console.WriteLine("Hi!");

        }

How it can be helpful? 

We can use delegates to create a skeleton of a method that would be used by multiple classes.  Event handlers can be created using delegates.

More Info: http://msdn.microsoft.com/en-us/library/ms173171(VS.80).aspx

Anonymous Methods

Anonymous methods were also introduced in C# 2.0 version.  Sometimes we run into cases like we have to create a method for assigning to events.  In this case, instead of creating a method, we can create inline methods – those are methods without a name.

Eg: In an ASP.NET application, we are setting the event handler of a button. The code will look like:

        protected void Page_Load(object sender, EventArgs e)

        {

            Button button = new Button();

            button.Click += new EventHandler(button_Click);

        }

 

        void button_Click(object sender, EventArgs e)

        {

           

        }

Here button_Click() is the method for the event handler.  The same code can be replaced as following using anonymous methods.

        protected void Page_Load(object sender, EventArgs e)

        {

            button1.Click += delegate(object s1, EventArgs e1)

            {

            };

        }

Please note that the delegate keyword is used to place the anonymous method.

In the above code we have saved one method and used inline coding for event handler.  This is a step towards our real aim – Lambda Expressions.

Delegates – Custom Delegate

Let us take another advanced example of Anonymous methods.  Here we are creating a custom delegate.  The WriteMessageDelegate delegate takes a string as argument and returns void.  It can be used as a callback mechanism to write messages globally in an application.

 

    public class Operation

    {

        public delegate void WriteMessageDelegate(string write);

 

        public void Do(WriteMessageDelegate write)

        {

            write("From Do() method.");

        }

    }

Test code is following: Here we are declaring a method named WriteMessage with same signature of the previous WriteMessageDelgate and then passing it to the Do method. 

    class Program

    {

        static void Main(string[] args)

        {

            Operation operation = new Operation();

            operation.Do(WriteMessage); // See the method pointer we are passing

 

            Console.ReadKey();

        }

 

        public static void WriteMessage(string message)

        {

            Console.WriteLine(message);

        }

    }

Please note that the Do method will be invoking the WriteMessage.

(One may get confused that statement operation.Do(WriteMessage); would be calling the WriteMessage. No!  This is just passing the method reference only)

If you can understand the above code, Congratulations!!!  You have just learned how to use delegates as arguments.

 

Lambda Expressions

A lambda expression is an anonymous function that can contain expressions and statements.

All lambda expressions uses the operator =>, which means “goes to”.

Eg: ForEach(argument => Console.WriteLine(argument));

The left hand side of => represents function arguments.

and the right hand side is the statement using argument.

Here the “argument” denotes the method argument and the operation on the right hand side.

This could be equivalent to the following lines:

        public void Write(string argument)

        {

            Console.WriteLine(argument);

        }

invoked as: list.ForEach(Write);

Example on Lambda

Consider we are having a list of string items.  We need to sort them using descending order.  So we have to implement the Compare() delegate.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace ConsoleApplication1

{

    class Program

    {

        static void Main(string[] args)

        {

            List<string> names = new List<string>();

            names.Add("Haq");

            names.Add("Jean");

            names.Add("Swami");

            names.Add("Gokila");

            names.Add("Meg");

 

            names.Sort((s1, s2) => s2.CompareTo(s1)); // Sorting

 

            names.ForEach(s => Console.WriteLine(s));

            Console.ReadLine();

        }

    }

}

Note: All the examples are intended to have System.Linq in the namespace section.

Sorting Example

Lambda Expression Without
names.Sort((s1, s2) => s2.CompareTo(s1));

names.Sort(

                delegate (string s1, string s2)

                {

                     return s2.CompareTo(s1);

 

                }

             );

 

Integer OrderBy Example

Lambda Expression Without
names.OrderBy(s => int.Parse(s));

names.Sort(

                delegate (string s1, string s2)

                {

                     return

int.Parse(s2).CompareTo(int.Parse(s1));

 

                }

             );

Note: The Sort() method actually changes the list, but OrderBy() gives an ordered view only without actually changing the list.

Integer OrderBy With Console Print

using System.Linq;

Namespace to include

List<string> list = new List<string>();

list.Add("1");

list.Add("10");

list.Add("2"); 

Code to Arrange

list.OrderBy(s => int.Parse(s)).ToList().ForEach(s => Console.WriteLine(s));

Lambda Code

list.Sort(delegate(string s1, string s2)

{

    return int.Parse(s1).CompareTo(int.Parse(s2));

}

);

 

foreach (string s in list)

    Console.WriteLine(s);

Regular Code

 

Selecting distinct Items With Console Print

using System.Linq;

Namespace to include

List<string> list = new List<string>();

list.Add("1");

list.Add("1");

list.Add("2"); 

list.Add("2"); 

Code to Arrange

list.Distinct(s => s).ToList().ForEach(s => Console.WriteLine(s));

Lambda Code

IList<string> unique = new List<string>();

            foreach (string s in list)

                if (!unique.Contains(s))

                    unique.Add(s);

foreach (string s in unique)

    Console.WriteLine(s);

Regular Code

 

Leave a Reply

Your email address will not be published. Required fields are marked *