0

I have a collection of items that each have an IObserver, and a message source that produces Messages(!) I want to filter the messages, and only send on the relevant ones to each item. I think this is a good fit for System.Reactive's linq. Below is an example:

IObservable<Message> source;
foreach(item in items)
{
   var filtered = from msg in source
                  where msg.Id == item.Id
                  selct msg;
   filtered.Subscribe(item.Sink);
}

The problem is that when the source produces a message, the query is evaluated with respect to the last item in the loop. So if there are twenty items each query will be against the properties of item 20.

How do I fix this?

Matthew Finlay
  • 3,354
  • 2
  • 27
  • 32

1 Answers1

2

Try this:

IObservable<Message> source;
foreach(item in items)
{
   var item2 = item;
   var filtered = from msg in source
              where msg.Id == item2.Id
              selct msg;
   filtered.Subscribe(item2.Sink);
}

I think that might help. All is because of scoping I think.

Here is what I think happen in your code. Since the linq query is evaluated lazy the query will always use the variable item and when you enter the loop the variable was last set to the latest item in the collection. By assigning the value to another value in the beginning of the loop each query will work against that variable instead which will not changed in each iteration.

Tomas Jansson
  • 22,767
  • 13
  • 83
  • 137
  • 1
    On a sidenote that is bound for a change in C# 5 as far as I remember. – cyberzed Feb 28 '12 at 09:37
  • The issue is due to the scheduling of the observable. It's running on a different thread or is being queued on the current thread. Either way the subscription is being called after the loop has completed and at that point the `item` variable is set to the last item in the `items` collection. – Enigmativity Feb 28 '12 at 10:26