Почему плохо использовать переменную итерации в выражении лямбда
Я только что написал быстрый код и заметил эту ошибку компилятора
Использование переменной итерации в выражении лямбда может иметь неожиданные результаты.
Вместо этого создайте локальную переменную в цикле и присвойте ей значение переменной итерации.
Я знаю, что это значит, и я могу легко это исправить, а не большое дело.
Но мне было интересно, почему это плохая идея использовать переменную итерации в лямбда?
Какие проблемы я могу вызвать позже?
Ответы
Ответ 1
Рассмотрим этот код:
List<Action> actions = new List<Action>();
for (int i=0; i < 10; i++)
{
actions.Add(() => Console.WriteLine(i));
}
foreach (Action action in actions)
{
action();
}
Что вы ожидаете от печати? Очевидный ответ 0... 9 - но на самом деле он печатает 10, десять раз. Это потому, что есть только одна переменная, которая захватывается всеми делегатами. Это такое поведение, которое неожиданно.
EDIT: Я только что видел, что вы говорите о VB.NET, а не о С#. Я считаю, что VB.NET имеет еще более сложные правила, благодаря тому, как переменные сохраняют свои значения в разных итерациях. Этот пост Джареда Парсонса дает некоторую информацию о тех трудностях, которые были связаны с этим, хотя с 2007 года, поэтому реальное поведение, возможно, изменилось с тех пор.
Ответ 2
Предположим, вы имеете в виду С# здесь.
Это из-за того, как компилятор реализует закрытие. Использование переменной итерации может вызвать проблему с доступом к модифицированному закрытию (обратите внимание, что я сказал, что "может" не "будет" причиной проблемы, потому что иногда это не происходит в зависимости от того, что еще находится в методе, а иногда вы действительно хотите доступ к модифицированному закрытию).
Дополнительная информация:
http://blogs.msdn.com/abhinaba/archive/2005/10/18/482180.aspx
Еще больше информации:
http://blogs.msdn.com/oldnewthing/archive/2006/08/02/686456.aspx
http://blogs.msdn.com/oldnewthing/archive/2006/08/03/687529.aspx
http://blogs.msdn.com/oldnewthing/archive/2006/08/04/688527.aspx