Events in C# are a powerful mechanism for implementing the observer pattern, enabling a class (publisher) to notify other classes (subscribers) about changes or actions.
Events allows to build interactive and dynamic applications by providing a way to respond to user actions, data changes, or system states.
Core Concepts
- Delegate:
- Events are based on delegates.
- A delegate is a type-safe function pointer that defines the method signature for event handlers.
- The event can only invoke methods with the same signature as the associated delegate.
- Publisher:
- A class that defines the event and is responsible for triggering it when an action occurs.
- Subscriber:
- A class that listens to the event and defines the method(s) to handle it.
- Event:
- It is a wrapper around a delegate that restricts the direct invocation of the delegate.
- Only the class that declares the event can raise it.
Defining and Using Events
Here’s a step-by-step breakdown:
1. Define a Delegate
public delegate void Notify(); // Delegate definition
2. Declare an Event in the Publisher Class
public class Publisher
{
public event Notify OnNotify; // Event based on the delegate
public void TriggerEvent()
{
if (OnNotify != null) // Check if there are any subscribers
{
OnNotify(); // Raise the event
}
}
}
3. Subscribe to the Event
public class Subscriber
{
public void HandleEvent()
{
Console.WriteLine("Event received and handled.");
}
}
4. Link Publisher and Subscriber
class Program
{
static void Main()
{
Publisher publisher = new Publisher();
Subscriber subscriber = new Subscriber();
// Subscribe to the event
publisher.OnNotify += subscriber.HandleEvent;
// Trigger the event
publisher.TriggerEvent();
}
}
Output:
Event received and handled.
Key Points About Events
- Encapsulation:
- Only the class that declares an event can trigger it. This ensures encapsulation.
- The
event
keyword restricts direct manipulation of the delegate by external classes.
- Multicast:
- Events support multiple subscribers. All subscribed methods are invoked in the order of subscription.
- Thread Safety:
- Use thread-safe techniques (e.g.,
Interlocked.CompareExchange
) to manage event subscriptions in multi-threaded environments.
- Use thread-safe techniques (e.g.,
Common EventHandler Pattern
C# provides the EventHandler
and EventHandler<T>
delegates for standardized event handling.
Using EventHandler
public class Publisher
{
public event EventHandler OnNotify;
public void TriggerEvent()
{
OnNotify?.Invoke(this, EventArgs.Empty);
}
}
public class Subscriber
{
public void HandleEvent(object sender, EventArgs e)
{
Console.WriteLine("Event received and handled.");
}
}
Advantages of Using Events
- Decoupling:
- Events decouple publishers and subscribers, making the system more modular and easier to maintain.
- Reusability:
- Subscribers can reuse event handlers for different publishers.
- Flexibility:
- Any number of subscribers can listen to the same event, providing great flexibility.
Real-World Examples
- UI Controls: Button clicks (
Button.Click
event in Windows Forms/WPF). - Data Changes: Notifications when data in a database changes.
- Custom Notifications: Implementing event-driven architecture in business logic.