Skip to content

ReactiveUI.Primitives

ReactiveUI.Primitives is a small, fast library for reactive programming in .NET. Reactive programming means working with values that arrive over time, such as button clicks, timer ticks, or network replies, rather than values you already hold.

If you know LINQ, you already know the shape. LINQ queries a collection you hold and pulls values out of an IEnumerable<T>. Reactive programming queries values that arrive over time: an IObservable<T> pushes each value to you as it happens.

dotnet add package ReactiveUI.Primitives

New to streams, or wondering why ReactiveUI uses this library? Start with why Primitives.

Your first stream

1. Make a stream. Signal holds the factories that build one.

using ReactiveUI.Primitives;
using ReactiveUI.Primitives.Signals;

IObservable<int> numbers = Signal.FromEnumerable([1, 2, 3, 4, 5]);

2. Shape it. Where passes through the values a test accepts. Select runs a lambda on each value.

IObservable<int> odds = numbers.Where(x => x % 2 == 1)
                               .Select(x => x * 10);

3. Subscribe. Nothing runs until you do.

odds.Subscribe(x => Console.WriteLine(x));   // 10, 30, 50

Subscribe hands back an IDisposable. Dispose it to stop listening.

Two names for one operator

Many operators have two names, and both build the same thing. One matches LINQ or the Primitives style, such as Where or Calm. The other matches the names used by other reactive libraries, such as System.Reactive and RxJS, such as Throttle. Use whichever suits you and your team.

This site uses the LINQ name when LINQ has the operator, and the Primitives name otherwise. Each page lists the other names in the table at its end, and the System.Reactive page lists them all.

The operator pages

Operators are grouped by what they do. Each page covers every operator in its group, with an example for each one.

GroupWhat it covers
Creation factoriesBuilding a stream from a value, a collection, a task, an event or a timer.
TransformationChanging each value, or flattening a stream of streams.
FilteringDropping values you do not want.
CombinationJoining two or more streams into one.
TimeDelaying, batching, sampling and timing out.
Error handlingRecovering from a failure, retrying, and cleaning up.
Aggregation and resultsReducing a stream to one answer, or waiting for a result with await.
UtilitySubscribing, choosing where code runs, peeking at values, and cleaning up.
Sharing one subscriptionLetting several subscribers share one run of a stream, and keeping a current value.
Signals you push values intoSignal<T> and the other signals: remembering values, many threads, commands and cancellable work.
Sequencers and schedulingChoosing where and when work runs, and testing with a virtual clock.
UI platformsUpdating the screen from a stream on WPF, WinForms, WinUI, Avalonia, MAUI, Blazor, Android and Apple.
DisposablesGrouping subscriptions, swapping the latest one, and disposing each exactly once.
ReactiveUI.Primitives and System.ReactiveNames, types and behaviour that differ, AOT and speed, and using both together.
Best practicesHabits that avoid leaks, frozen screens and slow tests.
Extension helpersReady-made helpers: retries with delays, async work per value, spotting a quiet stream, and waiting in tests.
Async streamsIObservableAsync<T>, where the sender waits for each subscriber, with its own operator pages.
Type referenceEvery public type not shown on an operator page, and the operator it belongs to.

The two package flavours

Every type ships twice. ReactiveUI.Primitives is the lean build with no dependency on System.Reactive. ReactiveUI.Primitives.Reactive is the same source compiled against System.Reactive, and its types sit under ReactiveUI.Primitives.Reactive. Pick the lean package unless your app must share System.Reactive types with other code. See using both libraries together.