Anonymous method for event handler in for loop

c#, event-handling, winforms

Solution

This is coming from the lambda expression; `i` is shared between all of them. By the time the function is executed they're essentially being called like `timers[i].Tick += (sender, e) => Tick(targs[5])`.

To avoid this, create a locally scoped variable (`int locali = i`) and use that in your line instead. This will make sure that each lambda expression actually gets the value you expect.

for (i = 0; i <= 4; i++)
{
    int locali = i;
    timers[locali].Tick += (sender, e) => Tick(targs[locali]);
} 

`i` becomes 5 from the last iteration of your loop before exiting. Naturally, you don't have a `targs[5]` element, so it throws an `IndexOutOfRangeException`.

Technically, you don't need to use `locali` for the `timers[i].Tick` part since it's evaluated immediately, but I personally find it confusing to mix the two.

Some additional reading on the concepet:

The foreach identifier and closures

Closing over the loop variable considered harmful

Problem

Can this be done in a for loop? ``` TickEventArgs targs1 = new TickEventArgs(lbl1_up_time, _elapsedTime_up1); timer_up1.Tick += (sender, e) => Tick(targs1); TickEventArgs targs2 = new TickEventArgs(lbl2_up_time, _elapsedTime_up2); timer_up2.Tick += (sender, e) => Tick(targs2); TickEventArgs targs3 = new TickEventArgs(lbl3_up_time, _elapsedTime_up3); timer_up3.Tick += (sender, e) => Tick(targs3); TickEventArgs targs4 = new TickEventArgs(lbl4_up_time, _elapsedTime_up4); timer_up4.Tick += (sender, e) => Tick(targs4); TickEventArgs targs5 = new TickEventArgs(lbl5_up_time, _elapsedTime_up5); timer_up5.Tick += (sender, e) => Tick(targs5); ``` This doesnt work because i is out of bounds (5) ``` targs[0] = new TickEventArgs(lbl1_up_time, _elapsedTime_up1); targs[1] = new TickEventArgs(lbl2_up_time, _elapsedTime_up2); targs[2] = new TickEventArgs(lbl3_up_time, _elapsedTime_up3); targs[3] = new TickEventArgs(lbl4_up_time, _elapsedTime_up4); targs[4] = new TickEventArgs(lbl5_up_time, _elapsedTime_up5); timers[0] = timer_up1; timers[1] = timer_up2; timers[2] = timer_up3; timers[3] = timer_up4; timers[4] = timer_up5; int i = 0; for (i = 0; i <= 4; i++) { timers[i].Tick += (sender, e) => Tick(targs[i]); } ```

Original source

Related problems