Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Events and Delegates Vs Calling methods

Tags:

c#

I hope this question is not to closely related to others but others don't seem to fill the gap in knowledge.

This seems to be hot topic to try and understand Events and Delegates and after reading many SO questions and MSDN articles I'm afraid to say I still don't understand. After some years creating great web applications, I found myself getting extremely frustrated in not understanding them. Please can anyone clarify this in common code. So the question is, why would you use events and delegates over calling a method?

Below is some basic code I written at work. Would I be able to leverage events and delegates?

Public Class Email
{
   public string To {get;set;}
   //Omitted code

   public void Send()
   {
    //Omitted code that sends.
   }
}

Public Class SomeClass
{
   //Some props

   Public void DoWork()
  {
    //Code that does some magic

    //Now Send Email
    Email newEmail = new Email();
    newEmail.To = "[email protected]";
    newEmail.Send();
  }
}

This is probably not the best example but is there anyway that the DoWork() method can subscribe to the Email? Would this work? Any help for me to truly understand events and delegates would be greatly appreciated.

Regards,

like image 340
Tez Wingfield Avatar asked Mar 07 '15 11:03

Tez Wingfield


People also ask

What is difference between delegate and method?

A delegate is a method with a parameter and a return type. A delegate is a type that safely encapsulates a method. Delegates are object-oriented, type safe, and secure.

What is the difference between an event and a delegate?

Delegate is an object used as a function pointer to hold the reference of a method. On the other hand, events provide an abstraction to delegates. A keyword required to declare a delegate is a delegate whereas, a keyword required to declare an event is event.

Why should I use events instead of direct method calls?

Less references to other classes in your code, which reduces the potential for memory leaks. Cleaner code. More flexible/reusable code (a bunch of other classes could all listen/respond to the event without any additional code in the your dispatcher)

What is the difference between events and multicast delegates?

Delegates are pointer to functions and used for call back. Multicast delegates help to invoke multiple callbacks. Events encapsulate delegate and implement publisher and subscriber model.


1 Answers

The biggest reason I have found in real-world programming for the use of events and delegates is easing the task of code maintenance and encouraging code reuse.

When one class calls methods in another class, those classes are "tightly coupled". The more classes you have tightly coupled, the more difficult it becomes to make a change to one of them without having to also change several others. You may as well have written one big class at that point.

Using events instead makes things more "loosely coupled" and makes it much easier to change one class without having to disturb others.

Taking your example above, suppose we had a third class, Logger, that should log when an email is sent. It uses a method, LogEvent(string desc, DateTime time), to write an entry to the log:

public class Logger 
{
  ...
  public void LogEvent(string desc, DateTime time)
  {
    ...//some sort of logging happens here
  }
}

If we use methods, we need to update your Email class' Send method to instantiate a Logger and call its LogEvent method:

public void Send()
   {
    //Omitted code that sends.
    var logger = new Logger();
    logger.LogEvent("Sent message", DateTime.Now);
   }

Now Email is tightly coupled to Logger. If we change the signature of that LogEvent method in Logger, we will also have to make changes to Email. Do you see how this can quickly become a nightmare when you are dealing with even a medium-sized project? Furthermore, no one wants to even try to use the LogEvent method because they know that if they need to make any sort of change to it, they will have to start changing other classes, and what should have been an afternoon's worth of work quickly turns into a week. So instead, they write a new method, or a new class, that then becomes tightly coupled to whatever else they are doing, things get bloated, and each programmer starts to get into their own little "ghetto" of their own code. This is very, very bad when you have to come in later and figure out what the hell the program is doing or hunt down a bug.

If you put some events on your Email class instead, you can loosely couple these classes:

Public Class Email
{
   public event EventHandler<EventArgs> Sent;
   private void OnSent(EventArgs e)
    {
        if (Sent!= null)
            Sent(this, e);
    }

   public string To {get;set;}
   //Omitted code

   public void Send()
   {
    //Omitted code that sends.
    OnSent(new EventArgs());//raise the event
   }
}

Now you can add an event handler to Logger and subcribe it to the Email.Sent event from just about anywhere in your application and have it do what it needs to do:

public class Logger 
{
  ...
  public void Email_OnSent(object sender, EventArgs e)
  {
    LogEvent("Message Sent", DateTime.Now);
  }

  public void LogEvent(string desc, DateTime time)
  {
    ...//some sort of logging happens here
  }
}

and elsewhere:

var logger = new Logger();
var email = new Email();

email.Sent += logger.Email_OnSent;//subscribe to the event

Now your classes are very loosely coupled, and six months down the road, when you decide that you want your Logger to capture more or different information, or even do something totally different when an email is sent, you can change the LogEvent method or the event handler without having to touch the Email class. Furthermore, other classes can also subscribe to the event without having to alter the Email class, and you can have a whole host of things happen when an email is sent.

Now maintaining your code is much easier, and other people are much more likely to reuse your code, because they know they won't have to go digging through the guts of 20 different classes just to make a change to how something is handled.

BIG EDIT: More about delegates. If you read through here: Curiosity is Bliss: C# Events vs Delegates (I'll keep links to a minimum, I promise), you see how the author gets into the fact that events are basically special types of delegates. They expect a certain method signature (i.e. (object sender, EventArgs e)), and can have more than one method added to them (+=) to be executed when the method is raised. There are other differences as well, but these are the main ones you will notice. So what good is a delegate?

Imagine you wanted to give the client of your Email class some options for how to send the mail. You could define a series of methods for this:

Public Class Email
{
   public string To {get;set;}
   //Omitted code

   public void Send(MailMethod method)
   {
     switch(method)
     {
       case MailMethod.Imap:
         ViaImap();
         break;
       case MailMethod.Pop:
         ViaPop();
         break;
      }
   }

   private void ViaImap() {...}

   private void ViaPop() {...}
}

This works well, but if you want to add more options later, you have to edit your class (as well as the MailMethod enum that is assumed here). If you declare a delegate instead, you can defer this sort of decision to the client and make your class much more flexible:

Public Class Email
{
   public Email()
   {
     Method = ViaPop;//declare the default method on instantiation
   }

   //define the delegate
   public delegate void SendMailMethod(string title, string message);

   //declare a variable of type SendMailMethod
   public SendMailMethod Method;

   public string To {get;set;}
   //Omitted code

   public void Send()
   {
     //assume title and message strings have been determined already
     Method(title, message);
   }

   public void SetToPop()
   {
     this.Method = ViaPop;
   }

   public void SetToImap()
   {
     this.Method = ViaImap;
   }

   //You can write some default methods that you forsee being needed
   private void ViaImap(string title, string message) {...}

   private void ViaPop(string title, string message) {...}
}

Now a client can use your class with its own methods or provide their own method to send mail just about however they choose:

var regularEmail = new Email();
regularEmail.SetToImap();
regularEmail.Send();

var reallySlowEmail = new Email();
reallySlowEmail.Method = ViaSnailMail;

public void ViaSnailMail(string title, string message) {...}

Now your classes are somewhat less tightly coupled and much easier to maintain (and write tests for!). There are certainly other ways to use delegates, and lambdas sort of take things up a notch, but this should suffice for a bare-bones introduction.

like image 143
Paul Griffin Avatar answered Sep 29 '22 22:09

Paul Griffin