Delegate Composition

The ability to compose delegates⏼by creating a single delegate out of multiple delegates-is one of those features that at first doesn't seem very handy, but if you ever need it you'll be happy that the C# design team thought of it. Let's look at some examples in which delegate composition is useful. In the first example, you have a distribution system and a class that iterates through the parts for a given location, calling a callback method for each part that has an "on-hand" value of less than 50. In a more realistic distribution example, the formula would take into account not only "on-hand" but also "on order" and "in transit" in relation to the lead times, and it would subtract the safety stock level, and so on. But let's keep this simple: if a part's on-hand value is less than 50, an exception has occurred.

The twist is that we want two distinct methods to be called if a given part is below stock: we want to log the event, and then we want to email the purchasing manager. So, let's take a look at how you programmatically create a single composite delegate from multiple delegates: -

Therefore, using this feature of the language, we can dynamically discern which methods comprise a callback method, aggregate those methods into a single delegate, and pass the composite delegate as though it were a single delegate. The runtime will automatically see to it that all of the methods are called in sequence. In addition, you can also remove desired delegates from the composite by using the minus operator.

However, the fact that these methods get called in sequential order does beg one important question: why can't I simply chain the methods together by having each method successively call the next method? In this section's example, where we have only two methods and both are always called as a pair, we could do that. But let's make the example more complicated. Let's say we have several store locations with each location dictating which methods are called. For example, Location1 might be the warehouse, so we'd want to log the event and email the purchasing manager, whereas a part that's below the minimum on-hand quantity for all other locations would result in the event being logged and the manager of that store being emailed.

We can easily address these requirements by dynamically creating acomposite delegate based on the location being processed. Without delegates, we'd have to write a method that not only would have to determine which methods to call, but also would have to keep track of which methods had already been called and which ones were yet to be called during the call sequence. As you can see in the following code, delegates make this potentially complex operation very simple.