Saturday, October 23, 2004

Events/Delegates

Have you ever wondered whats the difference between events and delegates.
Yes/no whatever, just read on....
All the documentation that I have read makes them look like pretty differnt from each other. But, but just you wait.
My question is, what you can do with events, you can easily do with delegates? Right? Confused? Think...think :)


To get started check this example,

namespace DifferenceEvDel
{
using System;
delegate void BarkHandler(string s);


class DogApplication

{
public static event BarkHandler delegate1;
public static BarkHandler event1;
static void Main(string[] args)

{
delegate1 += new BarkHandler(DogBarking);
event1 += new BarkHandler(DogBarking);
delegate1("Bow!! Bow!! used delegate");
event1("Bow!! Bow!! used event");
}

static void DogBarking(string str)
{
Console.WriteLine(str.ToString());
}
}
}
Differnt approach, same result. Now you will agree on what I said in the begining.

MSDN clearly says :
"The event keyword lets you specify a delegate that will be called upon the occurrence of some "event" in your code."

Lets check out whats new in the events, point by point:

* Event can be invoked by the class which declared it. Delegate has no such restriction. Derived classes from the class declaring the event also aren't allowed to fire the event.

namespace DifferenceEvDel

{
using System;
delegate void BarkHandler(string s);

class BlueDog
{
public static event BarkHandler event1;
public static BarkHandler delegate1;
static void Main(string[] args)

{
delegate1 += new BarkHandler(DogBarking);
event1 += new BarkHandler(DogBarking);
new BlackDog().TeaseTheDog();
Console.ReadLine();
}

static void DogBarking(string str)
{
Console.WriteLine(str.ToString());
}
}

class BlackDog
{
public void TeaseTheDog()
{
BlueDog.event1("Bow!! Bow!! used events");
//The event 'DifferenceEvDel.BlueDog.event1' can only
//appear on the left hand side of += or -=
//(except when used from within the type 'DifferenceEvDel.BlueDog')
//Comment the above line to compile
BlueDog.delegate1("Bow!! Bow!! used delegate"); // compiles fine
}
}
}
An event of BlueDog can not be invoked from BlackDog, but a delegate can be.

*Accessor specifiers

When you put an access specifier(private, public etc.) on an event it controls who can register or listen to that event. Now, how would you specify the access control for the invocation of that event? In the question lies the answer :)

There will be two access modifiers like 'public public event' which is not so intutive. So as of now Event can be invoked by the class which declared it. But there are always ways to bypass this.

*Event can be included in an interface.

This one is the most important difference from the design perspective.
Try this in the same namespace
as above

namespace DifferenceEvDel
{
interface IDog
{
//Delegate in interface, error, comment this line to compile ;)
BarkHandler delegate1; //Err: Interfaces cannot contain fields
//Event in interface, its okey, Karry on I mean Carry on

event BarkHandler event1;
}

class Dog : IDog
{
public event BarkHandler event1; // Implement the interface
static void Main(string[] args) {}
}
}

*Events have an add and remove method(like get set).You can override these, so you can find out when somebody subscribes to your event.

public event BarkHandler event1
{
add
{
Console.WriteLine("Bow!! Bow!! I got added"); msgNotifier += value;
}
remove
{
Console.WriteLine("Bow!! Bow!! I got removed"); msgNotifier -= value;
}
}

My conclusion:
"Events are nothing more then a modifier on delegate type, Like all modifiers it adds some restrictions to be enforced by the compiler.

Keep watching this space for more events on delegates.

No comments: