Reputation: 1288
I have ten positions with x, y and name. I would like to set all x to x+1. How to do this? I tried different methods, but I always get that I cannot modify the list. It should be done with for or foreach.
I get "Cannot modify members of "item" because it is foreach iteration variable."
public struct Position
{
public int x { get; set; }
public int y{ get; set; }
public string name{ get; set; }
}
class Program
{
static void Main(string[] args)
{
List<Position> positions = new List<Position>();
Position position = new Position();
position.x = 12;
position.y = 12;
position.name = "left";
positions.Add(position);
position = new Position();
position.x = 13;
position.y = 13;
position.name = "right";
positions.Add(position);
Console.WriteLine(positions.Count);
Console.WriteLine();
Position newPosition;
foreach (Position item in positions)
{
}
Console.WriteLine();
foreach (Position item in positions)
{
Console.WriteLine(item.x + " " + item.name);
}
}
}
}
Upvotes: 0
Views: 189
Reputation: 63317
You should consider using class instead of struct. However if it's a requirement. You can still make it work. The problem is you used a foreach
which in fact always refer to the underlying list item, if the item is reference type, it's OK without problem but if it's value type, this value will be copied to the iterator. And all the modifications on the copy iterator are meaningless. So error is needed. You surely have to use a normal for
instead. However it is not enough. Your positions
is a List<Position>
and when you get some item from it, actually some copied value is returned because of the internal implementation of indexer. To solve this you can do one of the followings:
First solution:
for(int i = 0; i < positions.Count; i++){
//copy first
var current = positions[i];
//update value
current.x++;
//set back to list
positions[i] = current;
}
Second solution:
//convert the list to array so that all the items will be fetched directly
//without using indexer:
var temp = positions.ToArray();
for(int i = 0; i < temp.Length; i++){
temp[i].x++;
}
Upvotes: 1
Reputation: 3118
i hope i get what in your mind truly:
int preX1 = 0, PreX2 = 0;
for (int i = 0; i <= positions.Count - 1; i++)
{
if(i == 0)
{
preX1 = positions[i].x;
}
else
{
preX2 = positions[i].x;
positions[i].x = preX1;
preX1 = preX2;
}
}
Upvotes: 0
Reputation: 1675
Structs are immutable types. So once you assign it, it can't be changed within the list. The foreach loop isn't really the problem. Editing an element of the list outside of the foreach will give the same error.
There are a number of questions addressing this on Stack Overflow with some valuable insight:
Cannot modify a struct in a list
So if you had to use a struct in this scenario you would have to make a mutable struct, which is --evil-- from what I have read.
Upvotes: 0
Reputation: 38079
You need to increment x within the loop.
If you want to use a for each, then you need to also make position a class:
public class Position
{
public int x { get; set; }
public int y{ get; set; }
public string name{ get; set; }
}
foreach (Position item in positions)
{
item.x = item.x + 1;
}
Upvotes: 1