5

does anyone know if, when iterating on a C# BlockingCollection<>, the elements are taken from the collection, in the same way that BlockingCollection.Take() does for example?

BlockingCollection<int> q = new BlockingCollection<int>();
[...]
foreach(int i in q)
{
    //does q still contain i?
}

Thanks

EDIT: Of course I meant BlockingCollection, but for some reason got BlockingQueue in my head and used that.

nitbix
  • 143
  • 8

3 Answers3

13

The BlockingCollection<T> enumerator does NOT remove items from the collection.

However, the enumerator returned from BlockingCollection<T>.GetConsumingEnumerable() DOES remove items from the collection.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
2

foreach simply enumerates across a collection. It never removes anything from any collection.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
  • 1
    And actually if I'm not mistaken, manipulating the collection inside a foreach is forbidden and will fail at runtime. – Laurent S. Dec 06 '13 at 11:20
  • 2
    That is simply not true. Consider, for example, using `foreach` with [`BlockingCollection.GetConsumingEnumerable()`](http://msdn.microsoft.com/en-us/library/dd287186%28v=vs.110%29.aspx) The issue is that because `foreach` simply calls methods in `IEnumerator` the effect depends on the specific implementation of `IEnumerator` that's being called - so you can make no claims about what the effect of using `foreach` will be. – Matthew Watson Dec 06 '13 at 11:25
  • Sorry, Matthew, you're wrong. `foreach` isn't removing anything - it's the `IEnumerator` which is removing items in this very specific and very unusual case. – John Saunders Dec 06 '13 at 11:29
  • 2
    Using `foreach` can have the side-effect of removing items from a collection, which is my point. I think this point is important in the context of the OP's question which wasn't *"does foreach remove elements from a collection?"* but rather *"when iterating on a C# BlockingQueue<>, are elements taken from the collection?"* – Matthew Watson Dec 06 '13 at 11:32
  • @MatthewWatson: name one other enumerator that removes from a standard collection. This possibility is simply not worth mentioning. – John Saunders Dec 06 '13 at 11:39
  • The OP seems to be talking about a BlockingCollection (although he referred to it as a BlockingQueue) so my opinion is that this is definitely relevant and therefore it is indeed worth mentioning. I agree in the general case (i.e. ALL other cases!) then it isn't relevant. But I'm responding to the OP's actual question rather than something theoretical. – Matthew Watson Dec 06 '13 at 12:15
0

There is no BlockingQueue<T> in the .NET libraries.

Assuming

  1. You're talking about BlockingCollection<T>: No. using foreach calls the GetEnumerator method, which returns an IEnumerator. Standard implementations of an IEnumerator simply enumerate through the elements in the collection without any observable side effects. Since MSDN doesn't say otherwise regarding BlockingCollection<T> specifically, it is safe to assume that this specific implementation also has no observable side effects.

  2. You're talking about a third-party library: You'll have to check its implementation, but I think it's safe to assume it doesn't remove anything from the collection.

Edit: Actually, because BlockingCollection wraps around an IProducerConsumerCollection<T>, BlockingCollection uses the enumerator of the underlying (internal) collection. None of the IProducerConsumerCollection<T> implementations provided by .NET modify the collection.

robkriegerflow
  • 716
  • 5
  • 13
dcastro
  • 66,540
  • 21
  • 145
  • 155