This can occur in a situation such as the following:
private struct Position
{
public int left;
public int top;
}
private static List<Position> \_points = new List<Position>();
private static void MyFunc()
{
foreach (Position pnt in \_points)
{
pnt.top++;
}
}
This will fail to compile with the error message:
Cannot modify members of ‘pnt’ because it is a ‘foreach iteration variable’
Why?
The reason for this is simply that you cannot modify the collection that you iterate through, as you iterate through it. From the above statement, I can see that modifying the variable `top` would make no difference, but imagine this:
foreach (Position pnt in \_points.OrderBy(p => p.top))
{
pnt.top++;
}
How to fix?
There’s two easy ways around this; the first is to switch a struct for a class:
internal class Position
{
public int left;
public int top;
}
That would now work. The reason for this is the way that the two types are stored. Classes are reference types; which means that what is actually stored in the collection is a list of pointers to classes, and not the classes themselves; consequently, changing them does not affect the actual collection. You can even use orderby on the collection because it caches the order at the start of the loop (I’m certainly not advocating actually doing this).
What if you need to use a struct
Structs are immutable; which means you cannot change them. You can do something like this; although I personally can’t see why it’s easier that using a class:
for (int i = 0; i <= \_points.Count() - 1; i++)
{
\_points[i] = new Position() { left = \_points[i].left, top = \_points[i].top + 1 };
}