Recently I ran into a situation which isn't very obvious at first glance if you don't know how the Linq to objects extension methods work in C#. If you know how the IEnumerable<T> works in combination with the various extension methods in the System.Linq namespace however, you’ll quickly see what'll go wrong. Observe the following snippet:
List<int> source = new List<int> { 1, 2, 3, 4, 5, 6 };
var filter = source.Where(x => x > 4);
foreach(var listitem in filter)
{
// do something with the value //
source.Remove(listitem);
}
This will throw an InvalidOperationException, stating that the collection has been changed. If you don’t know exactly how this construction works, you assume that ‘filter’ is not related to ‘source’. However, internally it still uses the source object and simply decorates the source with WhereIterator<T>. In other words, if you do something with ‘source’, any result from methods like Where(), Select() and so on will be affected as well. To circumvent this, you’ll have to convert this enumerable to a new object, like a List. This is done simply as such:
List<int> source = new List<int> { 1, 2, 3, 4, 5, 6 };
var filter = source.Where(x => x > 4).ToList();
foreach(var listitem in filter)
{
// do something with the value //
source.Remove(listitem);
}
By calling ToList() on the enumerable, the enumeration is evaluated and the result will be put into a new list. This way, you’ll remove the reference to the source object, solving this bug.
PS: I know this example could be implemented in a better way, but to illustrate the problem this is the easiest example.