Event vs. Delegate
Explaining the important differences between the Event and Delegate patterns in C# and why they're useful.
Join the DZone community and get the full member experience.
Join For FreeThis post explains the basics of Events and Delegate in .NET and, most importantly, explains what is difference between both.
Both Event and Delegate is based on overserved pattern of GOF, which is based on giving notification of change in one thing (object) to all others who is interested in change. Below image is graphical interpretation of same.
Delegates
Delegate in C# is a reference type, which holds a reference to the function and invokes the function when called with an Invoke method. If one is coming from C++/C background, delegate is like a pointer to a function.
To understand delegates in a better way, take a look at the below sample code:
public class DelegateTest {
public delegate void Print(string val);
public DelegateTest() {
Print p = new Print(PrintValue);
p += new Print(PrintData);
p.Invoke("Test");
}
private void PrintData(string s) {
Console.WriteLine("PrintData" + s);
}
public void PrintValue(string s)
{
Console.WriteLine("PrintValue" + s);
}
}
When above class get invoked following output will get printed:
PrintData Test
PrintValue Test
Some key points about the above code:
- It defines Delegate, which points to a method with the void return type and takes a string as an input.
- In the constructor of a type, it creates a reference object of Delegate which points to the methods “PrintData” and “PrintValue”.
- Invokes a method of delegate, which calls both methods one by one.
Read more about Delegates here: https://msdn.microsoft.com/en-in/library/900fyy8e(v=vs.71).aspx
Events
Event in C# is a type of Delegate, which means that if one wants to use Event, then one must define delegate first. Events can have multiple event-handler functions, which have a signature like Delegate, and get called when an Event is raised by some other Event in an application. A simple example is when a button is clicked in the UI. Events are very useful to create notifications.
To understand Events in a better way, take a look at the below sample code:
public class EventTest {
public delegate void Print(string val);
public event Print PrintEvent;
public EventTest() {
this.PrintEvent += PrintData;
this.PrintEvent += PrintValue;
}
public virtual void OnPrintEvent() {
if (PrintEvent != null)
PrintEvent("Test");
}
private void PrintData(string s) {
Console.WriteLine("PrintData" + s);
}
public void PrintValue(string s)
{
Console.WriteLine("PrintValue" + s); }
}
When above class object is created and then “OnPrintEvent” method invoked following output will get printed:
PrintData Test
PrintValue Test
Some key points in the above code:
- Its creates a Delegate, which can point to a method with return type void and take a string as an argument.
- It defines Event, which is defined as a Delegate.
- In Constructor, an event holds two delegates, i.e. Event handlers. It can also be written as:
this.PrintEvent += new Print (PrintData);
this.PrintEvent += new Print (PrintValue);
- OnPrintEvent method checks that the Event is holding an Event handler function or not, if there are any Event handler(s) it calls all Event handlers.
Read more about Events: https://msdn.microsoft.com/en-in/library/8627sbea%28v=vs.71%29.aspx
Events vs. Delegates
Both Event and Delegate do the same task, which is to hold event handlers and call them when delegate or event are invoked. So we have a question: Why do you need Event in a language like C# when one can achieve the same thing with Delegate?
The answer is that Event is a wrapper on the Delegate type.
The Problem With Delegate
Let’s understand this, using the same class defined above which is “DelegateTest”.
class Program {
static void Main(string[] args) {
Program p = new Program();
DelegateTest delegateTest = new DelegateTest();
delegateTest.p = new DelegateTest.Print(p.TestString);
delegateTest.p = null; }
public void TestString(string s)
{ }
}
The above code performs the following steps:
- It creates an object of the DelegateTest type.
- Its assigns new a Delegate reference to Delegate Print and overrides the value assigned in the constructor.
- It assigns “null” to the Print Delegate and removes all added functions.
The Problem with Delegate is that one can easily override Delegate properties, and that leads to error or serious issue. That means one cannot use Delegate as a public property.
The Solution With Event
To avoid the above problem, C# uses Events, which defines wrappers around Delegates. The below code makes use of the EventTest class defined above, and PrintEvent is a wrapper around the Print Delegate.
static void Main(string[] args)
{
Program p = new Program();
EventTest eventTest = new EventTest();
//eventTest.PrintEvent = null;
//Not allowed in C#
eventTest.PrintEvent += p.TestString;
}
public void TestString(string s)
{ }
The above code performs the following steps:
- It defines the object EventTest.
- its assigns eventhandler to the PrintEvent Event of EventTest.
One cannot do this with Event:
eventTest.PrintEvent = null;//Not allowed in C#
eventTest.PrintEvent = new PrintEvent()//Not allowed in C#
So the Event type resolves the problem of exposing Delegates outside of a class by defining wrappers around Delegate. The below image is a representation of Event and Delegate.
More differences between Event and Delegate are:
- Event is very helpful to create Notification systems. The same is not possible with Delegate because Delegate cannot be exposed as public.
- Delegate is very helpful to create call back functions, i.e pass delegate as function argument, which is not possible with Event.
Conclusion
Event and Delegate both follow the Observer pattern. The difference between both is that Event wraps Delegate type, and makes Delegate not modifiable in terms of changing references, i.e. assigning a new object is not possible.
Published at DZone with permission of Pranay Rana, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments