2013-09-05 3 views
7

Я выполнил следующий код с C# 3.5 и 4.0. Результаты совершенно разные.Разница в результатах запроса LINQ в .NET 3.5 и 4.5

static void Main() 
    {  
     int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 
     List<IEnumerable<int>> results = new List<IEnumerable<int>>(); 

     foreach (var num in numbers) 
     { 
      results.Add(numbers.Where(item => item > num)); 
     } 

     foreach (var r in results) 
     { 
      Console.WriteLine("{0}", r.Count()); 
     }   
    } 

с Microsoft (R) Visual C# 2008 Compiler версии 3.5.30729.5420 выход 0 0 0 0 0 0 0 0 0 0.

Но с Microsoft (R) Visual C# компилятор версии 4.0.30319.17929 вывод 9 8 7 6 5 4 3 2 1 0.

У меня есть слабое представление о том, что это из-за отложенного исполнения или ленивой оценки, но не ясно поняли, как она несет ответственность за разные выходы здесь.

Исправление: К сожалению это .NET 3.5 и 4.5, а также добавлены версии компилятора Пожалуйста, поясните.

+2

Я получаю тот же результат в 3.5 и 4.0, {9 8 7 ...}, вы уверены, что не делаете что-то другое? –

+0

Это дает мне те же результаты .... – Habib

+3

Я считаю, что это изменение произошло с 4.5, а не 4.0. –

ответ

7

С C# 5 переменная цикла в foreach скомпилирована таким образом, что она существует внутри области цикла, а не вне ее.

Это означает, что когда вы закрываете переменную цикла, вы получаете разные результаты.

Here's what Eric Lippert должен был сказать об исходной проблеме.

+6

Это с тех пор, как C# 5.0, а не .NET 4.0. – Servy

+0

Gotcha. Благодарю. – spender

+1

Это не отвечает на вопрос. OP запрашивает C# 4.0. но ваш вопрос о C# 5.0 –

6

Вы получили доступ к переменной внутри замыкания, поэтому результаты будут отличаться в разных версиях компилятора.

В C# 5.0 переменная переопределяется на каждой итерации цикла, тогда как в предыдущих версиях C# она определялась только один раз.

Для получения дополнительной информации см Эрика Липперт великого blog post

заметнее, открывающий пункт:

UPDATE: Мы принимаем отключающие изменения. В C# 5 переменная цикла foreach будет логически внутри цикла, и поэтому замыкания будут закрываться по новой копии переменной каждый раз. Цикл «для» не будет изменен. Мы вернем вас к нашей оригинальной статье.

+1

Объем переменной имеет * ничего *, связанный с версией .NET. Он имеет все, что связано с версией C#. Он был изменен в C# 5.0. – Servy

+0

Вы читали блог eric 'Мы принимаем разрушительные изменения. В C# 5' –

+0

@Servy Да, я разъяснил это, спасибо. – mattytommo

Смежные вопросы