Ответ 1
Здесь есть два соответствующих правила.
Первое соответствующее правило:
Это ошибка для локальной переменной пространства декларации и вложенных локальных пространство декларации переменных, содержащее элементы с тем же именем.
(И еще один ответ на этой странице вызывает другое место в спецификации, где мы вызываем это снова.)
Этого достаточно, чтобы сделать это незаконным, но на самом деле второе правило делает это незаконным.
Второе релевантное правило в С#:
Для каждого случая данного идентификатор как простое имя в выражения или декларатора в пределах локальное пространство декларации переменных, немедленно закрывающий блок, или switch-block этого события, каждое другое возникновение того же идентификатор как простое имя в выражения или декларатора в пределах немедленно вставляя блок или блок switch должен ссылаться на тот же организация. Это правило гарантирует, что значение имени всегда одно и то же в пределах данного блока, блок переключателя, for-, foreach- или use-statement или анонимная функция.
Вам также нужно знать, что for-loop рассматривается так, как будто есть все невидимые фигурные скобки.
Теперь, когда мы это знаем, давайте аннотируем ваш код:
public void MyMethod()
{ // 1
int i=10; // i1
{ // 2 -- invisible brace
for(int x=10; x<10; x++) // x2
{ // 3
int i=10; // i3
var objX = new MyOtherClass(); // objX3
} // 3
} // 2
var objX = new OtherClasOfMine(); // objX1
} // 1
У вас есть три "простых имени", i, x и objX. У вас есть пять переменных, которые я обозначил i1, x2, i3, objX3 и objX1.
Самый внешний блок, который содержит использование я и objX, является блоком 1. Поэтому в блоке 1 я и objX должны всегда ссылаться на одно и то же. Но они этого не делают. Иногда я ссылаюсь на i1, а иногда на i3. То же самое с objX.
x, однако, только когда-либо означает x2 в каждом блоке.
Кроме того, обе переменные "i" находятся в одном и том же локальном пространстве декларации переменных переменных, как и "objX".
Следовательно, эта программа является ошибкой несколькими способами.
В вашей второй программе:
public void MyMethod()
{ // 1
{ // 2 -- invisible
for(int x=10; x<10; x++) // x2
{ // 3
int i=10; // i3
var objX = new MyOtherClass(); // objX3
} //3
} // 2
{ // 4 -- invisible
for(int x=10; x<10; x++) // x4
{ // 5
int i=10; // i5
var objX = new MyOtherClass(); // objX5
} //5
} // 4
} // 1
Теперь у вас снова три простых имени и шесть переменных.
Внешние блоки, которые сначала содержат использование простого имени x, являются блоками 2 и 4. На протяжении второго блока x относится к x2. На протяжении блока 4 x относится к x4. Поэтому это законно. То же самое с я и objX - они используются в блоках 3 и 5 и означают разные вещи в каждом. Но нигде одно и то же простое имя не означает, что в одном блоке означают две разные вещи.
Теперь вы можете заметить, что с учетом всего блока 1, x используется для обозначения как x2, так и x4. Но не упоминается x, которое находится внутри блока 1, но НЕ также внутри другого блока. Поэтому мы не считаем несогласованное использование в блоке 1 релевантным.
Кроме того, ни одно из пространств декларации не перекрывается незаконными способами.
Поэтому это законно.