Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use events for what I can do with Delegates?

I know Events are always associated with Delegates. But, I am missing some core use of Events, and trying to understand that.

I created a simple Event program, as below, and it works perfectly fine.

namespace CompleteRef3._0
{
delegate void someEventDelegate();

class EventTester
{
    public event someEventDelegate someEvent;

    public void doEvent()
    {
        if (someEvent != null) someEvent();
    }

}

class Program
{
    static void EventHandler1()
    {
        Console.WriteLine("Event handler 1 called..");
    }

    static void EventHandler2()
    {
        Console.WriteLine("Event handler 2 called..");
    }
    static void EventHandler3()
    {
        Console.WriteLine("Event handler 3 called..");
    }


    static void Main(string[] args)
    {
        EventTester evt = new EventTester();
        evt.someEvent += EventHandler1;
        evt.someEvent += EventHandler2;
        evt.someEvent += EventHandler3;
        evt.doEvent();
        Console.ReadKey();

    }
}
}

I replaced the event declaration with delegates. That is I replaced the line public event someEventDelegate someEvent; with someEventDelegate someEvent; on the above program, and I still get the same result. Now, I was confused why we need to use Events, if it can be achieved by Delegates only. What is the real use of Events?

The modified program without events is as below -

namespace CompleteRef3._0
{
delegate void someEventDelegate();

class EventTester
{
    someEventDelegate someEvent;

    public void doEvent()
    {
        if (someEvent != null) someEvent();
    }

}

class Program
{
    static void EventHandler1()
    {
        Console.WriteLine("Event handler 1 called..");
    }

    static void EventHandler2()
    {
        Console.WriteLine("Event handler 2 called..");
    }
    static void EventHandler3()
    {
        Console.WriteLine("Event handler 3 called..");
    }


    static void Main(string[] args)
    {
        EventTester evt = new EventTester();
        evt.someEvent += EventHandler1;
        evt.someEvent += EventHandler2;
        evt.someEvent += EventHandler3;
        evt.doEvent();
        Console.ReadKey();

    }
}
}
like image 848
Deepak Raj Avatar asked Mar 03 '13 05:03

Deepak Raj


2 Answers

Imagine you have 3 subscribers who are interested in your someEvent. Let's further imagine they are interested in receiving events from the same EventTester instance. For brevity, let's leave out the details of how the exact same instance is passed to all the clients. When I say clients, I mean any class who is a subscriber to the event.

Here is the instance:

EventTester evt = new EventTester();

They have subscribed to the event of the above instance as shown below:

Client 1

evt.someEvent += Client1Handler1;
evt.someEvent += Client1Handler2;

Client 2

evt.someEvent += Client2Handler1;

Client 3

evt.someEvent += Client3Handler1;
evt.someEvent += Client3Handler2;

Client 4:

Imagine client 4 did one of the 3 below:

// 1: See Note 1 below
evt.someEvent = null;

// 2: See Note 2 below
evt.someEvent = new someEventDelegate(MyHandler);

// 3: See Note 3 below
evt.someEvent();

//...
private void MyHandler()
{
    MessageBox.Show("Client 4");
}

Note 1

Client 1, 2, and 3 will not be getting any events anymore. Why? Because Client 4 just did this evt.someEvent = null; and in EventTester you have this line of code:

if (someEvent != null) someEvent();

Since that condition will not pass anymore, no event will be raised. There is nothing wrong with the above line of code by the way. But there is the problem with using delegates: It can be assigned to.

Note 2

It has been completely over-written to a brand new instance. Now regardless of the client, they will all see a message box that says "Client 4".

Note 3

Ooops all of a sudden one of the clients is broadcasting the event.


Imagine for a second EventTester was a Button and someEvent was Click. Imagine you had multiple clients interested in the click event of this button. All of a sudden, one client decides no-one else should get notifications (Note 1). Or one client decides that when the button is clicked, it will be handled only 1 way (Note 2). Or it has made the decision that it will decide when a button is clicked even though the button may not have been clicked (Note 3).


If you have an event and one of the clients tried the above, they will not be allowed and get a compile error, like this:

enter image description here

like image 81
CodingYoshi Avatar answered Sep 17 '22 08:09

CodingYoshi


Sure, you can use delegates because behind the scenes an event is a construct that wraps a delegate.

But the rationale of using events instead of delegates is the the same as for using properties instead of fields - data encapsulation. It's bad practice to expose fields (whatever they are - primitive fields or delegates) directly.

By the way, you missed a public keyword before your delegate field to make it possible in the second snippet.

Another "by the way" with the second snippet: for delegates you should use Delegate.Combine instead of "+=".

like image 25
serge.karalenka Avatar answered Sep 19 '22 08:09

serge.karalenka