Skip to main content
added 837 characters in body
Source Link
Mangata
  • 2.8k
  • 1
  • 4
  • 10

This is a common coding pitfall: you are using a loop increment in a callback function inside a loop construct. The callback function records the reference of the local variable i and reads it when it is called, but at this time i has already increased to the exit threshold.

Try this:

    for (int i = 0; i < panel.buttonActions.Count; i++)
    {
        var temp = i;
        ...
        button.onClick.AddListener(() => panel.buttonActions[temp]());
    }

Deeper explanation:

When a local variable is referenced in the delegate, it becomes a captured variable. this is a good explanation.

The for loop is actually a syntactic sugar, the scope of i is outside the for structure:

    for (int i = 0; i < 10; i++)
    {
        //your code
    }

is actually equivalent to:

    int i = 0;
    for (;;)
    {
        if(i < 10) break;
        //your code
        i++;
    }

that is to say, the i used in each round of the loop points to the same local variable. The captured variable is also the same one. If a new variable(copied of i) scoped to the loop structure is used in each round of the loop, then the captured variable is different.

This is a common coding pitfall: you are using a loop increment in a callback function inside a loop construct. The callback function records the reference of the local variable i and reads it when it is called, but at this time i has already increased to the exit threshold.

Try this:

    for (int i = 0; i < panel.buttonActions.Count; i++)
    {
        var temp = i;
        ...
        button.onClick.AddListener(() => panel.buttonActions[temp]());
    }

This is a common coding pitfall: you are using a loop increment in a callback function inside a loop construct. The callback function records the reference of the local variable i and reads it when it is called, but at this time i has already increased to the exit threshold.

Try this:

    for (int i = 0; i < panel.buttonActions.Count; i++)
    {
        var temp = i;
        ...
        button.onClick.AddListener(() => panel.buttonActions[temp]());
    }

Deeper explanation:

When a local variable is referenced in the delegate, it becomes a captured variable. this is a good explanation.

The for loop is actually a syntactic sugar, the scope of i is outside the for structure:

    for (int i = 0; i < 10; i++)
    {
        //your code
    }

is actually equivalent to:

    int i = 0;
    for (;;)
    {
        if(i < 10) break;
        //your code
        i++;
    }

that is to say, the i used in each round of the loop points to the same local variable. The captured variable is also the same one. If a new variable(copied of i) scoped to the loop structure is used in each round of the loop, then the captured variable is different.

Source Link
Mangata
  • 2.8k
  • 1
  • 4
  • 10

This is a common coding pitfall: you are using a loop increment in a callback function inside a loop construct. The callback function records the reference of the local variable i and reads it when it is called, but at this time i has already increased to the exit threshold.

Try this:

    for (int i = 0; i < panel.buttonActions.Count; i++)
    {
        var temp = i;
        ...
        button.onClick.AddListener(() => panel.buttonActions[temp]());
    }