1

IObservable.Do() has overload with OnError handler but exception is propagated to Subscribe() call, but if OnError is specified in Subscribe - exception is not propagated to the caller - here is the simple example:

    public static void Main()
    {
        OnErrorInDo(); // throws
        OnErrorInSubscribe(); // doesn't throw
    }        
    public void OnErrorInDo()
    {
        var observableThatThrows = GetEnumerableThatThrows().ToObservable();
        var res = observableThatThrows.Do(i => Console.Write("{0}, ", i), LogEx).Subscribe();
    }
    public void OnErrorInSubscribe()
    {
        var observableThatThrows = GetEnumerableThatThrows().ToObservable();
        var res = observableThatThrows.Do(i => Console.Write("{0}, ", i), LogEx)
            .Subscribe(i=>{}, LogEx);
    }

    public IEnumerable<int> GetEnumerableThatThrows()
    {
        foreach (var i in Enumerable.Range(0,10))
        {
            if (i != 5)
                yield return i;
            else
                throw new Exception("ex in enumerable"); 
        }
    }
    public void LogEx(Exception ex)
    {
        Console.WriteLine("Ex message:" + ex.Message);
    } 
arena-ru
  • 990
  • 2
  • 12
  • 25

1 Answers1

1

The short answer to the question is: Do monitors notifications; Subscribe handles them.

The actual reason one throws and not the other is that the default OnError handler for calls to Subscribe that do not provide one is to throw the exception. As such, the first method will throw, regardless of the presence of Do and the second will not because of the OnError handlers passed to Subscribe.

Do is provided as a teeing operator which allows you to do some processing with the notification before it is observed by subscribers or sent down the pipeline of operators. Its most common uses are for debugging or logging. Aside from the side-effects of the methods passed to Do, you should see no difference between the behavior of the system with or without Do.

If you have:

obs.Do(i => { /* ... */ }, ex => { /* ... */ }).Subscribe(...);

and

obs.Subscribe(...);

You will see the same series of notifications into the methods passed to Subscribe. If Do did not pass the exceptions on, it would be modifying the stream of notifications, which it is counter to the design of that operator.

Gideon Engelberth
  • 6,095
  • 1
  • 21
  • 22
  • Thanks for clarifications. Could you comment on this question http://stackoverflow.com/q/13310865/296494 plz, if I understood correctly `.Do()` chain is not the best option there. – arena-ru Nov 12 '12 at 07:59