Understanding Delegates In C# - Part 2

In this article I will explain about delegates with named method, anonymous method, Lambda Expression, anonymous method with omit parameter list, and delegate inference.

inference

This is my 2nd article on “understanding delegates in C#” and in this article I will explain about those points of delegates which were not covered in the previous article. If you missed the previous article on understanding delegates in C# you can go through the following link:

In my previous article I explained about Event, Event Raiser, Event Handler, Delegate, EventArgs (event data), Delegates, and  Event Handling with Windows Form, WPF and Web Form Applications, Singlecast and Multicast delegate, way of calling a delegate (using Invoke method, by passing it as parameter, by passing parameters inside the delegate object) using return type other than void with Multicast delegates, adding methods in invocation list and removing it from invocation list and calling it, etc.

In this article I will explain these points:

  • Instantiate the delegate using an anonymous method.
  • Delegate inference.
  • Instantiate the delegate using Lambda Expression.
  • Instantiate the delegate using an anonymous method & omit parameter list.

Instantiate the delegate using an anonymous method

We have already seen a lot of ways to instantiate the delegate using named method. Now let us see how the same thing can be used with anonymous method.

The delegate feature was available in C# from the first day of its release but later on a lot of updates were done in later versions. In C# 2.0 a new way of calling method using delegate has been introduced which is known as anonymous method.

As it has the name anonymous it means it does not have a method name, and creating anonymous methods is essentially a way to pass a code block as a delegate parameter.

Using Named Method

  1. SomeActionPerformedHandler mycustomdelegate1 = new SomeActionPerformedHandler(FirstWorkPerformed);  
  2. public static void FirstWorkPerformed(int x, int y)  
  3. {  
  4.    //do something for FirstWorkPerformed   
  5.    Console.WriteLine($"FirstWorkPerformed Executed and result is: {x + y}");  
  6. }   
Using Anonymous Method
  1. SomeActionPerformedHandler mycustomdelegate2 = delegate (int x, int y)  
  2. { Console.WriteLine($"SecondWorkPerformed Executed and result is: {x + y}"); };  
Complete Code
  1. class AnonymousMethodExample  
  2. {  
  3.     public delegate void SomeActionPerformedHandler(int x, int y);  
  4.     static void Main(string[] args)  
  5.     {  
  6.         // Instantiate the delegate using named Method  
  7.         SomeActionPerformedHandler mycustomdelegate1 = new SomeActionPerformedHandler(FirstWorkPerformed);  
  8.         // Instantiate the delegate using an anonymous method  
  9.         SomeActionPerformedHandler mycustomdelegate2 = delegate(int x, int y)  
  10.         {  
  11.             Console.WriteLine($ "SecondWorkPerformed Executed and result is: {x + y}");  
  12.         };  
  13.     }  
  14.     public static void FirstWorkPerformed(int x, int y)  
  15.     {  
  16.         //do something for FirstWorkPerformed   
  17.         Console.WriteLine($ "FirstWorkPerformed Executed and result is: {x + y}");  
  18.     }  
  19. }  
These are the following benefits of the anonymous method:

 

  • We do not have to create a separate method in the case of the anonymous method due to the fact that  it reduces the coding overhead in instantiating delegate.
  • We can omit the parameter list while using the anonymous method.

You may be thinking that when you have the advantage of specifying a code block instead of a delegate it can be useful. It can be useful in many cases. Suppose you have to start a new thread, so in that case why would you prefer to create a new method to start the thread? Just use it with the anonymous method.

Example

  1. publicstaticvoid StartNewThreadToWriteConsoleMsg()  
  2. {  
  3.     Thread thread = newThread(delegate()  
  4.     {  
  5.         System.Console.WriteLine("Hi!!!");  
  6.         System.Console.WriteLine("Good Morning everyone");  
  7.         System.Console.WriteLine("Welcome to understanding delegates in C#");  
  8.     });  
  9.     thread.Start();  
  10. }  
  11. Complete code: classAnonymousMethodExample  
  12. {  
  13.     staticvoid Main(string[] args)  
  14.     {  
  15.         StartNewThreadToWriteConsoleMsg();  
  16.     }  
  17.     publicstaticvoid StartNewThreadToWriteConsoleMsg()  
  18.     {  
  19.         Thread thread = newThread(delegate()  
  20.         {  
  21.             System.Console.WriteLine("Hi!!!");  
  22.             System.Console.WriteLine("Good Morning everyone");  
  23.             System.Console.WriteLine("Welcome to understanding delegates in C#");  
  24.         });  
  25.         thread.Start();  
  26.     }  
  27. }  
In the above example we are specifying a code block instead of a delegate so it creates a thread and contains the code that executes without creating an additional method for the delegate.

I am giving an example to create a thread using the anonymous method, but we also have another option to create a thread. Let’s see another way to create a thread using delegate ThreadStart.

Code
  1. static void StartNewThread(ThreadStart threadStart)  
  2. {  
  3.     threadStart();  
  4. }  
  5. static void PrintCurrentTime()  
  6. {  
  7.     Console.WriteLine($ "Current DateTime is : {DateTime.Now}");  
  8.     Thread.Sleep(1000);  
  9.     PrintCurrentTime();  
  10. }  
  11. And call it as: StartNewThread(newThreadStart(PrintCurrentTime));  
  12. Complete Code: classAnonymousMethodExample  
  13. {  
  14.     public delegate void SomeActionPerformedHandler(int x, int y);  
  15.     staticvoid Main(string[] args)  
  16.     {  
  17.         StartNewThread(newThreadStart(PrintCurrentTime));  
  18.     }  
  19.     staticvoid StartNewThread(ThreadStart threadStart)  
  20.     {  
  21.         threadStart();  
  22.     }  
  23.     staticvoid PrintCurrentTime()  
  24.     {  
  25.         Console.WriteLine($ "Current DateTime is : {DateTime.Now}");  
  26.         Thread.Sleep(1000);  
  27.         PrintCurrentTime();  
  28.     }  
  29. }  
Output

Output

Here you may be thinking that we have not used the delegate keyword. I am not using any delegate keyword but rather using the in-built delegate of C#. If you press F12 (go to definition) on ThreadStart then you will find the following definition:
  1. namespace System.Threading  
  2. {  
  3.     //  
  4.     // Summary:  
  5.     // Represents the method that executes on a System.Threading.Thread.  
  6.     [ComVisible(true)]  
  7.     public delegate void ThreadStart();  
  8. }  
There are a lot of in-built delegates in C#.

Delegate inference

Delegate inference means attaching a method directly with the event or passing a method reference directly and the compiler will infer the delegate internally.

Example 1:

Using
  1. StartNewThread(PrintCurrentTime);  
  2. Instead of   
  3. StartNewThread(newThreadStart(PrintCurrentTime));  
Complete code
  1. class AnonymousMethodExample  
  2. {  
  3.     public delegate void SomeActionPerformedHandler(int x, int y);  
  4.     static void Main(string[] args)  
  5.     {  
  6.         StartNewThread(newThreadStart(PrintCurrentTime)); //comment and use below line you will get the same result.  
  7.         StartNewThread(PrintCurrentTime);  
  8.     }  
  9.     static void StartNewThread(ThreadStart threadStart)  
  10.     {  
  11.         threadStart();  
  12.     }  
  13.     static void PrintCurrentTime()  
  14.     {  
  15.         Console.WriteLine($ "Current DateTime is : {DateTime.Now}");  
  16.         Thread.Sleep(1000);  
  17.         PrintCurrentTime();  
  18.     }  
  19. }  
Example 2:

using
  1. this.button1.Click += this.button1_Click;  
instead of
  1. this.button1.Click += new System.EventHandler(this.button1_Click);  
And the compiler will infer the delegate internally.

Instantiate the delegate using Lambda Expression

In C# 3.0 Lambda expression has been introduced which provides features to write very little code to associate a method with a delegate, so the user has more options on using lambda expressions. So we can say that lambda expressions supersede anonymous methods as the preferred way to write inline code.

Example:
  1. public delegate void SomeActionPerformedHandler(int x, int y);  
  2. SomeActionPerformedHandler mycustomdelegate3 = (x, y) =>  
  3. {  
  4.     Console.WriteLine($ "ThirdWorkPerformed Executed and result is: {x + y}");  
  5. };  
  6. Complete Code: classProgram  
  7. {  
  8.     public delegate void SomeActionPerformedHandler(int x, int y);  
  9.     static void Main(string[] args)  
  10.     {  
  11.         // Instantiate the delegate using named Method  
  12.         SomeActionPerformedHandler mycustomdelegate1 = new SomeActionPerformedHandler(FirstWorkPerformed);  
  13.         // Instantiate the delegate using an anonymous method  
  14.         SomeActionPerformedHandler mycustomdelegate2 = delegate(int x, int y)  
  15.         {  
  16.             Console.WriteLine($ "SecondWorkPerformed Executed and result is: {x + y}");  
  17.         };  
  18.         // Instantiate the delegate using Lambda Expression  
  19.         SomeActionPerformedHandler mycustomdelegate3 = (x, y) =>  
  20.         {  
  21.             Console.WriteLine($ "ThirdWorkPerformed Executed and result is: {x + y}");  
  22.         };  
  23.     }  
  24.     public static void FirstWorkPerformed(int x, int y)  
  25.     {  
  26.         //do something for FirstWorkPerformed  
  27.         System.Threading.Thread.Sleep(500);  
  28.         Console.WriteLine($ "FirstWorkPerformed Executed and result is: {x + y}");  
  29.     }  
  30. }  
You may be thinking that if the lambda expression has been introduced, then why will we need to use named method or anonymous method for associating method with delegate? I would like to clarify that no one is a replacement of any other, all three are the ways to call delegates and they have their own importance.

For instance, anonymous method provides the features that we can omit the parameter list but we cannot do this with lambda expression.

Instantiate the delegate using an anonymous method & omit parameter list

Example:
  1. // Instantiate the delegate using an anonymous method & omit parameter list  
  2. SomeActionPerformedHandler mycustomdelegate1 = delegate  
  3. {  
  4.     Console.WriteLine($ "FirstWorkPerformed Executed");  
  5. };  
  6. mycustomdelegate1.Invoke(10, 20);  
Complete code:
  1. classProgram  
  2. {  
  3.     publicdelegatevoidSomeActionPerformedHandler(int x, int y);  
  4.     staticvoid Main(string[] args)  
  5.     {  
  6.         // Instantiate the delegate using an anonymous method & omit parameter list  
  7.         SomeActionPerformedHandler mycustomdelegate1 = delegate  
  8.         {  
  9.             Console.WriteLine($ "FirstWorkPerformed Executed");  
  10.         };  
  11.         mycustomdelegate1.Invoke(10, 20);  
  12.     }  
  13. }  
  14. But the same thing will not work with lambda expression.  
  15.     //try with lambda expression  
  16. SomeActionPerformedHandler mycustomdelegate2 = () =>  
  17. {  
  18.     Console.WriteLine($ "SecondWorkPerformed Executed and result is: {x + y}");  
  19. };  
It will throw the following complete time error:

Error CS1593 Delegate 'Program.SomeActionPerformedHandler' does not take 0 arguments ParameterOmitWithAnonymousMethod

error

In this article I have explained about instantiating delegate using an anonymous method, delegate inference, etc.

Instantiate the delegate using Lambda Expression & instantiate the delegate using an anonymous method & omit parameter list. In the next article I will explain about in-built delegates of C#.