Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I modify the loop variable in a foreach?

Tags:

c#

foreach

Why is a foreach loop a read only loop? What reasons are there for this?

like image 600
George Avatar asked Aug 23 '10 21:08

George


3 Answers

I'm not sure exactly what you mean by a "readonly loop" but I'm guessing that you want to know why this doesn't compile:

int[] ints = { 1, 2, 3 };
foreach (int x in ints)
{
    x = 4;
}

The above code will give the following compile error:

Cannot assign to 'x' because it is a 'foreach iteration variable'

Why is this disallowed? Trying to assigning to it probably wouldn't do what you want - it wouldn't modify the contents of the original collection. This is because the variable x is not a reference to the elements in the list - it is a copy. To avoid people writing buggy code, the compiler disallows this.

like image 192
Mark Byers Avatar answered Nov 19 '22 16:11

Mark Byers


I would assume it's how the iterator travels through the list.

Say you have a sorted list:

Alaska
Nebraska
Ohio

In the middle of

foreach(var s in States)
{
}

You do a States.Add("Missouri")

How do you handle that? Do you then jump to Missouri even if you're already past that index.

like image 25
taylonr Avatar answered Nov 19 '22 15:11

taylonr


If, by this, you mean:

Why shouldn't I modify the collection that's being foreach'd over?

There's no surety that the items that you're getting come out in a given order, and that adding an item, or removing an item won't cause the order of items in the collection to change, or even the Enumerator to become invalid.

Imagine if you ran the following code:

var items = GetListOfTOfSomething(); // Returns 10 items

int i = 0;
foreach(vat item in items)
{
    i++;
    if (i == 5)
    {
        items.Remove(item);
    }
}

As soon as you hit the loop where i is 6 (i.e. after the item is removed) anything could happen. The Enumerator might have been invalidated due to you removing an item, everything might have "shuffled up by one" in the underlying collection causing an item to take the place of the removed one, meaning you "skip" one.

If you meant "why can't I change the value that is provided on each iteration" then, if the collection you're working with contains value types, any changes you make won't be preserved as it's a value you're working with, rather than a reference.

like image 35
Rob Avatar answered Nov 19 '22 15:11

Rob