Should I use List<IObserver> or simply Action<T> to keep track of an IObservable's subscribers?

故事扮演 提交于 2020-01-02 08:30:14

问题


I'm implementing the IObservable<T> interface on some classes. I used Reflector to figure out how this is typically done in Rx. Concerning how an observable keeps track of its subscribers and notifies them via their OnNext method, I stumbled upon code similar to this:

private List<Observer<T>> observers;

// subscribe a new observer:
public IDisposable Subscribe(IObserver<T> observer)
{
    observers.Add(observer);
    ...
}

// trigger all observers' OnNext method:
...
foreach (IObserver<T> observer in observers)
{
    observer.OnNext(value);
}

Since all delegates are multi-cast, couldn't this be simplified to:

Action<T> observers;

// subscribe observer:
public IDisposable Subscribe(IObserver<T> observer)
{
    observers += observer.OnNext;
    ...
}

// trigger observers' OnNext:
...
observers(value);

Or are there specific advantages to the first approach (performance, threading/concurrency issues, …)?


回答1:


In general, calling the delegates individually gives you more control over the behavior:

  • If one delegate raises an exception you can keep calling the others, for example, or remove the faulted delegate from your list.
  • If you want to call the delegates in parallel, it's really easy.
  • If you need to call them in a certain order, you can easily guarantee the correct order (I'm not sure that the order of multicast delegate calls is defined).



回答2:


Usually you don't implement IObservable<T> yourself, you return an IObservable<T> from a method using one of the generation methods (like Observable.Create).

However, if you are going to implement the interface yourself, you should wrap an internal Subject<T> which will handle all the concurrency issues for you:

public class CustomObservable<T> : IObservable<T>
{
    private Subject<T> subject = new Subject<T>();

    public IDisposable Subscribe(IObserver<T> observer)
    {
        return subject.Subscribe(observer);
    }

    private void EmitValue(T value)
    {
        subject.OnNext(value);
    }
}

NB: If you decide to stick with the delegate (for whatever reason), at least make sure you are unsubscribing in your IDisposable return value:

observers += observer.OnNext;
return Disposable.Create(() => observers -= observer.OnNext);


来源:https://stackoverflow.com/questions/4003077/should-i-use-listiobserver-or-simply-actiont-to-keep-track-of-an-iobservable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!