This question already has an answer here:
- How to tell a lambda function to capture a copy instead of a reference in C#? 4 answers
I've faced some issue with C# code. Adding method to delegate in "for" loop increments "i" by one., so "for(int i = 0, i < x ; i++)" must be change to "for(int i = -1, i < x-1; i++)" to work correctly. Why is that?
Code below throws an IndexOutOfRangeException
string[] names = new string[] { "John", "Madeline", "Jack", "Gabby" };
Action showNameDelegate = null;
for (int i = 0; i < names.Length; i++)
{
showNameDelegate += () => global::System.Console.WriteLine(names[i]);
}
foreach (Action showName in showNameDelegate.GetInvocationList())
{
showName();
}
Right code is (look at iterator "i" which starts from -1 but "names[-1]" does not exist):
string[] names = new string[] { "John", "Madeline", "Jack", "Gabby" };
Action showNameDelegate = null;
for (int i = -1; i < names.Length - 1; i++)
{
showNameDelegate += () => global::System.Console.WriteLine(names[i]);
}
foreach (Action showName in showNameDelegate.GetInvocationList())
{
showName();
}
This answer is correct (by Ed Plunkett): Each delegate references the variable i. They all reference the variable, so when they execute, they'll get whatever value it has right then. The delegates are executed after the for loop completes. At that point, i is equal to names.Length. Make a local copy of i in the body of the loop -- or use a foreach loop, which automatically fixes this issue.