Devo usar a lista ou simplesmente acionar para acompanhar os assinantes de um IOBServable?

StackOverflow https://stackoverflow.com/questions/4003077

Pergunta

Estou implementando o IObservable<T> Interface em algumas classes. eu usei Refletor Para descobrir como isso é normalmente feito em Rx. Sobre como um observável acompanha seus assinantes e os notifica através de seus OnNext Método, tropecei em código semelhante a este:

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

Como todos os delegados são multicast-cast, isso não poderia ser simplificado para:

Action<T> observers;

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

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

Ou existem vantagens específicas para a primeira abordagem (desempenho de desempenho, encadeamento/concorrência,…)?

Foi útil?

Solução

Em geral, chamar os delegados individualmente fornece mais controle sobre o comportamento:

  • Se um delegado aumentar uma exceção, você poderá continuar ligando para os outros, por exemplo, ou remover o delegado com falha da sua lista.
  • Se você quiser ligar para os delegados em paralelo, é realmente fácil.
  • Se você precisar ligar para eles em um determinado pedido, poderá garantir facilmente o pedido correto (não tenho certeza de que o pedido de chamadas de delegados multicast seja definido).

Outras dicas

Normalmente você não implementa IObservable<T> você mesmo, você devolve um IObservable<T> de um método usando um dos métodos de geração (como Observable.Create).

No entanto, se você for implementar a interface, você deve embrulhar um interno Subject<T> que lidará com todos os problemas de simultaneidade para você:

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: Se você decidir ficar com o delegado (por qualquer motivo), pelo menos verifique se você está cancelando inscrição em seu IDisposable valor de retorno:

observers += observer.OnNext;
return Disposable.Create(() => observers -= observer.OnNext);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top