[Loop Logic] Wrong value being returned out of a loop from xml nodes

Hi there,

I’m looping through a XmlNodeList which contains information about UI element types and then draws them, via a switch statement of their type e.g. button/toggle

the UI elements however have a delegate for when clicked/toggled that runs, but the value being sent into the delegate function is the wrong one.

Example of my loop:

foreach(XmlNode option in currSettings)
{

 switch (_option.Attributes["guiType"].InnerText)
 {
case "Button":
//create and draw Button UI
//Add listener delegate to button
break;
case "Toggle": 
//create and draw toggle UI
//Add listener delegate to toggle
break;
}

I’m trying to use a delegate with onValueChanged to call a function when the UI is toggled for example.

toggleComponent.onValueChanged.AddListener(delegate { ChangeBoolValues(FieldInfo name, option); });

for function

void ChangeBoolValues(string fi, XmlNode node)
{

    Debug.Log(node.Attributes["val"].InnerText);

    //Change XML from old value to new
    bool oldVal = bool.Parse(node.Attributes["val"].InnerText);
    bool newVal = !oldVal;

    string stringOfNewVal = newVal.ToString().ToLower();
    node.Attributes["val"].InnerText = stringOfNewVal;

    //Change variable in script
    FieldInfo fieldInfo = type.GetField(fi);
    fieldInfo.SetValue(type, newVal);

    //Save 
    doc.Save(fileName);
    
}

However whenever the function ‘ChangeBoolValues’ is called. It receives the wrong node. It’s receiving the node for my button which is drawn from the same loop.

I’m not sure where the logic is going wrong.
Would really appreciate some advice.
Cheers

The foreach loop defines it loop variable “outside” of the loop just once. When you create a closure over that variable inside the loop, each closure will reference the same variable. You have to use a local variable which you can close over:

foreach(XmlNode option in currSettings)
{
    XmlNode temp = option;
    // [ ... ]
    ....AddListener(delegate { ChangeBoolValues(FieldInfo name, temp); });

Note: this won’t work inside coroutines. Coroutines are not normal methods. They are statemachine classes so local variables become class variables.