Область действия цикла for при объявлении переменной
Я столкнулся с этим странным поведением, когда я кодировал. Поэтому я спрашиваю это здесь.
Какова сфера for
цикл при объявлении переменных?
Этот код прекрасно компилируется
for (int i = 0; i < 10; i++) { }
for (int i = 0; i < 10; i++) { }
Это означает, что оба int i
не в том же объеме.
Но этот код не компилируется.
for (int i = 0; i < 10; i++) { }
int i; // Conflicts with both first loop and second one.
for (int i = 0; i < 10; i++) { }
Это означает, что int i
в середине цикла имеет одинаковую область видимости первого цикла и второго цикла.
Но как можно int i
в двоем for
петли имеют различную область видимости, но одинаковую область с серединой int i
? Потому что в настоящее время я вижу их на одном уровне.
Я знаю, что второй код не компилируется. Почему первый код компилируется тогда, если есть проблемы в областях. Это исключение внутри компилятора?
6 ответов
Компилятор C# не проверяет, была ли переменная объявлена до или после другой переменной. Все, что имеет значение, это масштаб. i
переменная, объявленная между циклами, безусловно, конфликтует со вторым циклом, потому что если вы используете i
внутри цикла нет способа различить, какие i
Вы хотели бы использовать. Что касается первого цикла, ошибка по-прежнему отображается, потому что блок, где i
объявлен инкапсулирует также первый цикл.
Например, следующее не скомпилируется, даже если j
не виден за пределами внутренних скобок, поэтому не должно быть никакой двусмысленности в отношении i
:
{
{
int i = 1;
int j = 1;
}
int i = 0; // compiler error: A local variable i cannot be declared in this scope (...)
// j is not visible here
}
Изменить относительно комментария:
Почему следующий штраф?
{
for(int i = 1; i < 10; i++) {}
for(int i = 1; i < 10; i++) {}
}
Когда вы объявляете for
переменная цикла, она видна только внутри блока цикла. Это означает, что области действия обеих переменных не пересекаются, поскольку нет строки кода, где один блок "перекрывает" другой.
Объем цикла for, for(INIT; COND; INCR) { BLOCK }
идентичен в области видимости
{
INIT;
while (COND) {
BLOCK;
INCR;
}
}
Таким образом, цикл for лучше всего рассматривать как две вложенные области видимости. (Примечание: приведенное выше преобразование из for
в while
неправильно фиксирует поведение continue
, Однако этот вопрос не на этом сфокусирован)
Проблема, с которой вы столкнулись с int i
вне цикла for есть что-то, что называется "shadowing". В C++, если вы объявили переменную области действия с тем же именем, что и что-то во внешней области видимости, вы "затеняли ее", скрывая ее, пока область не закончилась. Когда они разработали C#, они чувствовали, что это слишком нелогично и чревато ошибками. В C# это синтаксическая ошибка, чтобы скрыть переменную из внешней области видимости. Вводя int i
к внешнему объему, это теперь незаконно для for
петли, чтобы представить это сами.
Переменная, объявленная в цикле for, имеет только область видимости для блока цикла, но когда вы объявляете переменную вне цикла for, вы не можете иметь такую же переменную имени внутри цикла for, потому что это сбивает с толку компилятор ту переменную, которую вы имеете в виду для тела цикла.
Как я возьму ваш код в качестве примера:
int i =0;
for (int i = 0; i < 10; i++)
{
i = i+1; // now compiler is confused which i you mean here, so i complains on compile time that you have two with same name
}
Так что если вы объявите это между циклами, как вы сделали, переменная i
имеет область действия в обоих циклах for, поэтому она доступна в обоих циклах, поэтому, если вы удалите первый цикл, он все равно будет жаловаться из-за глобальной области видимости переменной вне цикла:
for (int i = 0; i < 10; i++)
{
i = i+1; // now compiler is still confused which i you mean
}
int i =0;
Я не думаю, что это важно, где вы положили int i;
,
Компилятор сначала сканирует поле, после чего начинает поиск выражений. Это не компилируется, потому что i
уже признан в качестве поля.
В этом нет ничего странного. Во втором случае вы определили внешний i
а затем попробуйте переопределить его в каждом цикле.
Переменные, объявленные в for
операторы являются локальными для цикла, но вы уже определили другую переменную с тем же именем во внешней области видимости.
Я думаю, что вы уже задали еще один ограничительный вопрос, предполагая, что область действия переменной начинается с точки объявления?
Область действия переменной - это блок, в котором она определена, и на нее не влияет ее размещение. Хотя компилятор откажется использовать переменную до объявления, он все еще находится в области видимости
int i
; Вы объявляете вне цикла доступным для текущей функции. Либо объявляю только внешний int i
и удалить int i
из обоих циклов, или просто удалите эту внешнюю переменную.