Здесь есть два соответствующих правила.
Первое соответствующее правила является:
Это ошибка для локального переменной декларации пространства и вложенного локального объявления переменных пространства содержит элементов с тем же именем.
(И еще один ответ на этой странице взывает другое место в спецификации, где мы называем это снова.)
Это само по себе достаточно, чтобы сделать это незаконно, но на самом деле второе правило делает это незаконно ,
Второе соответствующее правило в C# является:
Для каждого вхождения данного идентификатора в качестве простого-имени в качестве экспрессии или описатель, в пределах локального переменного пространства, немедленно вмещающий блока или включение блока этого возникновения, каждый другой случай одного и тот же идентификатора в качестве простого имени- в экспрессии или описателе в пределах непосредственно охватывающий блок или коммутирующий блок должен ссылаться на тот же объект . Это правило гарантирует, что значение имени всегда совпадает с в рамках данного блока, блок-переключатель, for-, foreach- или using-statement или анонимная функция.
Вам также необходимо знать, что для цикла используется как будто есть невидимые фигурные скобки вокруг всего.
Теперь, когда мы знаем, что, давайте аннотировать код:
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.
Самый внешний блок, который содержит использование i и objX, является блоком 1. Поэтому в блоке 1 i и 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. В течение всего блока 2 x относится к x2. На протяжении блока 4 x относится к x4. Поэтому это законно. То же самое с i и objX - они используются в блоках 3 и 5 и означают разные вещи в каждом. Но нигде одно и то же простое имя не означает, что в одном блоке означают две разные вещи.
Теперь вы можете заметить, что с учетом всего блока 1, x используется как x2, так и x4. Но нет упоминания о x, который находится внутри блока 1, но НЕ также внутри другого блока. Поэтому мы не считаем несогласованное использование в блоке 1 релевантным.
Кроме того, никакие пространства объявлений не перекрываются незаконными способами.
Таким образом, это законно.
Спасибо, что было очень описательно. –
Легко запомнить это, как правило ... но некоторые из них не могут понять, почему это ограничено, первый код и objX: я создал переменную в блоке, и когда я выхожу из цикла, это будет закончено , так же, как я не могу получить доступ к нему за пределами блока. –
Посмотрите на это так. Всегда должно быть законным перемещать объявление переменной UP в исходный код, если вы храните его в одном блоке, верно? Если бы мы сделали это так, как вы предлагаете, то это иногда было бы законным, а иногда и незаконным! Но то, что мы действительно хотим избежать, это то, что происходит на C++ - на C++, иногда перемещение объявления переменной фактически меняет привязки других простых имен! –