techmore.in

C# - Events

In C#, events are a way for a class to notify other classes or objects when something happens. They are typically used in scenarios where one class needs to react to an action performed by another class, following the publisher-subscriber model. Events are built on delegates and provide a mechanism for communication between objects in a decoupled way.

Key Features of Events:

  1. Encapsulation of Delegates: Events encapsulate delegates, restricting the way they can be accessed and invoked.
  2. Publisher-Subscriber Model: The class that raises the event is called the "publisher," and the classes that handle the event are called "subscribers."
  3. Delegates as Event Handlers: When an event is raised, the methods subscribed to the event (called event handlers) are invoked.
  4. Multicast: Multiple methods can subscribe to the same event.

Syntax:

  • Declaring an Event: An event is declared using the event keyword followed by a delegate type.
  • Raising an Event: The event is raised by the publisher class when a specific action occurs.

Example:

  1. Defining a Delegate Type for the Event:

    csharp
    public delegate void Notify(); // Delegate type
  2. Defining a Publisher Class:

    csharp
    public class Publisher { // Declare an event of delegate type Notify public event Notify OnProcessCompleted; // Method to trigger the event public void Process() { Console.WriteLine("Process Started..."); // After some processing, raise the event OnProcessCompleted?.Invoke(); // Safe invocation using null conditional operator Console.WriteLine("Process Completed."); } }
  3. Subscribing to an Event (in Subscriber Class):

    csharp
    public class Subscriber { public void Subscribe(Publisher publisher) { // Subscribe the method to the event publisher.OnProcessCompleted += EventHandler; } // This method will be called when the event is raised void EventHandler() { Console.WriteLine("Subscriber received the ProcessCompleted event."); } }
  4. Using the Event:

    csharp
    class Program { static void Main() { Publisher publisher = new Publisher(); Subscriber subscriber = new Subscriber(); // Subscribe to the event subscriber.Subscribe(publisher); // Trigger the process, which will raise the event publisher.Process(); } }

Output:

arduino
Process Started... Subscriber received the ProcessCompleted event. Process Completed.

Event with EventArgs:

To provide more information when an event is raised, events often use the EventHandler delegate or a custom delegate with a parameter of type EventArgs.

Example of Event with EventArgs:

  1. Defining Custom EventArgs:

    csharp
    public class ProcessEventArgs : EventArgs { public string Message { get; } public ProcessEventArgs(string message) { Message = message; } }
  2. Defining an Event with EventArgs:

    csharp
    public class Publisher { public event EventHandler<ProcessEventArgs> OnProcessCompleted; public void Process() { Console.WriteLine("Process Started..."); // Raise the event with custom event args OnProcessCompleted?.Invoke(this, new ProcessEventArgs("Process completed successfully")); Console.WriteLine("Process Completed."); } }
  3. Subscribing to the Event:

    csharp
    public class Subscriber { public void Subscribe(Publisher publisher) { publisher.OnProcessCompleted += EventHandler; } // Event handler that takes sender and EventArgs void EventHandler(object sender, ProcessEventArgs e) { Console.WriteLine($"Subscriber received the event: {e.Message}"); } }
  4. Using the Event with EventArgs:

    csharp
    class Program { static void Main() { Publisher publisher = new Publisher(); Subscriber subscriber = new Subscriber(); // Subscribe to the event subscriber.Subscribe(publisher); // Trigger the process publisher.Process(); } }

Output:

arduino
Process Started... Subscriber received the event: Process completed successfully Process Completed.

Key Points:

  • Delegates and Events: Events are based on delegates, but they provide a more restricted interface, as events can only be triggered by the class that declares them.
  • Multicasting: Multiple subscribers can handle the same event.
  • EventArgs: You can pass additional data to event handlers using EventArgs or a derived class.
  • Null Conditional Operator: When raising an event, use ?.Invoke to ensure that the event has subscribers before calling it.