October 10, 2018

726 words 4 mins read

Demystifying Delegates Part 1

Demystifying Delegates Part 1

In this post we are going to explore the basics of delegates, what they are and how to use them.

What are delegates?

Delegates are for methods what interfaces are for classes (kinda). That is, they both let you define types (or signatures) separately from implementation. Delegates:

  • Like interfaces, delegates can be passed as parameters
  • They can be ‘chained’ together (mulitcast) .
  • Used for event handling.
  • They are central to LINQ.
  • Can define callback methods.
  • Can define behaviours for implementing the Strategy Pattern.

Lets start with some simple examples: passing variables and objects to method parameters.

Passing a variable as a parameter

Calling a method passing a variable as a parameter is (hopefully) dead simple:

public void fillStapler(int stapleCount) { ... }
int numberOfStaplesToHand = 5;
fillStapler(numberOfStaplesToHand);

We have defined a method, fillStapler, which accepts an int instance. (Helpfully int is a type predefined by c#) We then defined a variable numberOfStaplesToHand of type int, initialised it to 5 (because that’s how many I just grabbed from the drawer). Then we called the fillStapler method, passing the numberOfStaplesToHand variable as the parameter.

Passing an object as a parameter

Pretty simple so far, fairly bread and butter. Defining our own types and passing them is also easy:

public interface Stapler { ... }
public class SwinglineStapler : Stapler { ... }
public void putInDrawer(Stapler obj) { ... }
Stapler myRedStapler = new SwinglineStapler();
putInDrawer(myRedStapler);

Here we have defined a couple of new types: the interface Stapler and class SwinglineStapler. Then we defined a new method, putInDrawer, which accepts a Stapler instance. We then defined myRedStapler, a variable of type Stapler and set it to a new SwinglineStapler (yeah I happen to work in a Stapler factory, we all make our own) Then we called putInDrawer passing the myRedStapler variable as the parameter.

Passing a method as a parameter

Okay also pretty simple but what if, when calling a method, instead of passing a variable as a parameter, we want to pass a method? Wait, what?

Well using delegates we can pass methods similarly to how we use interfaces to pass objects. Well above we saw how we can use an interface pass objects to methods via parameters. In a similar way we can use the delegate keyword to define a type to pass methods as parameters.

Interested?

How to implement delegates

Okay, in our scenario we want to specify a method that defines how we respond to someone who borrowed our stapler and is late to return it.

Defining a delegate

First we would have to define the signature of the method, we do this with the delegate keyword:

public delegate void responseBehaviour(Person borrower);

Delegate as a parameter

We then define a new method that accepts this new delegate as a parameter

public void borrowStapler(Person borrower, DateTime returnDate, responseBehaviour lateResponse) {
	if(DateTime.Now > returnDate) {
		lateResponse(borrower);
	}
}

So borrower is a Person who is borrowing our Stapler and is going to return it by returnDate, if they don’t then we will take do follow enact the lateResponse behaviour.

Assigning method to delegate

Suppose we have the following methods defined:

public void askPolitely(Person borrower) {
	borrower.say("Y-- Excuse me. You-- I believe you have my stapler?");
}

public void theLastStraw(Person borrower) {
	borrower.building.burn();
}

public bool UnjamPrinter() {
	return false;
}

We can pass these methods, to our borrowStapler method

Person Lumbergh = Management.CluelessManager();
borrowStapler(Lumbergh, DateTime.Now, askPolitely); // Ask Lumbergh for stapler back
borrowStapler(Lumbergh, DateTime.Now.AddDays(-1), theLastStraw); // Burn Initech HQ to the ground
borrowStapler(Lumbergh, DateTime.Now.AddDays(-1), UnjamPrinter); // Compiler error as UnjamPrinter does not match responseBehaviour delegate

So we can call borrowStapler and pass any method that matches the responseBehaviour delegate (that is accepts a Person, no return). UnjamPrinter doesn’t match this delegate, so can’t be passed for this parameter.

Conclusion

We have explored how delegates, like interfaces, define new types. These types can be passed as parameters, and looked at some examples.

Hopefully you are starting to see how delegates can be useful, in not never fear: At the start of this post we mentioned a number of uses Multicast, Event Handling, LINQ, Callback methods and the Strategy Pattern. I will be writing about these in the future.

Next Steps

Sign up to the bold mailing list to get updates to future articles, and please leave a comment below if you found this article useful, confusing or found a bug sadface

comments powered by Disqus