Introduction

Delegates encapsulate a method. All they do is provide an alternate way to call (‘invoke’) a method. This concept has been around for a while (function pointers in C – and other languages). In C#, there are three things to remember when using delegates. Just use the acronym D-A-I  for ‘Declare’, ‘Assign’ and ‘Invoke’.

Declaring a delegate

Say you have a function that takes two strings, concatenates them and returns the result. So the signature would look something like the snippet below.

private static string stringCat(string a, string b)

       {

           return String.Concat(a,b);

       }

To encapsulate this function within a delegate, one declares a delegate as follows:

delegate string del(string a, string b);

Assigning a Delegate

Once you have it declared (remember, it is simply encapsulating a function), you will need to specify which function you want to use it on. This is the assignment step – and is illustrated in the snippet below.

private static string DelegateSimpleInvoke()

       {

           // assign your delegate to the stringCat target

           del x = stringCat; 

           // invoke the delegate (which means 'call your function' indirectly). This should return "ab"

           string c = x.Invoke("a","b");

           return c;

       }

Invoking a Delegate

Once you have assigned a target method for your delegate, you are ready to invoke the delegate (call the method). This is done via the Invoke keyword as shown above. This is where you would pass in the actual argument values to the function.

So, there you have it. In three simple steps – D.A.I. – you can use delegates in C#.

Asynchronous Invocation

A nice advantage of encapsulating a method is that you can invoke it any way you like – synchronously (using Invoke) or asynchronously (using BeginInvoke).

private static string DelegateAsyncInvoke()

      {

          // assign your delegate to the stringCat target

          del x = stringCat;

          // invoke the delegate (which means 'call your function' indirectly). This should return "ab"

          IAsyncResult result = x.BeginInvoke("a", "b",null,null);

          

          // Do something else while the method execution has not yet completed

          while (!result.IsCompleted)

          {

              Thread.Sleep(500);

              Console.Write(".");

          }

 

          // Now, the method has finished executing - since result.IsCompleted is true

          string c = x.EndInvoke(result);

 

          return c;

      }

Common Misconception – Delegates and Async programming

Most people associate the two. Delegates, by themselves, have nothing to do with an asynchronous model of programming. They simply encapsulate a function (any function). Now, once the function is encapsulated, it becomes possible to call it (invoke it) – synchronously OR asynchronously – as you choose. In the case of C#, the built-in delegate class provides you with supporting methods to invoke (the encapsulated method) asynchronously – which is why the misconception occurs. A delegate by itself, doesn’t care about whether you invoke synchronously or asynchronously. Only the client cares. The delegate’s job is to provide encapsulation for your method – and that’s it.

Using a Lambda Expression with a delegate

Notice that there is no assignment step like del x = stringCat in the snippet below. The assignment is done using a lambda expression. How does it know what x and y are? It ‘infers’ them based on the String.Contact function. It figures out that you will need to pass in two strings – and infers that x and y are strings.

/// <summary>

       /// same thing as before - without an explicit assignment. Using a lambda expression for assignment.

       /// </summary>

       private static string DelegatesUsingLambdaExpr()

       {

           del z = (x,y) => String.Concat(x, y);

           return z.Invoke("a", "b");

       }

Summary

Delegates are a simple way to encapsulate methods – so that they can be called later. In addition to providing a way for ‘regular’ (synchronous) method invocation, they also provide an easy option to invoke the method asynchronously. Remember D.A.I (Declare, Assign and Invoke) to simplify usage of delegates within your codebase.

Anuj holds professional certifications in Google Cloud, AWS as well as certifications in Docker and App Performance Tools such as New Relic. He specializes in Cloud Security, Data Encryption and Container Technologies.

Initial Consultation

Anuj Varma – who has written posts on Anuj Varma, Hands-On Technology Architect, Clean Air Activist.