Предупреждение: «Использование итерационной переменной в лямбда-выражении может привести к неожиданным результатам» - PullRequest
3 голосов
/ 29 августа 2011

Редактировать : Вот гораздо более простой пример этой проблемы (я удалил мой оригинальный вопрос):

Dim numbers1 As New List(Of Int32)({1, 2, 3})
Dim numbers2 As New List(Of Int32)({3, 4, 5})
For Each n1 In numbers1
    ' no warning '
    Dim contains = numbers2.Contains(n1)
Next
For Each n1 In numbers1
    ' warning on n1'
    Dim contains = (From num In numbers2 Where num = n1).Any
Next

Так что я до сих пор не понимаю, почему компилятор считает, что я могу получить неожиданные результаты во второй итерации, тогда как с первой я в безопасности. Я не думаю, что интересная ссылка @ee-m обеспечивает причину такого поведения (это не проблема for-each, For n1 As Int32 = 1 To 3 также приведет к предупреждению компилятора).

Я не совсем уверен, что следующее должно быть "наилучшей практикой":

For Each n1 In numbers1
    Dim number1 = n1
    ' no warning'
    Dim contains = (From num In numbers2 Where num = number1).Any
Next

Локальная переменная number1 является избыточной и делает код менее читабельным, как уже подчеркивал @ Meta-Knight. Примечание. Все три способа безопасны и дают правильный результат.

Ответы [ 2 ]

4 голосов
/ 29 августа 2011

Эрик Липперт написал пару постов в блоге на эту тему (примеры кода на C #, а не на VB), в которых рассматриваются некоторые «хитрости», которые могут возникнуть из такого рода кода, который вам может показаться интересным:

Закрытие по переменной цикла считается вредным

3 голосов
/ 29 августа 2011

Как говорится в сообщении, оно "может иметь" нежелательные эффекты. В вашем случае .ToList() делает это безопасным, но это трудно проверить компилятору.

Я бы предложил принять копирование в локальную переменную (Dim exc = excel) в качестве стандартной «передовой практики»

...