Delegates, can’t live with them, can’t live without them.

Introduction

There is a famous quote by Jim Henson: “If you can’t beat them. Join them”.

It’s possible to write code for years without deliberately using delegates. I say “deliberately” because we may have used them without realizing it. Knowing what these types represent makes reading code easier. Knowing how to use them adds some useful tools to our developer toolbox. So instead of ignoring them, why not learn them. In this post, I will show you how you can get started with delegates and their use cases, which will encourage you to use them more in your code.

There are multiple definitions of delegates and one might make more sense over the other. Lets see few of those:

  • A delegate is a type that represents a method with a specific signature and return type.
  • A delegate is a pointer or a reference to a method.
  • A delegate is a pipeline.

Still cryptic? Here are few examples:

Examples:

A delegate representing a method that adds two numbers and returns a result:
delegate int AddNumbers(int value1, int value2);
A delegate representing a method that logs an exception and doesn't return anything:
delegate void LogException(Exception ex);
A delegate representing a function that converts some generic type to a string:
delegate string FormatAsString(T input);

Notice, The declaration of a delegate looks exactly like the declaration of a method, except with the keyword delegate in front of it.

Just like classes and interfaces, we can declare delegates outside of classes or nested within classes. We can mark them private, public, or internal.

With delegates we can pass our methods (functions) around like values.

Delegate in action

Lets see a working example of delegates. Here I started with defining a delegate MathCalculation with accepts two floats and return a double. Then I created two variables of this type and assign methods to those variables. And finally we invoke/call them and display the results:

So, in delegate world, instead of calling the methods directly, we have now an indirection, we are invoking the methods using delegates instead. Having this capability offers a lot of flexibility which we will learn more as we move forward. A common use case is to implement reactions to specific events, and call-back methods.

Lets see another example of delegates. The code is very similar to what we have already seen in Calculator example:

Define a delegate:

Here is the ServerInfo class, we will use its method to assign to delegate types. Notice the methods signature match the delegate defined earlier:

And here is code block which is using delegates:

output of this is shown below:

Events Relationship with Delegates

I’ve written few posts about .NET Events and you can check those if you need more information. Here I will just point out their relationship with delegates.

  • Events are associated with delegates.
  • A standard .NET Event accepts Sender and EventArgs.
  • The signature of EventHandler matches to delegate.
  • EventHandler<T> provides a simple way to create a custom delegate for an event.

Example Delegates

Lets see another example of delegates:

I created classes to generate a static list of employees as shown below:

Here is the main method using these classes:

If we run the code it will display information as shown below:

Nothing special so far, typical way of writing code.

Lets imagine, that inside the loop, we don’t want to use Console.WriteLine directly or in other words we dont want to hardcode the part which deals with printing. Instead we want this logic to comes from somewhere else. This part can be sent as a parameter from outside. Sounds familiar? yes, we can use delegate which as we saw before is a pointer to a function.

I created a delegate called Print:

Then I defined the function which has same signature as delegate:

Now, we can use it in main method as shown below:

And you might have already guessed it, running this code produces the same output, but we have now delegate indirection in-place:

Now, update our code to wireup a different print delegate to display employee info:

I create a new method in PrintingUtils class which has the same signature of the delegate, just the implementation is different:

Here is the updated delegate wiring and usage code:

The output now shows the Id as well along with Name:

Notice that with the use of delegates our code is already begin to be loose coupled and you can take this ability to next level, implement business rules as delegates and pass them around etc. You can pass functions to other functions as well. There are a lot places you can use delegates.

Summary

In this post, I tried to describe delegates and how to use those in your code. We also saw some information about their relationship with Events. You can read about Events in this post. The code for the demos is available on this link. Till next time, Happy Coding.

References