heltonbiker
heltonbiker

Reputation: 27575

Why subscriptions to IObservables taken from a Collection don't work (and what to do about it)

My goal is to create a bunch of observables from a source observable, so that I can subscribe to them individually.

When I do that manually (that is, creating each subSource manually), things work as expected: the values added to the original source propagate adequately to the subSources.

But when I create them in a loop, adding them to a List<IObservable<T>>, the subscriptions to elements taken from that list don't seem to be working:

class Program
{
    static void Main(string[] args)
    {
        // using Subject for the sake of example
        var source = new Subject<int>(); 


        // manually creating each subSource
        var source0 = source.Where((t, i) => i % 3 == 0);
        var source1 = source.Where((t, i) => i % 3 == 1);
        var source2 = source.Where((t, i) => i % 3 == 2);


        // creating a List of subsources
        List<IObservable<int>> sources = new List<IObservable<int>>();

        int count = 3;

        for (int i = 0; i < count; i++)
        {
            sources.Add(source.Where((v, ix) => ix % 3 == i));
        }


        // subscribing to one subSource from each group
        source0.Subscribe(Console.WriteLine); // this works
        sources[1].Subscribe(Console.WriteLine); // this doesn't

        // feeding data
        Observable.Range(0, 20).Subscribe(source);

        Console.ReadKey();
    }
}

Upvotes: 3

Views: 71

Answers (2)

James World
James World

Reputation: 29776

The predicate of your Where clause references the loop variable i.

However, the predicate is tested when a value is published from source - not when the loop is iterated. By the that time, i has reached it's final value 3.

To fix this, create a new variable inside the loop to store the current value of i, and reference that in your Where predicate:

for (int i = 0; i < count; i++)
{
    var j = i;
    sources.Add(source.Where((v, ix) => ix % 3 == j)); // note use of j here
}

Upvotes: 5

Richard Anthony Hein
Richard Anthony Hein

Reputation: 10650

for (int i = 0; i < count; i++)
{
    **var j = i;**
    sources.Add(source.Where((v, ix) => ix % 3 == j));
}

Closures.

Upvotes: 1

Related Questions