6

Does anyone know of an appropriate replacement for this handmade if/then/else operator for reactive extensions (.Net / C#)?

public static IObservable<TResult> If<TSource, TResult>(
  this IObservable<TSource> source,
  Func<TSource, bool> predicate,
  Func<TSource, IObservable<TResult>> thenSource,
  Func<TSource, IObservable<TResult>> elseSource) 
{
  return source
    .SelectMany(
      value => predicate(value)
        ? thenSource(value)
        : elseSource(value));
}

Usage example (assuming numbers is of type IObservable<int>:

numbers.If(
  predicate: i => i % 2 == 0,
  thenSource: i => Observable
    .Return(i)
    .Do(_ => { /* some side effects */ })
    .Delay(TimeSpan.FromSeconds(1)), // some other operations
  elseSource: i => Observable
    .Return(i)
    .Do(_ => { /* some other side effects */ }));
Daniel Müller
  • 434
  • 4
  • 12
  • Like this? https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/if.md ... opps, that's JS sorry, rather than C#. –  Apr 11 '17 at 13:31
  • Here's the C# version: https://github.com/Reactive-Extensions/Rx.NET/blob/develop/Rx.NET/Source/src/System.Reactive/Linq/Observable/If.cs –  Apr 11 '17 at 13:32
  • 1
    Yes, but this one is `internal`. – Daniel Müller Apr 11 '17 at 13:48

2 Answers2

3

Yes there is one: https://github.com/Reactive-Extensions/Rx.NET/blob/develop/Rx.NET/Source/src/System.Reactive/Linq/Observable/If.cs

But why don't use your selfmade version? It seems to work quite well for me.

Sadly there is, as far as I know, no build in operator for this task in .Net.

MetaColon
  • 2,895
  • 3
  • 16
  • 38
1

There is an If operator in Rx, with these signatures:

// If the specified condition evaluates true, select the thenSource sequence.
// Otherwise, return an empty sequence.
public static IObservable<TResult> If<TResult>(Func<bool> condition,
    IObservable<TResult> thenSource);

// If the specified condition evaluates true, select the thenSource sequence.
// Otherwise, return an empty sequence generated on the specified scheduler.
public static IObservable<TResult> If<TResult>(Func<bool> condition,
    IObservable<TResult> thenSource, IScheduler scheduler);

// If the specified condition evaluates true, select the thenSource sequence.
// Otherwise, select the elseSource sequence.
public static IObservable<TResult> If<TResult>(Func<bool> condition,
    IObservable<TResult> thenSource, IObservable<TResult> elseSource);

It is not an extension method for IObservable<T>s.

Your handmade If operator looks more like a variant of the SelectMany operator to me. I would have named it SelectMany, since projecting and merging is its primary function.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
  • This [method](https://github.com/dotnet/reactive/blob/f143a94e00ff2dd1b0eba4dcabbaed86574f5e9e/Rx.NET/Source/src/System.Reactive/Linq/QueryLanguage.Imperative.cs#L15) is internal. I personally prefer the name `If` because it describes what this operator does. – Daniel Müller Jan 15 '21 at 19:52
  • 1
    @DanielMüller AFAICS the [`If`](https://github.com/dotnet/reactive/blob/9329157592c13e97ce2d3251c91b2871aed875c9/Rx.NET/Source/src/System.Reactive/Linq/Observable.Imperative.cs#L264) is a public operator, at least in the latest Rx version (5.0.0). I have personally used it to solve a problem [here](https://stackoverflow.com/questions/64353907/how-can-i-implement-an-exhaustmap-handler-in-rx-net/64356119#64356119). – Theodor Zoulias Jan 16 '21 at 01:25