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]);
}
Anonymous methods provide a technique to pass a code block as a delegate parameter. Anonymous methods are the methods without a name, just the body. You need not specify the return type in an anonymous method; it is inferred from the return statement inside the method body.
Anonymous method is a block of code, which is used as a parameter for the delegate. An anonymous method can be used anywhere. A delegate is used and is defined in line, without a method name with the optional parameters and a method body. The scope of the parameters of an anonymous method is the anonymous-method-block.
Anonymous Method LimitationsIt cannot contain jump statement like goto, break or continue. It cannot access ref or out parameter of an outer method. It cannot have or access unsafe code. It cannot be used on the left side of the is operator.
Anonymous Method is an inline code that can be used wherever a delegate type is expected. Microsoft introduced Anonymous Methods in C# 2.0 somewhere around 2003. Lambda expression is an anonymous method that you can use to create delegates or expression tree types.
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
There is only one i
in this case and all of the lambdas are capturing the same value. Use a local that is scoped to the loop so that each lambda has a different copy
for (i = 0; i <= 4; i++)
{
int j = i;
timers[j].Tick += (sender, e) => Tick(targs[j]);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With