Переменная, объявленная внутри цикла for. Как мне сделать это с ошибкой во время компиляции? - PullRequest
10 голосов
/ 27 марта 2012

Сегодня я исследовал логическую ошибку в нашем программном обеспечении и выяснил, что это связано с тем, как переменные потока VB.NET внутри цикла.

Допустим, у меня есть следующий код:

    Dim numbers As New List(Of Integer) From {1, 2, 3, 4, 5}
    For Each number As Integer In numbers

        Dim isEven As Boolean

        If number Mod 2 = 0 Then
            isEven = True
        End If

        If isEven Then
            Console.WriteLine(number.ToString() & " is Even")
        Else
            Console.WriteLine(number.ToString() & " is Odd")
        End If

    Next

производит следующий вывод

1 is Odd
2 is Even
3 is Even
4 is Even
5 is Even

Проблема в том, что isEven объявлен, но не назначен. В этом конкретном случае было бы правильно написать dim isEven as Boolean = false, но я этого не сделал.

В VB.NET переменная, объявленная внутри цикла for, сохраняет свое значение для следующей итерации. Это специально: http://social.msdn.microsoft.com/Forums/en/vblanguage/thread/c9cb4c22-d40b-49ff-b535-19d47e4db38d, но это также опасная ловушка для программистов.

Однако до сих пор я не знал об этой проблеме / поведении. До сих пор. В любом случае, большая часть нашей базы кода - это C #, которая не позволяет использовать неинициализированную переменную, поэтому проблем нет.

Но у нас есть некоторый устаревший код, написанный на VB.NET, который мы должны поддерживать.

Я не думаю, что кто-либо из нашей команды разработчиков когда-либо использовал это специально. Если я явно хочу поделиться переменной над итерациями внутри цикла for, я объявляю ее вне области действия.

Так что лучше всего было бы создать предупреждение или даже ошибку в этом конкретном случае. Но даже с Option Explicit / Option Strict это не генерирует предупреждение / ошибку.

Есть ли способ сделать это ошибкой во время компиляции или, может быть, способ проверить это с помощью FxCop?

Ответы [ 3 ]

2 голосов
/ 27 марта 2012

Я не думаю, что кто-то из нашей команды разработчиков когда-либо использовал это специально. Если я явно хочу совместно использовать переменную по итерациям внутри цикла for, я объявляю ее вне области действия.

Полагаю, весь смысл объявления переменной внутри цикла состоит в том, чтобы явно ограничить ее область действия этим блоком. Чтобы сделать это, ошибка времени компиляции удалила бы область действия уровня блока из языка. Хотя, безусловно, существуют случаи, когда область действия уровня метода имеет смысл, не может быть сомнений и в важности области действия уровня блока. Я не думаю, что вы можете легко вырезать это из языка без введения какого-либо нового синтаксического метода его использования. На данный момент вы вступаете в сферу реорганизации VB.NET - я не уверен, что есть простой способ сделать это.

0 голосов
/ 31 июля 2012

Если вы считаете, что это может быть проблемой с вашей кодовой базой или вашими программистами, в своем стиле кодирования укажите, что все неинициализированные переменные объявляются в начале процедуры. Это было общим руководством по стилю (особенно для VB) до преобладания умозаключений типа.

Конечно, это не помогает избежать проблемы, а только делает ее более очевидной.

0 голосов
/ 27 марта 2012

Посмотрите на код ниже.Если запрещение объявления без инициализации является ошибкой компилятора, то этот код не будет выдавать правильный вывод (промежуточное количество четных чисел).Если вы заставите меня инициализировать значение «total», то метод никогда не будет корректным.

Dim numbers As New List(Of Integer) From {1, 2, 3, 4, 5, 6, 8, 9, 10}
For Each number As Integer In numbers

    Dim total As Integer

    Dim isEven As Boolean = (number Mod 2 = 0)

    If isEven Then
        total += number
        Console.WriteLine("Running Total: {0}", total)
    End If
Next

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...