2

I have some behaviour that I do not understand. While the unrolled loop works fine!!! The loop throws IndexOutOfRangeExceptions. Debugging shows that there 0..9 teamButtons and 0..9 cards c[i]. :(

private void Awake()
{
    InitCards();
    // This works!
    teamButtons[0].onClick.AddListener(() => SetCard(c[0]));
    teamButtons[1].onClick.AddListener(() => SetCard(c[1]));
    teamButtons[2].onClick.AddListener(() => SetCard(c[2]));

    teamButtons[3].onClick.AddListener(() => SetCard(c[3]));
    teamButtons[4].onClick.AddListener(() => SetCard(c[4]));
    teamButtons[5].onClick.AddListener(() => SetCard(c[5]));

    teamButtons[6].onClick.AddListener(() => SetCard(c[6]));
    teamButtons[7].onClick.AddListener(() => SetCard(c[7]));
    teamButtons[8].onClick.AddListener(() => SetCard(c[8]));
    // This yields an IndexOutOfRangeException
    for (int i = 0; i < 9; ++i)
    {
      teamButtons[i].onClick.AddListener(() => { SetCard(c[i]); });
    } 
}
Rofl Ukulus
  • 147
  • 2
  • This is a duplicate of many questions, but it's a hard one to find by searching, so I'll add an answer instead. – Jon Skeet Mar 07 '17 at 13:52
  • i++ not ++i, see http://stackoverflow.com/questions/24853/what-is-the-difference-between-i-and-i – yes Mar 07 '17 at 16:20

1 Answers1

14

You're capturing the variable i in your lambda expression. When that lambda expression is executed, it will use the "current" value of i - which will always be 9. You want to capture a copy of the variable... which you can do be introducing a new variable in the loop:

for (int i = 0; i < teamButtons.Length; i++)
{
    int index = i;
    teamButtons[i].onClick.AddListener(() => SetCard(c[index]));
} 
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194