I'm familiar with the problem of modifying a collection while looping over it with a foreach
loop (i.e. "System.InvalidOperationException: Collection was modified"). However, it doesn't make sense to me that when I use Linq to create a List of keys to delete from a dictionary, then loop over my new List, I get the same exception.
Code before, that threw an exception:
IEnumerable<Guid> keysToDelete = _outConnections.Where(
pair => pair.Value < timeoutPoint
).Select(pair => pair.Key);
foreach (Guid key in keysToDelete)
{
...some stuff not dealing with keysToDelete...
_outConnections.Remove(key);
}
Code after, that worked:
List<Guid> keysToDelete = _outConnections.Where(
pair => pair.Value < timeoutPoint
).Select(pair => pair.Key).ToList();
for (int i=keysToDelete.Count-1; i>=0; i--)
{
Guid key = keysToDelete[i];
...some stuff not dealing with keysToDelete...
_outConnections.Remove(key);
}
Why is this? I have the feeling that maybe my Linq queries aren't really returning a new collection, but rather some subset of the original collection, hence it accuses me of modifying the collection keysToDelete
when I remove an element from _outConnections
.
Update: the following fix also works, thanks to Adam Robinson:
List<Guid> keysToDelete = _outConnections.Where(
pair => pair.Value < timeoutPoint
).Select(pair => pair.Key).ToList();
foreach (Guid key in keysToDelete)
{
...some stuff not dealing with keysToDelete...
_outConnections.Remove(key);
}
You're correct. LINQ uses what's called "deferred execution". Declaring your LINQ query doesn't actually do anything other than construct a query expression. It isn't until you actually enumerate over the list that the query is evaluated, and it uses the original list as the source.
However, calling ToList()
should create a brand new list that has no relation to the original. Check the call stack of your exception to ensure that it is actually being thrown by keysToDelete
.
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