Observer Pattern In C#

Abstract

This is a tutorial article on the Observer pattern in C#. We first present the Classic Observer pattern which is one of the GoF patterns. Observe pattern is integrated into C# via the usage of Event mechanism and that is discussed next. The intended audience is Intermediate C# programmers and above.

Introduction

This is a tutorial article on the Observer pattern in C#. The intended audience is Intermediate C# programmers and above. We first present the Classic Observer pattern which is one of GoF patterns and is often mentioned in literature.

Modern language like C# has integrated Event mechanism, via which has practically integrated Observer pattern into language mechanisms. Modern usage of Observer pattern in C# is practically related to the usage of Event mechanism and Classic Observe pattern is made obsolete in C#.

The fact that the Event mechanism, in reality, provides Synchronous calls is often overlooked and not enough emphasized. Programmers often have the illusion of parallelism, which is not reality and is an important issue in today’s multi-core-processors world.

Code presented is tutorial, demo-of-concept level and for brevity does not handle or show all variants/problematic issues.

Classic Observer Pattern

Observe pattern, sometimes called Subject-Observe pattern, defines a one-to-many dependency between objects, so that when one object (Subject) changes its state, all its dependent objects (Observes) are notified and updated. We say that Observer “subscribes” with Subject to get notified of Subject’s state change. In simple words, one component (Subject) notifies other components (Observers) that state changed.

While in C# is already integrated Event keyword, that is the implementation of the Observer pattern, one can still decide to roll out his own version/implementation. Here is what Classic Observer, as described in GoF literature looks like.

Class diagram

Implementation code sample,

public class Args {}
public abstract class ASubject {
    protected List < IObserver > observersList = new List < IObserver > ();
    public void AddObserver(IObserver observer) {
        observersList.Add(observer);
    }
    public void RemoveObserver(IObserver observer) {
        observersList.Remove(observer);
    }
}
public interface IObserver {
    void Update(object subject, Args args);
}
public class Subject: ASubject {
    public string SubjectState = null;
    public void NotifyObservers() {
        ArgsSubject args = new ArgsSubject();
        args.SubjectState = this.SubjectState;
        foreach(IObserver o in observersList) {
            o.Update(this, args);
        }
    }
}
public class Observer: IObserver {
    private string name;
    private string observerState;
    public Observer(string name) {
        this.name = name;
    }
    public void Update(object s, Args args) {
        observerState = ((ArgsSubject) args).SubjectState;
        Console.WriteLine("Observer {0}'s new state is {1}", name, observerState);
    }
}
public class ArgsSubject: Args {
    public string SubjectState = null;
}
class Client {
    public static void Main(string[] args) {
        Subject s = new Subject();
        s.AddObserver(new Observer("1"));
        s.AddObserver(new Observer("2"));
        s.AddObserver(new Observer("3"));
        // Change subject state and notify observers
        s.SubjectState = "ABC123";
        s.NotifyObservers();
        Console.ReadLine();
    }
}

Sample execution

Modern Observer Pattern in C# -Events

C# has already integrated Event keyword, which is implementation of Observer pattern. C# is bringing it’s own terminology:

  • Subject -> Event
  • Observer -> EventHandler (more precisely, Observer.Notify() method is mapped to EventHandler method, Observer object itself is considered obsolete)
  • SubjectStateInfo -> EventArgs (more precisely SubjectStateInfo is mapped to attribute of class inherited from EventArgs)
  • AddObserver() metod -> operator +=
  • RemoveObserver() method -> operator -=

C# literature advice of using of EvenHandler delegates of certain signature, with parameters (this, EventArgs), but nothing in C# language prevents one to use a signature he likes.

Here is the class diagram of the new solution:

And here is the code,

public class Subject {
    public event EventHandler < EventArgsSubject > SubjectEvent;
    public string SubjectState;
    public void NotifyObservers() {
        EventArgsSubject args = new EventArgsSubject();
        args.SubjectState = this.SubjectState;
        // (1) 
        if (SubjectEvent != null) {
            SubjectEvent(this, args);
        }
    }
}
public class Observer {
    private string name;
    private string observerState;
    public Observer(string name) {
        this.name = name;
    }
    public void Update(object subject, EventArgsSubject args) {
        observerState = args.SubjectState;
        Console.WriteLine("Observer {0}'s new state is {1}", name, observerState);
    }
}
public class EventArgsSubject: EventArgs {
    public string SubjectState = null;
}
class Client {
    public static void Main(string[] args) {
        Subject s = new Subject();
        s.SubjectEvent += (new Observer("1")).Update;
        s.SubjectEvent += (new Observer("2")).Update;
        s.SubjectEvent += (new Observer("3")).Update;
        // Change subject state and notify observers
        s.SubjectState = "ABC123";
        s.NotifyObservers();
        Console.ReadLine();
    }
}

And here is a sample execution,

Let us mention that in (1) we used a method popular in literature. But, theoretically speaking, a “thread race” condition is possible, between the time SubjectEvent is checked for null, and events are invoked, some other thread can remove handlers from the SubjectEvent, which would result in a null reference exception. A more popular way to write invocation of handlers today is:

SubjectEvent?.Invoke(this, args);

The event mechanism provides Synchronously calls on a single thread

What needs to be emphasized, is that in a calls

if (SubjectEvent != null) {
    SubjectEvent(this, args);
}
//or
SubjectEvent?.Invoke(this, args);

subscribed EventHandlers are being invoked Synchronously on a single thread. That has some not so obvious consequences:

  • EventHandlers are executed in sequence, one after another, in the order they are subscribed to the event.
  • That means that objects/values in earlier subscribed EventHandler are updated earlier than in other EventHandlers, which might have consequences for program logic
  • Call to certain EventHandler blocks the thread until all work in that EventHandler is completed
  • If Exception is thrown in a certain EventHandler, all EventHandlers subscribed after that one will not be executed

Conclusion

The observer pattern is a very important pattern and has been directly supported by C# language by the usage of Events. Though threading issues can be tricky, the programmer must have a good understanding of how the Notification mechanism works from a threading prospective.


Similar Articles