Рассмотрим следующее
Dim nofTries As Integer
For nofTires = 1 To 5
If (condition) Then Exit For
Next
Если из-за опечатки счетчик цикла отличается от объявленной переменной. Тем не менее, несмотря на настройку «явной опции», НЕТ предупреждения или ошибки компилятора, и это действовало так, как если бы:
Dim nofTries As Integer
For nofTires As Integer = 1 To 5
If (condition) Then Exit For
Next
Есть ли объяснение тому, почему компилятор взял на себя задачу принять тип вместо того, чтобы выдать ошибку?
Опция Explicit здесь не имеет значения. Начиная с .NET Framework 1.1, оператор For сам по себе считается объявлением, если указанная переменная еще не объявлена. Здесь уместен вариант Option Strict, потому что без вывода типа вам нужно будет указать тип данных объявляемой переменной. При выведении типа вам не требуется предложение As, если тип можно вывести из инициализирующего выражения. Поскольку 1 является целым числом, предполагается, что переменная имеет тип Integer.
Это связано с включением OPTION INFER. Выключите его и появится нужная ошибка компилятора. Источником недоразумения для меня было то, что эта опция на самом деле не существует в VBA, но также и то, что она включена по умолчанию, тогда как отключение кажется более разумным.
Не только из-за включения Option Infer
, но и из-за того, что в операторе For
разрешено объявление переменной. Если бы у вас был nofTires = 1
где-то еще, это все равно было бы ошибкой необъявленной переменной, а не объявлением новой переменной с выведенным типом, как это происходит в цикле For
.
Отключение Option Infer по умолчанию абсолютно неразумно. Вывод типа был введен специально для поддержки LINQ и требуется в определенных сценариях LINQ.
Да, это неудачный результат сочетания Option Explicit
с Option Infer
.
Однако я считаю ошибкой читать из этого, что вам следует избегать Option Infer
. Эта опция позволяет реализовать некоторые действительно приятные вещи в современном VB.Net, особенно (но не исключительно) в отношении Linq. В большинстве сценариев вам действительно нужно включить Option Infer
(как и Explicit
).
Традиционные циклы For
— неудачный случай, потому что они позволяют вам использовать цикл для объявления переменной, удовлетворяющей Option Explicit
, а затем Option Infer
может позволить вам опустить определение типа, поэтому синтаксис выглядит как «просто используйте переменную», даже если вы набрали это неправильно... даже если при внимательном рассмотрении мы увидим, что переменная фактически объявлена, а также ей присвоен определенный тип посредством вывода.
Хитрость в том, что люди предпочитают меньше/более короткий код. Зачем печатать больше? Поэтому любой, кто работал с современным VB.Net в течение сколько-нибудь значимого периода времени, предпочтет идиоматически написать цикл без отдельной строки для определения переменной, например так:
For nofTires As Integer = 1 To 5
If (condition) Then Exit For
Next
Обратите внимание, что имя переменной по-прежнему неверно, но оно имеет значение только в том случае, если вы последовательно используете одно и то же имя (правильное или неправильное) внутри цикла. Если затем вы попытаетесь использовать «правильный» nofTries
внутри этого цикла, код завершится ошибкой, поскольку переменная не была объявлена. Это даст программисту возможность исправить ситуацию. Таким образом, мы также видим, что дополнительная строка для объявления переменной — это не просто дополнительная типизация или личные предпочтения, но она также активно делает ваш код более хрупким.
Кроме того, пользователи современного идиоматического VB.Net, как правило, вообще имеют меньше традиционных циклов For
, предпочитая вместо этого использовать операцию For Each
или linq, а это означает, что эта проблема не возникает так часто, как вы думаете.
Мне интересно, можно ли получить предупреждение компилятора (или анализатора) (а не об ошибке) для кода, в котором переменная, определенная в цикле For
, никогда не используется... но есть и законные практические причины сделать это, когда количество итерации - это то, что важно, и значение индекса каждой итерации не требуется.
Спасибо, это интересно, так как я ничего не знал о LINQ. Моей целью было узнать, сколько итераций выполнен цикл, и я был просто поражен, увидев, что счетчик всегда был равен нулю после выхода из цикла, пока я не заметил необычную опечатку. после этого я потратил почти час, пытаясь понять, почему явная опция не работает так, как я ожидал.
Этот вопрос не имеет ничего общего с областью действия переменной. Речь идет о выводе типа. Область переменной может возникнуть, если вы попытаетесь использовать
nofTires
после оператораnext
.