Dovrei usare List o semplicemente Azione per tenere traccia degli abbonati di un IObservable?

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

Domanda

sto implementando l'interfaccia IObservable<T> in alcune classi. Ho usato Reflector di capire come questo è in genere fatto in Rx . Per quanto riguarda il modo un'osservabile registra i suoi abbonati e li avvisa tramite il loro metodo OnNext, sono incappato in codice simile a questo:

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

Dal momento che tutti i delegati sono multi-cast, non potrebbe questo essere semplificata in:

Action<T> observers;

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

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

O ci sono vantaggi specifici per il primo approccio (prestazioni, problemi di threading / concorrenza, ...)?

È stato utile?

Soluzione

In generale, chiamando i delegati vi dà individualmente maggiore controllo sul comportamento:

  • Se un delegato solleva un'eccezione è possibile mantenere chiamando gli altri, per esempio, o rimuovere il delegato in errore dalla vostra lista.
  • Se si desidera chiamare i delegati in parallelo, è davvero facile.
  • Se avete bisogno di chiamarli in un certo ordine, si può facilmente garantire l'ordine corretto (non sono sicuro che l'ordine delle chiamate delegato multicast è definito).

Altri suggerimenti

Di solito non implementare IObservable<T> voi stessi, restituire un IObservable<T> da un metodo utilizzando uno dei metodi di generazione (come Observable.Create).

Tuttavia, se avete intenzione di implementare l'interfaccia da soli, si dovrebbe avvolgere un Subject<T> interna che gestirà tutti i problemi di concorrenza per voi:

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 si decide di attaccare con il delegato (per qualsiasi motivo), almeno assicurarsi che si sta annullamento dell'iscrizione nel valore di ritorno IDisposable:

observers += observer.OnNext;
return Disposable.Create(() => observers -= observer.OnNext);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top