- Home /
Add an iteration of OnClick methods
for (var a = 0; a < elements.Count; a++)
{
elements[a].Add.onClick.RemoveAllListeners();
elements[a].Add.onClick.AddListener(() => OnClick_IncrementFilteredIndex(a));
elements[a].Subtract.onClick.RemoveAllListeners();
elements[a].Subtract.onClick.AddListener(() => OnClick_DecrementFilteredIndex(a));
elements[a].Edit.onClick.RemoveAllListeners();
elements[a].Edit.onClick.AddListener(() => OnClick_EditFilteredIndex(a));
}
Whenever I click a button, it always debugs as the element.Count's max index instead of 0, 1, 2, 3, 4. Is there a way to programmatically assign OnClick events and maintain the correct index?
Answer by Bunny83 · Mar 23, 2016 at 11:58 AM
The problem here is that you create a closure inside a for loop. A closure is a special compiler created class for an anonymous method that accesses variables from the scope it was created in. In your case the your closures will "close" over the variable "a". However it closes over the "variable" not the value of the variable. That means whenever your callback is called, you will pass what's in that variable at that time. Since the scope of "a" usually ends when you leave the for loop the content of "a" will be the last value it has inside the for loop.
The solution is simple:
for (var a = 0; a < elements.Count; a++)
{
int tmp = a;
// [...]
elements[a].Add.onClick.AddListener(() => OnClick_IncrementFilteredIndex( tmp ));
// [....]
You simply have to create a "new" variable each for loop iteration which you use in your closure. That way each variable will have their own value.
You might want to read through this article. In your case only the section "the for loop" is relevant but it doesn't hurt to keep the rest in mind as well.