Click here to Skip to main content
15,867,141 members
Articles / Programming Languages / C#

Have Your Foot in the Door with Delegate and Events

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
21 Mar 2014CPOL4 min read 6.5K   3  
Have your foot in the door with delegates and events

delegate

Delegate and events are one of the most used techniques in a program. In my opinion, people use them most but write them the least. Recently, one of my juniors asked me about an explanation about delegate and event and this is the reason why I am here sitting and writing for the next generation programmers.

Frankly speaking, delegates are a kind of an advanced version of function pointer. Those who are familiar with C/C++ know that function pointers are a special type of pointers that store the address of a function in the stack. This address can be passed freely throughout the program and later on when needed, can be executed anywhere of the program.

On the other side, events are a kind of signal in C/C++. These signals can be raised by your program as like a signal can be raised by the Operating System when you plug-in a USB stick; but someone out there needs to listen the signals and handle them properly.

Well, all those are theoretical and now we can go to the practical use of it. Delegates and events are used in scenarios where we need publish-subscribe pattern. Now that is publish-subscribe pattern? Hit on wiki here for a detailed description. But in a nutshell, The Publishers will raise a signal and the subscribers will listen to those signals and act accordingly. What I want to emphasize on public subscriber pattern is The Publisher should not have any knowledge of who are The Subscribers are, and The Subscribers should not have any interaction with The Publishers, except one thing – listening to The Publisher’s event.

In Publisher.cs

So now, we have a publisher class where we need a delegate and delegate-type-variable. As I discussed above that the delegate will point to a function, so it must specify a function signature.

C#
public delegate bool NewEditionPublishHandler
(object Publisher, string EditionName , int EditionNr);

This function signature is the type of the delegate-variable.

C#
public NewEditionPublishHandler Publish;

Later in Publisher, this delegate-variable will point a function in the Subscriber class so that the publisher can call that function using this delegate-variable.

C#
public delegate bool NewEditionPublishHandler(object Publisher, string EditionName , int EditionNr);
public NewEditionPublishHandler Publish;
… … …
Publish(this, "Harry Potter" , i++);

Notice that Publisher is calling a function of a Subscriber without any knowledge of it. No reference, no variable, no knowledge at all, except the face that the subscriber must listen to the signal sent by the publisher, i.e., Subscriber must subscribe a function to that signal and of course that function signature should be the same as that delegate-type.

At the subscriber class, this is done by the following code:

In Subscriber.cs

C#
public void SubscriberToPublisher(Publisher publisher)
{
   publisher.Publish += new Publisher.NewEditionPublishHandler(ShowPublicationDetail);
   //or (event subscription with delegate keyword)
   publisher.Publish += delegate(object SubscribedPublisher, 
         string publicationName, int publilcationNr)  { … return True };
   //or (event subscription with linq expression)
   publisher.Publish += (SubscribedPublisher, publicationName, publilcationNr) => { … return True;};
}

The above three statements are doing the same task with three different syntaxes:

Here two interesting things are happening.

  • Subscriber is subscribing itself to a signal of the publisherSubscriber is binding an anonymous function with the signal of the publisher so that whenever a signal is raised from the publisher, this function will be executed.
  • Publisher is delegating its task to the SubscribersPublisher is delegating its task to the subscribers function so whenever the publisher is calling the delegate-variable, it’s the subscribers anonymous function gets executed.

In Program.cs

In our program, somewhere we need to create a publisher and a subscriber and subscribe to the publisher.

C#
Publisher P = new Publisher();
Subscriber S = new Subscriber();
S.SubscriberToPublisher(P);
Subscriber2 S2 = new Subscriber2();

S2.SubscriberToPublisher(P);
 
Finally run the publishers PublishRegularly().
 
P.PublishRegularly();

This PublishRegularly() function will in a regular interval call the delegate-variable with appropriate perimeters. This delegate-variable which will in turn delegate its task along with its parameter to the subscriber’s anonymous function and get the job done by the subscriber.

C#
public void PublishRegularly()
{
   while (true)
   {
      Thread.Sleep(2000);
      if (Publish != null)
      {
         Publish(this, "Harry Potter (pert " + i.ToString() + ") ", i++);
      }
   }
}

Notice that we are doing a check ((Publish != null)). This is done because if there is no subscriber subscribing to the publisher, the publisher can still run the function, i.e., the publisher is completely ignoring whether any subscriber is subscribing to it or not.

Even if there is more than one subscriber subscribing, it does not matter to the publisher either. It’s the subscriber's responsibility to listen to the publisher's signal and act accordingly with the help if its own anonymous function.

Event

Now in the Publisher.cs file, change the declaration of the delegate type-variable like this:

C#
<s>public NewEditionPublishHandler Publish;</s>
public event NewEditionPublishHandler Publish;

And in the Subscriber.cs, change the publisher's signal subskribtion(event subskribtion) like this:

C#
<s>publisher.Publish += (SubscribedPublisher, publicationName, publilcationNr) =>{…}</s>
publisher.Publish = (SubscribedPublisher, publicationName, publilcationNr) =>{…}

With this, you will get an error:

Error 1 The event 'Delegate_Event_Test.Publisher.Publish' can only appear 
on the left hand side of += or -= (except when used from within the type 'Delegate_Event_Test.Publisher')
C:\Users\rizvis\Documents\Visual Studio 2010\Projects Test\Delegate_Event_Test\Delegate_Event_Test\Subscriber.cs
23                     23                         Delegate_Event_Test.

Thanks to ‘event’ for making this error because with the statement:

C#
publisher.Publish = (SubscribedPublisher, publicationName, publilcationNr) =>{…}

Here, you are not subscribing a signal from a delegate-variable, rather you assigning a wrong value to it. This is wrong and your program will not work as it is intended. Without the ‘event’ keyword, you will not get a compilation error and thus you are planting a bug in your code. So with the ‘event’ keyword even if you missed += with =, it will show up at compile time.

Bird’s eye view

So with a delegate, we are preparing an object (i.e. Publisher) to emit a signal to another set of objects (i.e. Subscribers) who are subscribed with publishers' signal with an anonymous function. As a notification of the signal, the subscribers will execute their own function. So simple!

License

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


Written By
Software Developer
Sweden Sweden
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --