Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a foreach iteration variable not change for ANY reason?

Tags:

c#

foreach

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.

like image 579
warrens Avatar asked Dec 19 '22 20:12

warrens


1 Answers

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.

like image 108
Damien_The_Unbeliever Avatar answered Jan 23 '23 14:01

Damien_The_Unbeliever