C# Delegates

C# Delegates

Delegates can be hard to get your head around. I think the reason is that there are so many moving parts involved (declaring the delegate, declaring the delegate instance, declaring matching signatures, assigning the instance, etc, etc).

I thought maybe a different approach would be useful (Inspired by Rome Total War).

Enter Delegus Maximus

Imagine you are the great Roman general Delagus Maximus. In a few moments, you will be launching an all out offensive against a loosely allied confederation of barbarian tribes.

In a desperate attempt at defense the barbarians forge shaky relations between warring tribes, yet distrust runs rampant from years of conflict. While huge in number, they are unable to coordinate effectively.

But not you. Your army is a well oiled machine of destruction!

To coordinate your specialized units, you use different colors of flags to give to indicate shared maneuvers. This way a single flag can result in a whole series of complex maneuvers between legions, cavalry, archers, and artillery. For example, a red flag might mean rank and file attack head on while cavalry flank and archers shoot at the enemy’s rear. A yellow flag might mean skirmishers should pick at enemy archers while cavalry charges and your pikes brace for an enemy charges. You get the idea.

If coding this, we would need a way to represent the various flags and have the attack order vary with different flags. We also need multiple actions to be taken when the order is issued. One way would be to use a delegate type to represent the order and a parameter to represent the flag:

//Declare a delegate
public delegate void AttackOrder(Color flagColor);

So what is this delegate thing? In fact it’s just a type declaration: It’s a type whose payload is a method signature. What makes it confusing is that it looks so much like a method. If I had been the author of C# the delegate declaration might have looked more like this:

//Not real code!  
public delegate Attackorder  = void (Color flagColor);

But that’s just my opinion.

Each troop’s squad needs a method that matches the delegate’s method signature so they can respond to attack orders. To simplify this example, I created an interface that has a method matching the delegate signature. Notice that the signature of RespondToOrder matches the delegate.

interface ITroopSquad
{ 
       void RespondToOrder(Color flagColor);
}

Each unit implements this interface. I’m going to create Archer and Cavalry classes:

class Archers : ITroopSquad 
    { 
        public void RespondToOrder(Color flagColor) 
        { 
            //This matches the delegate signature. Do orders here. 
        } 
    }
 
class Cavalary : ITroopSquad
    {
        public void RespondToOrder(Color flagColor)
        {
            //This matches the delegate signature.  Do orders here.
        }
    }

I then place some units in a list:

    List<ITroopSquad> romanArmy;    
    romanArmy = new List<ITroopSquad>();
    romanArmy.Add(new ArcherSquad());
    romanArmy.Add(new CavalarySquad());

What we need next is to declare a variable of the delegate type.

public AttackOrder destroyBarbarians;

This just a declaration, nothing more interesting than int x. We have just declared (but not created!) a variable of the delegate type we are going to assign to.

We’re just about ready to crush the resistance, but we still need to tell our troops to listen for the order. We need to have each troop’s RespondToOrder method invoked when the destroyBarbarians delegate instance is invoked.

I can assign each troop’s RespondToOrder event using the following:

  foreach (ITroopSquad troop in romanArmy)
  {
      destroyBarbarians += new AttackOrder(troop.RespondToOrder);
  }

What’s happening here?

Each time we loop through the foreach, a new delegate instance of AttackOrder is constructed with an instance of the troop.RespondToOrder method. It is then combined (chained) using += with any existing delegates already assigned to destroyBarbarians.

In C# 2.0 and beyond, a simplified syntax is available as follows:

  foreach (ITroopSquad troop in romanArmy)
  {
      destroyBarbarians += troop.RespondToOrder;
  }

Under the covers the compiler is creating the appropriate delegate type for us and assigning it.

The stage is then set. The army awaits the order. All we need do is give the order!

if (destroyBarbarians != null)
{       
  destroyBarbarians(Color.Red);
}

Well you do see we had to do one more thing – we also needed to make sure the order isn’t null when we invoke it. For example, if all of our troops are dead (nobody is listening when we invoke destroyBarbarians) than we can expect an exception because the delegate has no assigned value.

With a single wave of our red flag, our squads sweep into action and route the barbarian horde! Victory!