Click here to Skip to main content
Click here to Skip to main content

C# - Delegates 101 - A Practical Example

, 11 Apr 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
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 !

In an UML class diagram, it could look like this:

Episode 1 - Without delegates

In code, we could write something like this:

class Program
{
     static void Main(string[] args)
     {
           bool success = false;

           MarketingDepartment MyDepartment = new MarketingDepartment();

           success = MyDepartment.ExecuteNewCampaign(5000);

           Console.WriteLine("The new marketing campaign has {0} !", 
		success == true ? "succeeded" : "failed");
     }
}

public class CustomerAddress
{
     //Properties of Customer Address (Name, Street, City, etc.)
}

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.

public class MarketingDepartment
{
     public bool ExecuteNewCampaign(decimal budget)
     {
          bool success = false;

          AddressProvider MyAddressProvider = new AddressProvider();          

          List<CustomerAddress> ListOfAddresses = 
			MyAddressProvider.GetAddressesNewProspects();

          if (budget < 10000)
          {
              BallpenCompany MyBallpenCompany = new BallpenCompany();
              success = MyBallpenCompany.SendBallPens(ListOfAddresses);
          }
          else
          {
               CoffeeCupCompany MyCoffeeCupCompany = new CoffeeCupCompany();
               success = MyCoffeeCupCompany.SendCoffeeCups(ListOfAddresses);
          }

          return success;
     }
}

These are the service providers:

public class AddressProvider
{
    public List<CustomerAddress> GetAddressesNewProspects()
    {
        List<CustomerAddress> ListOfAddresses = new List<CustomerAddress>();

        //add addresses of prospects

        return ListOfAddresses;
    }
}

public class BallpenCompany 
{
    public bool SendBallPens(List<CustomerAddress> ListOfAddresses)
    {
        //for each CustomerAddress send ball pen

        return true;
    }
}

public class CoffeeCupCompany
{
    public bool SendCoffeeCups(List<CustomerAddress> ListOfAddresses)
    {
        //for each CustomerAddress send coffee cup

        return true;
    }
}

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:

  1. A public delegate is declared, that will serve as the wrapper of the method that has to be invoked
  2. The MarketingDepartment will fill that wrapper with the method of its choice (SendBallpens or SendCoffeeCups), and pass the wrapper to AddressProvider
  3. 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>)
public delegate bool DoAfterGetAddresses(List<CustomerAddress> ListOfAddresses);

public class MarketingDepartment
{
    public bool 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;
    }
}

public class AddressProvider
{
    //here's the method that accepts the delegate object as parameter
    public bool 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 2 : Delegate telling what to do

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.

Here's the UML:

Episode 3 : Giving a choice

And here's the code. Tip: have a look first at the AddressProvider!

public class MarketingDepartment
{
    public bool ExecuteNewCampaign(decimal budget)
    {
        bool success = false;

        AddressProvider MyAddressProvider = new AddressProvider();

        // getting the addresses
        List<CustomerAddress> ListOfAddresses = 
			MyAddressProvider.GetAddressesNewProspects();

        if (budget < 10000)
        {
            //step 3
            success = MyAddressProvider.MySendBallPens(ListOfAddresses);
        }
        else
        {
            //step 3
            success = MyAddressProvider.MySendCoffeeCups(ListOfAddresses);
        }

        return success;
    }
}

//declaration of 2 delegates (step 1)
public delegate bool SendBallPens(List<CustomerAddress>ListOfAddresses);
public delegate bool SendCoffeeCups(List<CustomerAddress>ListOfAddresses);

public class AddressProvider
{
    // I'll keep the Ballpen & Coffeecup as private fields
    private BallpenCompany MyBallpenCompany;
    private CoffeeCupCompany MyCoffeeCupCompany;

    // I'll have the delegate objects as fields available 
    public SendBallPens MySendBallPens;
    public SendCoffeeCups MySendCoffeeCups;

    // in the constructor, I'll instantiate 
    // the Ballpen & Coffeecup companies
    // and also the delegate objects (step 2)
    public AddressProvider()
    {
        MyBallpenCompany = new BallpenCompany();
        MyCoffeeCupCompany = new CoffeeCupCompany();
        MySendBallPens = MyBallpenCompany.SendBallPens;
        MySendCoffeeCups = MyCoffeeCupCompany.SendCoffeeCups;
    }

    public List<CustomerAddress> GetAddressesNewProspects()
    {
        ....
    }
}

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!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Erwin@Attentia
Web Developer
Belgium Belgium
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.

Comments and Discussions

 
QuestionLearn simply delegate : Pinmembermaulik2929-May-14 1:35 
GeneralFinally understood delegates. Thanks! PinmemberMember 822488714-Feb-14 2:23 
GeneralRe: Finally understood delegates. Thanks! PinmemberErwin@E2P16-Feb-14 23:03 
QuestionVery fine article. PinmemberMarius DUMITRU25-Mar-13 23:50 
AnswerRe: Very fine article. PinmemberErwin@ODS26-Mar-13 22:43 
Questionthanks :) PinmemberMember 822634015-Mar-13 0:29 
AnswerRe: thanks :) PinmemberErwin@ODS15-Mar-13 2:52 
GeneralMy vote of 5 Pinmemberahsan sarfraz27-Feb-13 7:47 
GeneralRe: My vote of 5 PinmemberErwin@ODS27-Feb-13 8:35 
QuestionDelegates & Events PinmemberArunAmalraj21-Feb-13 2:28 
AnswerRe: Delegates & Events PinmemberErwin@ODS21-Feb-13 9:58 
GeneralRe: Delegates & Events PinmemberArunAmalraj21-Feb-13 18:10 
GeneralMy vote of 5 PinmemberShawnna Christensen12-Feb-13 6:27 
GeneralRe: My vote of 5 PinmemberErwin@ODS12-Feb-13 7:05 
QuestionDefinately a 5 PinmemberPetr Kohout10-Dec-12 12:45 
AnswerRe: Definately a 5 PinmemberErwin@ODS10-Dec-12 22:10 
GeneralMy vote of 5 Pinmemberhomer202912-Nov-12 4:43 
GeneralRe: My vote of 5 PinmemberErwin@ODS12-Nov-12 6:08 
GeneralMy vote of 4 PinmemberWartickler24-Oct-12 10:26 
GeneralRe: My vote of 4 PinmemberErwin@ODS24-Oct-12 19:22 
GeneralMy vote of 4 PinmemberSeniorCrispy17-Oct-12 6:38 
GeneralRe: My vote of 4 PinmemberErwin@ODS17-Oct-12 6:44 
GeneralMy vote of 5 PinmemberRahul Rajat Singh14-Oct-12 19:06 
GeneralRe: My vote of 5 PinmemberErwin@ODS14-Oct-12 20:43 
QuestionOne question remains....when and why? Pinmemberlinnx8812-Oct-12 8:06 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.141220.1 | Last Updated 11 Apr 2010
Article Copyright 2010 by Erwin@Attentia
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid