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 T开发者_Python百科hing
to a class
rather than a struct
, however, it does compile.
Please can someone explain what's going on?
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.
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.
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.
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
精彩评论