Должен ли я использовать List <IObserver>или просто Action <T>для отслеживания подписчиков IObservable? - PullRequest
3 голосов
/ 23 октября 2010

Я реализую интерфейс IObservable<T> в некоторых классах.Я использовал Reflector , чтобы выяснить, как это обычно делается в Rx .Относительно того, как наблюдаемая отслеживает своих подписчиков и уведомляет их с помощью их метода OnNext, я наткнулся на код, подобный следующему:

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);
}

Поскольку все делегаты являются многоадресными, это нельзя упроститьto:

Action<T> observers;

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

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

Или есть ли определенные преимущества у первого подхода (производительность, проблемы многопоточности / параллелизма,…)?

Ответы [ 2 ]

5 голосов
/ 23 октября 2010

Как правило, индивидуальный вызов делегатов дает вам больший контроль над поведением:

  • Если один делегат вызывает исключение, вы можете продолжать вызывать других, например, или удалить неисправного делегата из вашего.list.
  • Если вы хотите вызвать делегатов параллельно, это действительно просто.
  • Если вам нужно вызвать их в определенном порядке, вы можете легко гарантировать правильный порядок (яне уверен, что порядок вызовов делегатов многоадресной рассылки определен).
4 голосов
/ 25 октября 2010

Обычно вы не реализуете IObservable<T> самостоятельно, вы возвращаете IObservable<T> из метода, используя один из методов генерации (например, Observable.Create).

Однако, если вы собираетесь реализовать интерфейс самостоятельно, вам следует обернуть внутренний Subject<T>, который будет обрабатывать все проблемы параллелизма для вас:

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: Если вы решили остаться с делегатом (по какой-либо причине), по крайней мере, убедитесь, что вы отменили подписку в возвращаемом значении IDisposable:

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