Reputation: 2115
I have a foreach statement with an iteration variable named "rcnesw".
foreach( RCNESW rcnesw in shiftersave )
{
TestG.ShiftQuad( rcQuads, rcnesw.row, rcnesw.col, GO_.Up);
// other code...
}
During debugging the values of rcnesw.row and rcnesw.col CHANGE as a result of the call to ShiftQuad -- I thought the foreach loop variable was readonly. Is it ever not readonly?
Note: the TestG.ShiftQuad method also has a foreach loop in it with its own local (I thought local) variable which has the very same name and type: RCNESW rcnesw. That value seems to transmit back up to the calling foreach location.
(=====edit=====adding=====)
First, thanks to all for the info on the "mutable" nature of the "readonly" variable. That clarifies the situation (that the C#/.NET docs do not).
Further info on the ShiftQuad method, it is:
public void ShiftQuad( List<RCPair> rcList, int row, int col, int dir )
And inside that method nothing changes row or col. ShiftQuad declares its own rcnesw:
RCNESW rcnesw = null;
Or does it? Does that statement not create a new instance of RCNESW? Because when that method makes rcnesw.row and rcnesw.col change then the calling method receives those changes apparently.
public class RCNESW
{
public int row;
public int col;
public bool bNorth;
public bool bEast;
public bool bSouth;
public bool bWest;
}
At this point I still think it is a compiler bug. Changes to a local variable should not emerge at the caller through variables that are called by value.
(====edit====solved===) This issue was really related not to local vs non-local (or pass by value), the screwup was in how some lists became aliases for the same objects.
Upvotes: 4
Views: 972
Reputation: 61952
In the body of the loop
foreach( RCNESW rcnesw in shiftersave )
the loop variable rcnesw
is read-only, but exactly what that means depends heavily on whether RCNESW
is a reference type (class type, interface type, delegate type, array type) or a value type (struct type, enum type).
If RCNESW
is a reference type, the only thing that can't be mutated is the value of rcnesw
which is the reference. So the "identity" of which object is being referred by rcnesw
can't change. However, the state of that same object may change dramatically; there is no limitation there.
Upvotes: 2
Reputation: 43023
You can obviously change the object properties of the object that is referred to by each iteration of the foreach
loop.
You should not change the collection though. Citing MSDN:
The foreach statement is used to iterate through the collection to get the information that you want, but can not be used to add or remove items from the source collection to avoid unpredictable side effects. If you need to add or remove items from the source collection, use a for loop.
Upvotes: 1
Reputation: 239674
Whenever you encounter read only concepts in C#, it's almost always a shallow form of read only - you can't change which object the variable is referring to, but you can make changes to that object's own properties (or call methods on it, etc)
The same applies for readonly
fields of a class - you can't change the reference but you can mutate the object.
Upvotes: 8