C# - Events
Table of Content:
Events enable a class or object to notify other classes or objects when something of interest occurs. The class that sends (or raises) the event is called the publisher and the classes that receive (or handle) the event are called subscribers.
Events Overview
Events have the following properties:
-
The publisher determines when an event is raised; the subscribers determine what action is taken in response to the event.
An event can have multiple subscribers. A subscriber can handle multiple events from multiple publishers.
Events that have no subscribers are never raised.
Events are typically used to signal user actions such as button clicks or menu selections in graphical user interfaces.
When an event has multiple subscribers, the event handlers are invoked synchronously when an event is raised. To invoke events asynchronously, see Calling Synchronous Methods Asynchronously.
In the .NET class library, events are based on the EventHandler delegate and the EventArgs base class.
In C#, an event is a way for a class to provide notifications to clients of that class when some interesting thing happens to an object. Events are an implementation of the observer design pattern and are commonly used in user interface programming, where various elements of the UI need to respond to user actions such as clicks, key presses, etc.
Key Concepts of Events in C#
-
Delegate: A type that represents references to methods with a specific parameter list and return type. Delegates are required for defining events.
Learn Delegate -
Event: A member of a class that enables a class or object to notify other classes or objects when something of interest occurs. Events are based on delegates.
-
Event Handler: A method that is called (or "handles") when an event occurs.
Defining an Event
To define an event in C#, you first need to define a delegate that specifies the signature of the event handler methods. Then, you define the event based on that delegate.
Here’s a simple example:
using System; public class Publisher { // Define a delegate public delegate void NotifyEventHandler(object sender, EventArgs e); // Define an event based on the delegate public event NotifyEventHandler Notify; // Method to raise the event public void DoSomething() { Console.WriteLine("Doing something..."); // Check if there are any subscribers before raising the event Notify?.Invoke(this, EventArgs.Empty); } } public class Subscriber { public void OnNotified(object sender, EventArgs e) { Console.WriteLine("Subscriber received notification."); } } public class Program { public static void Main(string[] args) { Publisher publisher = new Publisher(); Subscriber subscriber = new Subscriber(); // Subscribe to the event publisher.Notify += subscriber.OnNotified; // Trigger the event publisher.DoSomething(); } }
Explanation
-
Define a Delegate:This delegate specifies that event handler methods will take an
object(the sender) andEventArgs(event data) as parameters. - Define an Event:This defines an event named
Notifythat is based on theNotifyEventHandlerdelegate. - Raise the Event:The
DoSomethingmethod raises theNotifyevent using theInvokemethod, which calls all the event handler methods subscribed to the event. The?.operator ensures that the event is only raised if there are subscribers. - Subscribe to the Event:The
+=operator is used to subscribe theOnNotifiedmethod of theSubscriberclass to theNotifyevent of thePublisherclass. - Event Handler Method:This method matches the signature of the
NotifyEventHandlerdelegate and is called when theNotifyevent is raised.
public delegate void NotifyEventHandler(object sender, EventArgs e);
public event NotifyEventHandler Notify;
public void DoSomething() { Console.WriteLine("Doing something..."); Notify?.Invoke(this, EventArgs.Empty); }
publisher.Notify += subscriber.OnNotified;
public void OnNotified(object sender, EventArgs e) { Console.WriteLine("Subscriber received notification."); }
Benefits of Using Events
- Encapsulation: Events provide a way for a class to notify other classes or objects when something of interest happens, without those other classes needing to tightly couple to the notifying class.
- Decoupling: The publisher class doesn't need to know which classes are subscribed to its events; it simply raises the event. This makes the system more modular and flexible.
- Reusability: Classes that define events can be reused in different contexts without requiring changes to their internal logic.
Events are a powerful feature in C# that facilitate communication between objects in a loosely coupled manner, making your code more maintainable and flexible.