IObservable<T>.Subscribeのオーバーロードの1つは
public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext)
内部的には、これによりAnoymousObserver<T>
IObservableにが作成および登録されます。渡された例外を再スローする単純なラムダである未指定のonError
パラメーターが設定されます。Stubs.Throw
内部的には、IObservableのオブザーバーはすべて、タイプObserverの単一のインスタンスに含まれています。これはのコードですObserver<T>.OnError
public void OnError(Exception error)
{
foreach (var observer in _observers.Data)
observer.OnError(error);
}
Stubs.Throwは例外をスローするため、そのオブザーバーのOnErrorからの例外は、foreachループと_observers.Data内の他のオブザーバーを通過します。OnErrorが呼び出されることはありません。例外自体はRx内のどこかに飲み込まれます。
Observer <T> .OnErrorはobserver.OnErrorをtry-catchでラップするか、Stubs.Throwは例外をスローする代わりに飲み込む必要があるように思われます。onErrorパラメーターを渡さないことにより、IObservable.Subscribeのユーザーは、そのサブスクライブに対してのみエラーが無視されることを望んでいます。独自のonErrorコールバックで登録された他のサブスクライバーは影響を受けないはずです。
(私はすでにCodeplexにバグを報告しましたが、トラッカーは見捨てられているように見えるので、これを正しく理解しているかどうかを確認するためにSOにも依頼したいと思いました。)
更新:アスティの答えは正しいです。リンクされたバグレポートに関する議論で、davedevはIEnumerableとの類似性を示し、例外を未処理でスローするデフォルトが、catchブロックなしでIEnumerableを反復するデフォルトと同等である方法を示しました。
オブザーバブルが特定の例外を致命的と見なすべきではないと判断した場合、OnErrorを使用してこれを伝達するべきではありません。OnErrorを呼び出すと、そもそもobservableに重大な問題が発生したことを意味するため、OnErrorが実行される保証はありません。代わりに、observableはIObservable < Either <T、Exception >>として定義できます( Observable2.Retryでの使用例)。