Question

I have this code (C#):

using System.Collections.Generic;

namespace ConsoleApplication1
{
    public struct Thing
    {
        public string Name;
    }

    class Program
    {
        static void Main(string[] args)
        {
            List<Thing> things = new List<Thing>();
            foreach (Thing t in things) //  for each file
            {
                t.Name = "xxx";
            }
        }
    }
}

It won't compile.
The error is:

Cannot modify members of 't' because it is a 'foreach iteration variable'

If I change Thing to a class rather than a struct, however, it does compile.

Please can someone explain what's going on?

Was it helpful?

Solution

More or less what it says, the compiler won't let you change (parts of) the looping var in a foreach.

Simply use:

for(int i = 0; i < things.Count; i+= 1) //  for each file
{
    things[i].Name = "xxx";
}

And it works when Thing is a class because then your looping var is a reference, and you only make changes to the referenced object, not to the reference itself.

OTHER TIPS

A struct is no reference type but a value type.

If you would have a class instead of a struct for Thing, the foreach loop would create a reference variable for you, that would point to the correct element in you list. But since it is a value type, it only operates on a copy of your Thing, which is in this case the iteration variable.

A struct is a value type but a class is a reference type. That's why it compiles when This is a class but not when it is a struct

See more: http://www.albahari.com/valuevsreftypes.aspx

An alternate syntax that I prefer to @Henk's solution is this.

DateTime[] dates = new DateTime[10];

foreach(int index in Enumerable.Range(0, dates.Length))
{
   ref DateTime date = ref dates[index];

   // Do stuff with date.
   // ...
}

If you are doing a reasonable amount of work in the loop then not having to repeat the indexing everywhere is easier on the eye imo.

P.S. DateTime is actually a really poor example as it doesn't have any properties you can set, but you get the picture.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top