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

  1. 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.
  2. Publisher:
    • A class that defines the event and is responsible for triggering it when an action occurs.
  3. Subscriber:
    • A class that listens to the event and defines the method(s) to handle it.
  4. 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

  1. 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.
  2. Multicast:
    • Events support multiple subscribers. All subscribed methods are invoked in the order of subscription.
  3. Thread Safety:
    • Use thread-safe techniques (e.g., Interlocked.CompareExchange) to manage event subscriptions in multi-threaded environments.

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

  1. Decoupling:
    • Events decouple publishers and subscribers, making the system more modular and easier to maintain.
  2. Reusability:
    • Subscribers can reuse event handlers for different publishers.
  3. Flexibility:
    • Any number of subscribers can listen to the same event, providing great flexibility.

Real-World Examples

  1. UI Controls: Button clicks (Button.Click event in Windows Forms/WPF).
  2. Data Changes: Notifications when data in a database changes.
  3. Custom Notifications: Implementing event-driven architecture in business logic.

By davs