Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Event vs EventHandler

I read a lot of materials but I still did not understand, can someone explain me, please?

What do I know:

Declare an event:

public event MyEvent myEvent;

Vs.

declare EventHandler:

public EventHandler MyEventHandler;

While EventHandler is a keyword in .NET:

public delegate void EventHandler (Send object, EventArgs e);

So, EventHandler is a delegate and not an event, since it is not used in the keyword 'event'?

And when should I use 'Event' and when 'EventHandler'?

like image 897
BIBI Avatar asked Oct 19 '17 07:10

BIBI


2 Answers

Exposing a (public) field

 public EventHandler MyEventHandler;

is a bad practice: one can easily ruin the code with a small typo:

 MyClass demo = new MyClass();

 demo.MyEventHandler += MyMethod;

 ...

 // Can you see the error? = instead of correct += ?
 // MyMethod will not be called since this assignment 
 demo.MyEventHandler = MyReaction;  

That's why you should use event which has been specially desinged for this

 public event EventHandler MyEventHandler;

if we try the previous demo we'll get compile time error:

 MyClass demo = new MyClass();

 ...

 demo.MyEventHandler = MyReaction; // <- doesn't compile, insist on +=

In very rare cases you may want explicit delegate-based fields, but these field should be concealed, say, be private, not public:

// We don't expose the field
private EventHandler m_MyEventHandler;

// ... But event:
public event EventHandler MyEventHandler {
  add {
    //TODO: extra logic on += operation

    m_MyEventHandler += value;
  }
  remove {
    //TODO: extra logic on -= operation

    m_MyEventHandler -= value;
  }  
} 
like image 136
Dmitry Bychenko Avatar answered Sep 23 '22 18:09

Dmitry Bychenko


Ah, the event vs. delegate question. I remember having that question as well...

So, suppose you're making a class called "Cat" and you want to let people know when your cat is hungry. You could do that in one of two ways: by exposing a delegate on the Cat class or by exposing an event.

You can think of a delegate as a pointer to a function (or method). So let's say there's a class called "Person" that has a method called FeedCat(Cat cat).

The delegate way


If your cat is exposing a delegate called HungryDelegate, the person can point the delegate to their FeedCat method, so that when the cat is hungry, it has a way to call the FeedCat method on the person.

The problem here is, only one person can feed the cat. Suppose you want multiple people to be able to feed the cat. People can be busy doing other things, so it's important for the cat to be able to tell multiple people that it's hungry. That way, people get notified of this, and they can check up on the cat when they have a chance, see if someone already fed the cat, and feed it if not.

Events to the rescue:


An event is basically a list of delegates (of a certain type). If you expose a Hungry event on your "Cat" class, multiple people can ADD pointers (delegates) to their FeedCat methods.

They can also remove the pointers (delegates) to their FeedCat methods if they like. Let's say a person moved out, and their sister is now taking care of the cat. The person can remove their delegate for their own FeedCat function from the cat, so that they no longer get notified that the darn cat is hungry.

Events vs. multicast delegates?


Technically, in order to be able to provide multiple delegates, you could use the so called MultiCastDelegates instead of events. They are composite delegates (a linked list or delegates). The problem there is, everyone can mess with them from the outside. An evil person could remove everyone else's "FeedCat" delegates, and the poor cat would starve (or would have to learn to hunt).

The important thing when using events is that the person cannot see other people's delegates that are added to the event, and it can't remove them or interact with them (in principle).

like image 31
anakic Avatar answered Sep 23 '22 18:09

anakic