Подтвердить что ты не робот

Область цикла '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? Потому что в настоящее время я вижу их на одном уровне.

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

4b9b3361

Ответ 1

Компилятор С# не проверяет, была ли переменная объявлена ​​до или после другой переменной. Все, что имеет значение, - это область. Переменная 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, она видна только внутри блока цикла. Это означает, что области действия обеих переменных не пересекаются, поскольку нет строки кода, где один блок "перекрывает" другой.

Ответ 2

Объем цикла for, for(INIT; COND; INCR) { BLOCK } идентичен по шкале до

{
    INIT;
    while (COND) {
        BLOCK;
        INCR;
     }
 }

Таким образом, цикл for лучше всего рассматривать как две вложенные области. (Примечание: приведенное выше преобразование от for до while не правильно фиксирует поведение continue. Однако этот вопрос не фокусируется на этом)

Проблема, с которой вы столкнулись с int i вне цикла for, называется "затенением". В С++, если вы объявили переменную с областью с тем же именем, что и нечто во внешней области, вы "затеняли ее", молча закрывая ее до тех пор, пока область не закончится. Когда они разработали С#, они чувствовали, что это слишком противоречиво, и слишком склонны к ошибкам. В С# это синтаксическая ошибка, чтобы затенять переменную из внешней области. Вводя int i во внешний охват, теперь петли for теперь нелегально вводят его.

Ответ 3

Переменная, объявленная в цикле for, имеет только область внутри цикла цикла, но когда вы объявляете переменную out for loop, вы не можете иметь такую ​​же переменную имени внутри цикла for, потому что она путает компилятор, какую переменную вы имеете в виду для цикла loop тела.

Как я возьму ваш код в качестве примера:

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 (int i = 0; i < 10; i++) 
{
  i = i+1; // now compiler is still confused which i you mean 
}
int i =0;

Ответ 4

Ничего странного не происходит. Во втором случае вы определили внешний i, а затем попытаетесь переопределить его в каждом цикле.

Переменные, объявленные в инструкции for, являются локальными для цикла, но вы уже определили другую переменную с тем же именем во внешней области.

Я думаю, вы уже задали другой вопрос, предполагающий, что область действия переменной начинается с точки объявления?

Область переменных - это блок, в котором он определен, на его размещение не влияет. Хотя компилятор откажется использовать переменную перед объявлением, она все еще находится в области

Ответ 5

Я не думаю, что это важно, если вы положили int i;.

Сначала компилятор сканирует это поле, после чего начинает сканирование выражений. Он не компилируется, потому что i уже распознан как поле.

Ответ 6

int i; Вы объявляете вне цикла доступным для текущей функции. Либо объявляйте только внешний int i, и удаляйте int i из обоих циклов, либо просто удаляйте эту внешнюю переменную.