How does the event pattern work in .NET?


Events are a simplified pattern that uses delegates. In C#, all delegates have the multicast capability, i.e., an instance of a delegate can represent not just a single method but a list of methods. For example −

Example

delegate int Transformer(int x);
static void Main(){
   Transformer perform = x =>{
      int result = x * x;
      Console.WriteLine(result);
      return result;
   };
   perform += x =>{
      int result = x * x * x;
      Console.WriteLine(result);
      return result;
   };
   perform(2); // prints 4 and 8
}

Calling Perform() calls both the methods that were added to the delegate. The methods are invoked in the order in which they were added.

This allows you to implement the publish-subscribe, also known as the event pattern. The publisher contains a delegate field. It decides when to publish by invoking the delegate. A subscriber adds its own methods to the publisher's delegate, so they get notified whenever the publisher decides to publish by invoking the delegate. A subscriber doesn't know about or interfere with other subscribers.

C# events are a language feature that formalizes the above pattern in a type-safe way that prevents common mistakes with the delegates. An event exposes a subset of delegate features needed to implement the event pattern. The following example illustrates this.

First, define the structure of the data that you want to send when the event happens.

public class ThresholdReachedEventArgs : EventArgs{
   public int Threshold { get; set; }
   public DateTime TimeReached { get; set; }
}

Then, define the Publisher, i.e. the class that wants to raise an event.

public class Counter{
   // 1. Define an event
   public event EventHandler<ThresholdReachedEventArgs> ThresholdReached;
   // 2. Do something that raises the event, and pass the EventArgs custom data
   public void DoSomething(){
      ThresholdReachedEventArgs e = new ThresholdReachedEventArgs{
         Threshold = 10,
         TimeReached = DateTime.Now
      };
      // 3. Raise the actual event
      ThresholdReached?.Invoke(this, e);
   }
}

Finally, create one or many subscribers. Classes that want to listen to an event raised by the Publisher.

class Program{
   static void Main(string[] args){
      // 1. Create an instance of the publisher, which you want to listen to
      Counter counter = new Counter();
      // 2. Attach an event handler on the publisher
      counter.ThresholdReached += OnThresholdReached;
      // 3. Do something that will raise the event. Now you are ready to listen to the event.
      counter.DoSomething();
   }
   // 4. Handle the event which is raised by publisher
   static void OnThresholdReached(object sender, ThresholdReachedEventArgs e){
      Console.WriteLine($"Reached Threshold {e.Threshold} at {e.TimeReached.ToString()}");
   }
}

Example

 Live Demo

using System;
class Program{
   static void Main(string[] args){
      // 1. Create an instance of the publisher, which you want to listen to
      Counter counter = new Counter();

      // 2. Attach an event handler on the publisher
      counter.ThresholdReached += OnThresholdReached;

      // 3. Do something that will raise the event. Now you are ready to listen to the       event.
      counter.DoSomething();
   }

   // 4. Handle the event which is raised by publisher
   static void OnThresholdReached(object sender, ThresholdReachedEventArgs e){
      Console.WriteLine($"Reached Threshold {e.Threshold} at {e.TimeReached.ToString()}");
   }
}
public class ThresholdReachedEventArgs : EventArgs{
   public int Threshold { get; set; }
   public DateTime TimeReached { get; set; }
}
public class Counter{
   // 1. Define an event
   public event EventHandler<ThresholdReachedEventArgs> ThresholdReached;
   // 2. Do something that raises the event, and pass the EventArgs custom data
   public void DoSomething(){
      ThresholdReachedEventArgs e = new ThresholdReachedEventArgs{
         Threshold = 10,
         TimeReached = DateTime.Now
      };
      // 3. Raise the actual event
      ThresholdReached?.Invoke(this, e);
   }
}

Output

Reached Threshold 10 at 5/15/2021 12:49:10 PM

Updated on: 19-May-2021

385 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements