Switch to a different IObservable if the first is empty
.net, c#, system.reactive
Solution
The accepted answer is undesirable in my opinion because it uses `Subject`, `Do`, and still subscribes to the second sequence when the first isn't empty. The latter can be a big problem if the second observable invokes anything nontrivial. I came up with the following solution instead:
public static IObservable<T> SwitchIfEmpty<T>(this IObservable<T> @this, IObservable<T> switchTo)
{
if (@this == null) throw new ArgumentNullException(nameof(@this));
if (switchTo == null) throw new ArgumentNullException(nameof(switchTo));
return Observable.Create<T>(obs =>
{
var source = @this.Replay(1);
var switched = source.Any().SelectMany(any => any ? Observable.Empty<T>() : switchTo);
return new CompositeDisposable(source.Concat(switched).Subscribe(obs), source.Connect());
});
}
The name `SwitchIfEmpty` falls in line with the existing RxJava implementation. Here is an ongoing discussion about incorporating some of the RxJava operators into RxNET.
I'm sure a custom `IObservable` implementation would be much more efficient than mine. You can find one here written by ReactiveX member akarnokd. It's also available on NuGet.
Problem
I'm writing a function that retrieves news about a subject and feeds this news back via an IObservable return value. However, I have several news sources. I don't want to use `Merge` to combine together these sources into one. Instead, what I'd like to do is order them by priority -- - When my function gets called, the first news source is queried (which produces an IObservable representing that source). - If that news source's IObservable completes without returning any results, the next news source is queried. - If that second source completes without returning results, the final news source is queried. - This whole behavior is wrapped up into an observable I can return to the user. Is this sort of behavior something I can accomplish using built-in Rx extension methods, or do I need to implement a custom class to handle this? How would I approach doing either?