New: support for joins in Rx. This includes two new operators, Join and GroupJoin, which have query expression support too:

This work will be covered on Channel 9 in much more detail. We’ll update this post with a link to the video when it’s online. Here’s the sketch of this new functionality.

Depending on the use of “into”, either Join or GroupJoin is being called in the following sample (see language specification for more details on the translation into query operator methods):

from x in xs join y in ys on f(x) equals g(y) [into z] …

In the sample above, xs and ys are observable sequences. Furthermore, f(x) and g(y) are functions that return an observable sequence that denotes a duration. Results are produced when those observable sequences overlap. For example, one could monitor people entering and leaving a room and create a joined sequence that produces pairs of people that are in the same room at the same time.

Added a Window operator that uses joins underneath.

Reimplemented BufferWithTime, BufferWithCount, BufferWithTimeOrCount in terms of those new join and windowing operators.

Generalized Publish family of operators (Publish, Prune, Replay) to a single Publish operator that takes in a Subject. Sharing a subscription to an observable sequence can be seen as “shadowing” the observable sequence using a Subject that can enforce different sharing policies (e.g. maintain history or not).

Related to this work is the addition of a Multicast operator, which encapsulates a ConnectableObservable.

ConnectableObservable is now parameterized in two generic type parameters, reflecting the most general ISubject.

Added an overload to If that doesn’t take an “else” case observable sequence (defaulting to Observable.Empty).

Fixes:

DispatcherScheduler is now maintained on a per-thread basis using ThreadStatic.

Refined implementation of Switch.

Variance annotations on IAsyncEnumerable and IAsyncEnumerator for .NET 4.