C# - Delegates 101 - A Practical Example

A practical example not too simple, not too complex, to explain delegates

This article has completely been reviewed, thanks to many encouraging comments below.

Introduction

Delegates play a major role in C# (e.g. LINQ's lambda expressions), so it's a good idea to really understand them.

Luckily, you'll find a whole bunch of well written articles on CodeProject that explain delegates (see links at the end). But IMHO, most articles fail to include a good example. Either they are too simple or too complex.

In this article, I'll try to give a practical example, albeit not from the real coding world.It's meant to give you a *feel* of how and when to use delegates.Still, the code will execute!

Delegates Simplified Recap

All you C# buffs will excuse me if I give a quick recap of delegates, and oversimplify things while doing so.

First off, a delegate is a type, i.e. a class. It’s a special class (you'll see why in a sec), but still, it's just a class.That means that like any other class, in order to be used, it must be:

declared and

instantiated

This will result in an object. That object can then be:

invoked

These are the 3 main steps in the lifecycle of a delegate. I'll point them out in the code.

Episode 1 – Without Delegates: the MarketingDepartment and its Service Providers

Suppose you have a class, called MarketingDepartment. It's job is to run advertising campaigns on new prospects (class CustomerAddress).If the budget is less then 10000, only Ballpens will be sent to the prospects. If we can afford more, we'll send coffee cups!

In order to do that, MarketingDepartment has 3 different "service providers" : an AddressProvider that will provide addresses, a BallpenCompany that will send the ballpens, and a CoffeeCupCompany that... well, you get the idea !

The Program class is the starting point. CustomerAddress is the class we'll use to pass addresses of prospects.The real shabang goes on in the MarketingDepartment: we'll fetch the adresses, and send those to the BallpenCompany or the CoffeeCupCompany, depending on the given budget.

Episode 2 – Enter the Delegate: Tell the AddressProvider How to Proceed!

The Marketing people, smart as they are, have an idea to speed things up! They say: "Hey, we don't want to waste time getting the addresses back from the AddressProvider and then send them to the BallpenCompany or the CoffeeCupCompany. Instead, it would save time if the AddressProvider knows immediately what to do with the addresses." />

In short, this is the strategy to follow:

A public delegate is declared, that will serve as the wrapper of the method that has to be invoked

The MarketingDepartment will fill that wrapper with the method of its choice (SendBallpens or SendCoffeeCups), and pass the wrapper to AddressProvider

The AddressProvider will accept the wrapper, and invoke it, without even knowing what concrete method is being executed

Here's how it would look like in code (I have cut out the bits that didn't change)

// here is the DECLARATION of the delegate (Step 1)
// the delegate class name is "DoAfterGetAddresses"
// it must specify the signature of the methods it will represent :
// the return type (bool in this case, can be any type, or "void")
// and optionally the parameters (in this case : List<CustomerAddress>)
publicdelegatebool DoAfterGetAddresses(List<CustomerAddress> ListOfAddresses);
publicclass MarketingDepartment
{
publicbool ExecuteNewCampaign(decimal budget)
{
bool success = false;
AddressProvider MyAddressProvider = new AddressProvider();
// here I will declare a delegate object of the delegate type above
// I will not instantiate it yet, because that depends on the budget
DoAfterGetAddresses ToDoAfterAddresses;
if (budget < 10000)
{
BallpenCompany MyBallpenCompany = new BallpenCompany();
// here I'll instantiate the delegate object (Step 2)
// I need to assign a method with the same signature as declared
// Also notice that I don't need to give the parameter yet
ToDoAfterAddresses = MyBallpenCompany.SendBallPens;
}
else
{
CoffeeCupCompany MyCoffeeCupCompany = new CoffeeCupCompany();
//same here
ToDoAfterAddresses = MyCoffeeCupCompany.SendCoffeeCups;
}
// it's now time to let the AddressProvider handle the campaign
// note how we pass the delegate instance as a parameter
success = MyAddressProvider.HandleCampaign(ToDoAfterAddresses);
return success;
}
}
publicclass AddressProvider
{
//here's the method that accepts the delegate object as parameter
publicbool HandleCampaign(DoAfterGetAddresses ToDoAfterAddresses)
{
bool success = false;
//get the addresses first
List<CustomerAddress> ListOfAddresses = GetAddressesNewProspects();
//now invoke the delegate (Step 3)
//at this stage, the ListOfAddresses is needed to pass as argument
success = ToDoAfterAddresses(ListOfAddresses);
// this means that the AddressProvider does NOT know what method
// exactly has been called : MyBallpenCompany.SendBallPens
// or MyCoffeeCupCompany.SendCoffeeCups
// that was the decision of the MarketingDepartment
// Furthermore, the signature tells me that the
// delegated method will return a boolean,
// that I can return that to the MarketingDepartment
return success;
}
public List<CustomerAddress> GetAddressesNewProspects()
{
....
}
}

Conclusion

A delegate turns out to be a sort of an interface of a method of an object -- ANY method of ANY object that meets its signature.

The delegate object can then be passed around as a parameter, and invoked by the receiving object.

In UML, I don't know (yet) how a delegate is diagrammed, but this is my best shot (better suggestions are welcome!)

Episode 3 – Another Scenario: Delegates that Tell the MarketingDepartment How to Proceed!

Another scenario would be that the AddressProvider has a connection with a BallpenCompany and a CoffeeCupCompany, as the UML class diagram shows.Instead of exposing those companies to the MarketingDepartment, the AdressProvider makes 2 delegates available: one for sending ballpens, another for sending coffee cups.

Conclusion

Delegates are a cornerstone for a significant portion of the C# language, especially the event-framework. Yet, they have a right on their own to be used in code. So, it's worth spending some time trying to understand them as completely as possible.Although there are many well-written articles available (see links below), most of them in my humble opinion lack a practical example that is neither too simple nor too complex.This article tried to fill that gap. I hope it succeeded somewhat in achieving that goal.

Links

These are articles I learned a lot from. Some of them are even fun to read!

Share

About the Author

I'm a self-made developer. And after years of writing code, I think I don't suck at everything ! When I stumble on a problem, I can't help but to figure it out. In some cases, I even write an article about it !
Also, in my quest to write better code, I have obtained a certificate as UML Professional, and I'm also a Certified ScrumMaster.

First of all, thank you for taking the time to help others learn. I can't wait until I feel like I understand this stuff enough to help someone else learn.

I'm still fuzzy on the why you would need a delegate. Here is how I would describe what I think a delegate is: a delegate is a class that is used to "point at" or "wrap" a method from another class.

In the code example, you use the delegate to call the method on the CoffeCupCompany or the BallPenCompany, BUT, the class you instantiate the delegate from already has a reference to both types of companies. So when you call the AddressProvider you could have just passed AddressProvider an object of the correct type (CoffeCup/BallPen) and then call the method on the object directly? This would require that you set up AddressProvider to take an abstract or Interface reference but it seems that, at least in this case, using an interface would have worked just as well?

Can you provide and explanation of even a single situation where a delegate is the only way to solve a particular problem?

Good question ! I don't really know the answer to that technically. But for me, delegates are things that you can use in a "pull" scenario : an object want to let another object do something. While events are used in a "push" scenario : hey, something happened to me, and I want everyone interested to know about it (and what they do with it, I don't care).
Ok, so this is far from a technical explanation, but it can create the proper context in which to use an event... or not ?

Excellent article. I'm at a point where I perfectly understand how to use delegates/events/anon methods and lambdas. However what seems to torture me is not understanding exactly WHY use delegates instead of regular method calls.

I understand how using a delegate can allow you to substitute code during run time in your class on the fly, simply by reassigning what method your delegate is referencing. So basically if I understand correctly, a delegate or a callback, allows me to write a class which can communicate back to the caller, like the main() method which calls a procedure in my class for example, and that class in turn, can call back some method in my Program class, so basically a delegate allows communication between objects. Is that correct and is that the main purpose of delegates? I also know that .NET library makes you use delegates a lot. Could you clarify and perhaps give a bit more explanation about exactly when I want/must use delegates? Thanks, I think I just had a revelation just writing this and I think I'm starting to understand the point. Thanks!

Wow, this is a very extensive question : when and why use delegates ? The truth is, there is no single answer. I was hoping that my article would give a hint when you can use a delegate. But in fact, there are many situations when you can/want/must use delegates. They are a technique that is available in the C#, VB.Net and perhaps others languages, just like for instance interfaces or abstract classes, and can be used and misused.
I think the more you use them, even just for fun in private and/or test projects, the more you will get to know them. And know know knowing them is love love loving them, as the song goes !
Thanks for writing !

I'm glad the example helped you to understand delegates better. But please remember that this is only 1 way of using delegates. Events are another, lambda expressions yet another. So keep on studying !

I'm sorry you find the example "not godd" (only joking )
But can you be a bit more specific ? Is it too complicated ? Too long ? Not clear enough ?
I suggest you copy the code and debug it step-by-step. I think you'll it find not that difficult at all !
Thank you for your vote