Имею следующий код:
foreach (NetworkInterfaceInfo info in _comps)
{
Dispatcher.Invoke(() => SpeedLabel.Content += info.NetInterface.Description + " - " + info.IncomeSpeed + "kbps
");
}
На что получаю предупреждение:
Access to foreach variable in closure. May have different behaviour when compiled with different versions of compiler.
Какое "различное поведение" может произойти и в каких случаях?
Ответ
Смотрите.
Цикл foreach (NetworkInterfaceInfo info in _comps) может быть реализован так:
NetworkInterfaceInfo info;
using (var iterator = _comps.GetEnumerator())
{
while (iterator.MoveNext())
{
info = iterator.Current;
// тело вашего цикла
}
}
А может и так:
using (var iterator = _comps.GetEnumerator())
{
while (iterator.MoveNext())
{
NetworkInterfaceInfo info = iterator.Current;
// тело вашего цикла
}
}
В старых версиях использовался первый вариант. При этом если вы выполняете closure по info (то есть, запоминаете текущее значение info в () => SpeedLabel.Content += info.NetInterface.Description...), к моменту фактической отработки функции переменной info может быть уже присвоено другое значение, совсем не то, которое вы ожидали, потому что цикл при этом уже пробежал до конца.
Во втором случае у вас на каждую итерацию свежая переменная, и «изменения» info в цикле нет. При этом каждое замыкание общается со своим экземпляром info
Это и есть то самое изменение поведения, о котором вас предупредил компилятор. Ваш код будет бежать по-разному с разными версиями языка.
Дополнительное чтение по теме:
Closing over the loop variable considered harmful
Closing over the loop variable, part two
Комментариев нет:
Отправить комментарий