pmohandas pmohandas - 1 month ago 14
C# Question

Modifying collection inside foreach loop using IEnumerable Where()

Although the iterator variable in a

foreach
loop is immutable, I am able to modify my collection in the example below if I use
Where()
to do the modification:

static void Main(string[] args)
{
var list = new List<int> { 1, 2, 3, 4 };

foreach (var listElement in list)
{
Console.WriteLine(listElement + " ");
list = list.Where(x => x != listElement).ToList();
}

Console.WriteLine("Count: " + list.Count);
}


Output:

1
2
3
4
Count: 0


Could someone please explain this behavior?

Answer

I believe that in the foreach (var listElement in list) you are getting the enumerator for the reference of list at that point in time.

In your loop you assign a new instance to the list variable, but the enumerator the loop is using keeps the reference to the original enumerator.

What you can not do is mutate the original instance. i.e. perform list.Remove(listElement) as this would be mutating the actual data you are trying to enumerate

It might help if the code is expanded to what the foreach loop is actually doing

static void Main(string[] args)
{
    var list = new List<int> { 1, 2, 3, 4 };
    var enumerator = list.GetEnumerator();
    while (enumerator.MoveNext())
    {
        var listElement = enumerator.Current;
        Console.WriteLine(listElement + " ");
        list = list.Where(x => x != listElement).ToList();
    }
    enumerator.Dispose();

    Console.WriteLine("Count: " + list.Count);
}