[ACCEPTED]-Why is The Iteration Variable in a C# foreach statement read-only?-language-design

Accepted answer
Score: 26

Lets start out with a silly but illustrative 29 example:

Object o = 15;
o = "apples";

At no point do we get the impression 28 that we just turned the number 15 into a 27 string of apples. We know that o is simply 26 a pointer. Now lets do this in iterator 25 form.

int[] nums = { 15, 16, 17 };

foreach (Object o in nums) {
     o = "apples";
}

Again, this really accomplishes nothing. Or 24 at least it would accomplish nothing were it 23 to compile. It certainly wouldn't insert 22 our string into the int array -- that's 21 not allowed, and we know that o is just a 20 pointer anyway.

Let's take your example:

foreach (Position Location in Map)
{
     //We want to fudge the position to hide the exact coordinates
     Location = Location + Random();     //Compiler Error

     Plot(Location);
}

Were 19 this to compile, the Location in your example stars 18 out referring to a value in Map, but then you 17 change it to refer to a new Position (implicitly 16 created by the addition operator). Functionally 15 it's equivalent to this (which DOES compile):

foreach (Position Location in Map)
{
     //We want to fudge the position to hide the exact coordinates
     Position Location2 = Location + Random();     //No more Error

     Plot(Location2);
}

So, why 14 does Microsoft prohibit you from re-assigning 13 the pointer used for iteration? Clarity 12 for one thing -- you don't want people assigning 11 to it thinking they've changed your position 10 within the loop. Ease of implementation 9 for another: The variable might hide some 8 internal logic indicating the state of the 7 loop in progress.

But more importantly, there 6 is no reason for you to want to assign to it. It 5 represents the current element of the looping 4 sequence. Assigning a value to it breaks 3 the "Single Responsibility Principle" or 2 Curly's Law if you follow Coding Horror. A variable 1 should mean one thing only.

Score: 14

If the variable were mutable, that might 5 give an incorrect impression. For example:

string[] names = { "Jon", "Holly", "Tom", "Robin", "William" };

foreach (string name in names)
{
    name = name + " Skeet";
}

Some 4 people might think that would change the array 3 contents. It's reaching a bit, but it might 2 be a reason. I'll look it up in my annotated 1 spec tonight...

Score: 11

I think its artificial limitation, no really 7 need to do it. To prove the point, take 6 this code into considiration, and a possible 5 solution to your problem. The problem is 4 to asign, but internal changes of objects 3 don't present a problem:

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {

            List<MyObject> colection =new List<MyObject>{ new MyObject{ id=1, Name="obj1" }, 
                                                    new MyObject{ id=2, Name="obj2"} };

            foreach (MyObject b in colection)
            {
             // b += 3;     //Doesn't work
                b.Add(3);   //Works
            }
        }

        class MyObject
        {
            public static MyObject operator +(MyObject b1, int b2)
            {
                return new MyObject { id = b1.id + b2, Name = b1.Name };
            }

          public void Add(int b2)
          {
              this.id += b2;
          }
            public string Name;
            public int id;
        }
    }
}

I didn't know about 2 this phenomena, because I was always modifying 1 the objects the way I described.

Score: 4

When you modify the collection, the modification 5 might have unpredictable side effects. The 4 enumerator has no way of knowing how to 3 deal correctly with these side effects, so 2 they made the collections immutable.

See 1 also this question: What is the best way to modify a list in a foreach

Score: 1

The foreach statement works with Enumerable. The 11 thing that is different with an Enumerable 10 is that it doesn't know about the collection 9 as a whole, it's almost blind.

This means 8 that it doesn't know what's coming next, or 7 indeed if there is anything until the next 6 iteration cycle. That why there you see 5 .ToList() a lot so people can grab a count 4 of the Enumerable.

For some reason that I'm 3 not sure about, this means that you need 2 to ensure your collection isn't changing 1 as you try to move the enumerator along.

Score: 1

The condition to work with IEnumerable objects 11 is that the underlying collection must not 10 change while you are accessing it with Enumerable. You 9 can presume that the Enumerable object is 8 a snap shot of the original collection. So 7 if you tries to change the collection while 6 enumerating it'll throw an exception. However 5 the fetched objects in Enumeration is not 4 immutable at all.

Since the variable used 3 in foreach loop is local to the loop block 2 this variable is however not available outside 1 the block.

More Related questions