Используя Visual Studio 2013, я пытаюсь воспроизвести полученную информацию, упомянутую в блоге Эрика Липперта "Closing over the loop variable considered harmful".Воспроизведение «закрыть по переменной foreach» gotcha
В свойствах проекта я выбрал «C# 3.0» в качестве языковой версии (Build> Advanced ...). Кроме того, я выбрал «.NET Framework 3.5» как целевую структуру, как будто я считаю, что это не обязательно, поскольку это касается только языка.
Запуск его код:
using System;
using System.Collections.Generic;
namespace Project1
{
class Class1
{
public static void Main(string[] args)
{
var values = new List<int>() { 100, 110, 120 };
var funcs = new List<Func<int>>();
foreach (var v in values)
{
funcs.Add(() => v);
}
foreach (var f in funcs)
Console.WriteLine(f());
}
}
}
Ожидаемый результат:
120 120 120
Фактический выход:
100 110 120
Как ответил Eric Lippert himself в "Is there a reason for C#'s reuse of the variable in a foreach?":
Цикл
for
не будет изменен, и изменение не будет перенесено обратно в предыдущие версии C#. Поэтому вы должны быть осторожны при использовании этой идиомы.
Что я делаю неправильно?
Когда код действительно сломается? Я думаю, если бы код опирался на ошибку в старом компиляторе, который затем фиксируется или новый компилятор вводит ошибку. Существуют ли другие сценарии, где это может быть полезно? – xehpuk
@xehpuk: Я не уверен, что понимаю ваш вопрос. Разумеется, код, основанный на ошибках фиксированного компилятора, будет прерываться независимо от значения переключателя langversion. Команда компилятора очень старательно сохраняет обратную совместимость при исправлении ошибок, но это не всегда возможно. –
Вы правы, это все тот же компилятор. Таким образом, вариант использования в основном состоит в том, что один член проекта имеет более новую версию компилятора, но не может легко использовать старшую (потому что, например, он использует более новую версию VS, которая по какой-либо причине не имеет этого параметра). – xehpuk