Monthly Archives: July 2011

Delegates Explained – Part 2

The Delegates Series:

  1. Delegates Explained – Part 1
  2. Delegates Explained – Part 2 <<
  3. Delegates Explained – Part 3
  4. Delegates Explained – Part 4

In this, my 2nd post about Delegates in C#, I’m going to run through some code which demonstrates multicasting. The NotifyDvdArrived object which I worked with in my first post only had one “method-loaded” delegate assigned to it in the subscription method SubscribeMeForNotifications. This means that when we invoke that NotifyDvdArrived object, only one callback method will be invoked. With multicasting, we can have any number of methods subscribe for the invocation of the delegate. Hence the name multicasting i.e. the delegate is broadcasting to (potentially) multiple subscribers.

Recall in the first post how we created a custom delegate object using the Delegate keyword, and in the DVD store class, included a private variable of that type:

        public delegate void NotifyDvdArrived(string title);
        // ...
        public class DvdStore
        {
            private NotifyDvdArrived notification;        
        // ...
        }

Every custom delegate object maintains an invocation list i.e. a list of the Delegates that it will invoke, when it is invoked itself. The list can easily be ascertained with a call to the GetInvocationList method of that custom delegate object, which returns an array of Delegates i.e. Delegate []. This invocation list is what provides us with the multicasting functionality.

Recall that the DVD store provided a specification for the world at large to adhere to in subscribing for notifications. In that post, we (as a consumer) provided a method BroadcastArrivalOfDvd which adhered to that specification. We are going to refactor that code this week. First, we are going to supply a method called BroadcastArrivalOfDvdByBatSignal for the DVD Store to use to notify us.To recap what that means. We are giving the DVD store the BroadcastArrivalOfDvdByBatSignal method and when a new DVD comes in, they will use that method to notify us.

We should first take a look at the existing overload of the SubscribeMeForNotifications method which takes a single NotifyDvdArrived Delegate as a parameter. This now has to account for multicasting. It may be the case that the notification object already has one or more Delegates in its invocation list. To achieve this, C# gives us the Combine method, which adds any new Delegate objects to its existing invocation list:

            public void SubscribeMeForNotifications(NotifyDvdArrived notificationMethod)
            {
                notification = NotifyDvdArrived.Combine(notification, notificationMethod) as NotifyDvdArrived;
            }

But, we may decide, that is not enough. We want to cover our bases and make sure we don’t miss our notification (we may forget to look up at the sky when the bat signal is burning brightly). So, we are going to use a new overload for the DVD store’s subscription method to provide two further methods, BroadcastArrivalOfDvdByLoudSpeaker and BroadcastArrivalOfDvdBySnailMail, by which the DVD store will be able to notify us. So now, when the DVD store issues a notification, it will use 3 separate and distinct methods to do so. And each of those methods will comply with the specifications set out by the DVD store i.e. the signature of the NotifyDvdArrived Delegate. The new subscription method which takes an array of NotifyDvdArrived Delegates as a parameter:

            public void SubscribeMeForNotifications(params NotifyDvdArrived[] notificationMethod)
            {
                if (notificationMethod != null)
                {
                    //  Create a new Delegate array for the overload of the Combine method which takes a Delegate array as a parameter.
                    Delegate[] listOfDelegates = new Delegate[notificationMethod.Length + 1];

                    //  Now, add the existing notification to the array, along with the ones passed in as a parameter (the params array).
                    if (this.notification != null)
                    {
                        listOfDelegates[0] = notification;
                        notificationMethod.CopyTo(listOfDelegates, 1);
                    }
                    else
                    {
                        notificationMethod.CopyTo(listOfDelegates, 0);
                    }

                    notification = NotifyDvdArrived.Combine(listOfDelegates) as NotifyDvdArrived;
                }
                else
                {
                    throw new ArgumentException("The notificationMethod argument was null. It must have a value for a subscription to be successful.");
                }
            }

The calls to the subscription methods now become:

            theStore.SubscribeMeForNotifications(new NotifyDvdArrived(BroadcastArrivalOfDvdByLoudSpeaker), new NotifyDvdArrived(BroadcastArrivalOfDvdBySnailMail));
            theStore.SubscribeMeForNotifications(new NotifyDvdArrived(BroadcastArrivalOfDvdByBatSignal)); 
            theStore.SendOutNotification("The Thing");

One final noteworthy refactoring which I have made is to the SendOutNotification method. There is no need to explicitly call the Invoke method of the delegate (as shown in the original version of this program in the previous blog post). So our code becomes:

            public void SendOutNotification(string titleOfDvd)
            {
                notification(titleOfDvd);
            }

Get the code:


In my next post dealing with Delegates, I will talk about the event keyword and what it brings to the table.