I'm interested in the following overloads:
public static IObservable<IList<TSource>> CombineLatest<TSource>(this params IObservable<TSource>[] sources);
public static IObservable<IList<TSource>> CombineLatest<TSource>(this IEnumerable<IObservable<TSource>> sources);
Is the order of the elements in the resulting list guaranteed to be the same as the order in the input?
For example, in the following code will list[0] always contain an element from a and list[1] an element from b?
IObservable<int> a = ...;
IObservable<int> b = ...;
var list = await Observable.CombineLatest(a, b).FirstAsync();
The documentations states:
a list with the latest source elements
and:
observable sequence containing lists of the latest elements of the sources
but does not really mention anything about order.
The order is conserved.
When you look in the source code of RX, it all boils down to the System.Reactive.Linq.CombineLatest<TSource, TResult> class.
You can find there that an indexed observer is created for each input observable (where the index is the order in the input):
for (int i = 0; i < N; i++)
{
var j = i;
var d = new SingleAssignmentDisposable();
_subscriptions[j] = d;
var o = new O(this, j);
d.Disposable = srcs[j].SubscribeSafe(o);
}
And the resulting element is produced as follows:
private void OnNext(int index, TSource value)
{
lock (_gate)
{
_values[index] = value;
_hasValue[index] = true;
if (_hasValueAll || (_hasValueAll = _hasValue.All(Stubs<bool>.I)))
{
/* snip */
res = _parent._resultSelector(new ReadOnlyCollection<TSource>(_values));
/* snip */
_observer.OnNext(res);
}
/* snip */
}
}
The _resultSelector for the overloads I'm interested in is just a Enumerable.ToList(). So the order in the output list will be the same as the order in the input.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With