Class OperatorHelper
- Namespace
- RxSharp
- Assembly
- RxSharp.dll
The building block every operator is written against. Mirrors rxjs's operate() helper.
public static class OperatorHelper
- Inheritance
-
System.ObjectOperatorHelper
Methods
Operate<TSource, TResult>(Observable<TSource>, Func<Observable<TSource>, Subscriber<TResult>, IDisposable?>)
Creates a new Observable<T> whose subscribe logic is init, given the
upstream source and the downstream Subscriber<T> to push notifications to.
This is the low-level primitive every built-in operator is implemented on top of.
public static Observable<TResult> Operate<TSource, TResult>(this Observable<TSource> source, Func<Observable<TSource>, Subscriber<TResult>, IDisposable?> init)
Parameters
sourceObservable<TSource>The upstream source observable.
initFunc<Observable<TSource>, Subscriber<TResult>, IDisposable?>Called at subscribe time with the source and the downstream subscriber; returns the teardown logic for the subscription, if any.
Returns
- Observable<TResult>
The new, operator-defined observable.
Type Parameters
TSourceThe element type of the source observable.
TResultThe element type of the resulting observable.
Pipe<TSource, TResult>(Observable<TSource>, OperatorFunction<TSource, TResult>)
Applies an OperatorFunction<TSource, TResult> to source. Equivalent to calling op directly; exists to let operators be composed in a left-to-right, method-chained style.
public static Observable<TResult> Pipe<TSource, TResult>(this Observable<TSource> source, OperatorFunction<TSource, TResult> op)
Parameters
sourceObservable<TSource>The source observable.
opOperatorFunction<TSource, TResult>The operator function to apply.
Returns
- Observable<TResult>
The result of applying
optosource.
Type Parameters
TSourceThe element type of the source observable.
TResultThe element type of the resulting observable.
SubscribeChild<TSource, TResult>(Observable<TSource>, Subscriber<TResult>, Action<TSource>?, Action<Exception>?, Action?)
Subscribes to source with a fresh inner Subscriber<T>, registered as a
child of downstream before the subscribe call runs. This is what lets a downstream
disposal (an early-completing operator further down the chain, or an external unsubscribe) cascade up and stop
source immediately — including mid-loop for a fully-synchronous, self-checking source —
instead of only after the whole synchronous call stack has already unwound. See CLAUDE.md's Learnings for the
full story of the bug this fixes.
public static IDisposable? SubscribeChild<TSource, TResult>(this Observable<TSource> source, Subscriber<TResult> downstream, Action<TSource>? onNext = null, Action<Exception>? onError = null, Action? onComplete = null)
Parameters
sourceObservable<TSource>The source observable to subscribe to.
downstreamSubscriber<TResult>The downstream subscriber the new inner subscriber is registered as a child of.
onNextAction<TSource>?Called for each value from
source.onErrorAction<Exception>?Called if
sourceerrors.onCompleteAction?Called when
sourcecompletes.
Returns
- IDisposable?
null, always — see the remarks above for why.
Type Parameters
TSourceThe element type of the source observable.
TResultThe element type of the downstream subscriber (usually unrelated to the callback signatures, just needed to type
downstream).
Remarks
Only use this for an operator with exactly ONE inner subscription for its whole lifetime. An operator that
creates a new inner subscription per value or per cycle (MergeMap, SwitchMap, Debounce, Window*, ...)
needs to also call Remove(IDisposable) once each inner subscription naturally ends, or the
downstream subscriber's finalizer list grows unboundedly — this helper does not do that for you.
Deliberately returns null, not the inner subscription: the inner subscriber is already
registered as a child of downstream above, so if a caller did return
src.SubscribeChild(...) as the tail expression of an Operate<TSource, TResult>(Observable<TSource>, Func<Observable<TSource>, Subscriber<TResult>, IDisposable?>) callback and
this method returned the inner subscriber, Subscribe(IObserver<T>) would add that
same object to downstream a second time (it adds whatever the callback returns as a
teardown). Harmless in practice (disposing a Subscription twice is a no-op) but a wasted,
permanent duplicate entry in the finalizer list for the operator's whole lifetime — returning null here is what keeps that list to exactly one entry per inner subscription.