HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Observer pattern implementation in C#

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
observerimplementationpattern

Problem

In order to implement the Observer pattern in C#, one of the ways to go (at least, the one I chose) is to make classes that implement the IObservable for the observable objects and the IObserver for the observers.

In a project of mine I created a base class from which every observable inherits:

public class Observable : IObservable
{
    private SubscriptionManager _subscriptionManager;

    public Observable()
    {
        _subscriptionManager = new SubscriptionManager(
            new List>());
    }

    public IDisposable Subscribe(IObserver observer)
    {
        _subscriptionManager.Subscribe(observer);

        return _subscriptionManager;
    }

    public void Notify(T obj)
    {
        _subscriptionManager.Notify(obj);
    }
}


and an IDisposable class that manages the subscriptions to the observable object:

public class SubscriptionManager : IDisposable
{
    private ICollection> _observers;
    private IObserver _observer;

    public SubscriptionManager(ICollection> observers)
    {
        if (observers == null)
        {
            throw new ArgumentNullException("observers");
        }

        _observers = observers;
    }

    public void Subscribe(IObserver observer)
    {
        _observers.Add(observer);
        _observer = observer;
    }

    public void Notify(T obj)
    {
        foreach (var observer in _observers)
        {
            observer.OnNext(obj);
        }
    }

    public void Dispose()
    {
        _observers.Remove(_observer);
    }
}


Do you see anything that can be done more efficiently, or in a better way? Do you see anything else that may be wrong?

Solution

Here's a problem:

var o = new Observable();
var a = o.Subscribe(_ => Console.WriteLine("A"));
var b = o.Subscribe(_ => Console.WriteLine("B"));
a.Dispose();
o.Notify(Unit.Default);


This prints

A


Disposing of a removed the wrong observer.

I'd recommend reading Why shouldn't I implement IObservable?


The reason you shouldn't implement IObservable is the same reason
you don't usually implement IEnumerable, is that somebody has most
likely already built the thing you want.

Code Snippets

var o = new Observable<Unit>();
var a = o.Subscribe(_ => Console.WriteLine("A"));
var b = o.Subscribe(_ => Console.WriteLine("B"));
a.Dispose();
o.Notify(Unit.Default);

Context

StackExchange Code Review Q#107704, answer score: 4

Revisions (0)

No revisions yet.