Adding method to delegate changes iteration in “fo

2019-06-14 19:41发布

This question already has an answer here:

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.

1条回答
forever°为你锁心
2楼-- · 2019-06-14 19:58

You should change your code like this;

for (int i = -1; i < names.Length - 1; i++)
{
    string name = names[i];
    showNameDelegate += () => global::System.Console.WriteLine(name);
}

Or you can try to use foreach.

查看更多
登录 后发表回答