Почему не может быть объявлено дублируемое имя переменной во вложенной локальной области?
Основываясь на этом недавнем question, я не понимаю ответа. Похоже, вы должны быть способны сделать что-то подобное, поскольку их области не перекрываются
static void Main()
{
{
int i;
}
int i;
}
Этот код не может скомпилироваться со следующей ошибкой:
Локальная переменная с именем "i" не может быть объявлена в этой области, потому что она будет иметь другое значение для "i", которое уже используется в области "child", чтобы обозначить что-то еще
Ответы
Ответ 1
Я не думаю, что какой-либо из ответов до сих пор получил ключевую строку из спецификации.
Из раздела 8.5.1:
Область локальной переменной, объявленной в объявлении локальной переменной, содержит блок, в котором происходит объявление. Ошибочно ссылаться на локальную переменную в текстовой позиции, которая предшествует локальному переменному-декларатору локальной переменной. В рамках локальной переменной ошибка времени компиляции объявляет другую локальную переменную или константу с тем же именем.
(Подчеркните мой.)
Другими словами, область для "более поздней" переменной включает в себя часть блока перед объявлением, то есть включает в себя "внутренний" блок, содержащий "более раннюю" переменную.
Вы не можете ссылаться на более позднюю переменную в месте раньше своего объявления - но все еще в области.
Ответ 2
"Объем локальной или постоянной переменной продолжается до конца текущего блока. Вы не можете объявить другую локальную переменную с тем же именем в текущем блоке или в любых вложенных блоках". С# 3.0 в двух словах, http://www.amazon.com/3-0-Nutshell-Desktop-Reference-OReilly/dp/0596527578/
"Локальное пространство объявления переменной блока включает любые вложенные блоки. Таким образом, внутри вложенного блока невозможно объявить локальную переменную с тем же именем, что и локальная переменная в закрывающем блоке." Переменные области, MSDN, http://msdn.microsoft.com/en-us/library/aa691107%28v=vs.71%29.aspx
На стороне примечания это совершенно противоположно правилам JavaScript и F #.
Ответ 3
Из Спецификация языка С#:
Локальное пространство объявления переменной блока включает любые вложенные блоки. Таким образом, внутри вложенного блока невозможно объявить локальную переменную с тем же именем, что и локальная переменная в закрывающем блоке.
По существу, это не допускается, потому что в С# их области действительно перекрываются.
edit: просто для пояснения, область С# разрешена на уровне блока, а не по строке. Поэтому, хотя верно, что вы не можете ссылаться на переменную в коде, которая предшествует ее объявлению, также верно, что ее область действия полностью возвращается к началу блока.
Ответ 4
Это было правило в С# из первой версии.
Разрешение совпадающих областей приведет только к путанице (программистов, а не компилятора).
Так что это было запрещено специально.
Ответ 5
Это не вопрос перекрытия областей. В С# простое имя не может означать больше одного объекта в блоке, где он был объявлен. В вашем примере имя i
означает две разные вещи внутри одного и того же внешнего блока.
Другими словами, вы должны иметь возможность перемещать объявление переменной в любое место внутри блока, где оно было объявлено, не вызывая перекрытия областей. Сменив ваш пример на:
static void Main()
{
int i;
{
int i;
}
}
приведет к перекрытию областей различных переменных i
, ваш пример является незаконным.
Ответ 6
Для С#, ISO 23270 (Информационные технологии - Программирование
языки - С#), & sect; 10.3 (Декларации):
Каждый блок, блок switch, for-statement, foreach-statement или using-statement создает пространство декларации для локальных переменных и локальные константы, называемые пространством объявлений локальной переменной. Имена введенные в это пространство декларации через локальные переменные-объявления и локальные константы.
Если блок является телом экземпляра конструктор, метод или оператор, или get или set accessor для объявление индексатора, параметры, объявленные в таком объявлении, являются члены локального пространства декларации переменных блоков.
Если блок является тело общего метода, параметры типа, объявленные в таком объявлении являются членами локального пространства декларации переменных блоков.
Это ошибка для двух членов локального пространства переменных переменных с одинаковым именем. Это ошибка для локального пространства декларации переменных и вложенных локальных переменных пространство декларации переменных, чтобы содержать элементы с тем же именем.
[Примечание: Таким образом, внутри вложенного блока невозможно объявить локальный переменная или константа с тем же именем, что и локальная переменная или константа в закрытом блоке. Возможно, чтобы два вложенных блока содержали элементы с тем же именем, если ни один из блоков не содержит другого. end note]
Итак,
public void foobar()
{
if ( foo() )
{
int i = 0 ;
...
}
if ( bar() )
{
int i = 0 ;
...
}
return ;
}
является законным, но
public void foobar()
{
int i = 0 ;
if ( foo() )
{
int i = 0 ;
...
}
...
return ;
}
не является законным. Лично я считаю, что это ограничение довольно раздражает. Я вижу, как выдает предупреждение компилятора о перекрытии областей, но ошибка компиляции? Слишком много ремней и подтяжек, ИМХО. Я мог видеть достоинство опции компилятора и/или прагмы, хотя (возможно, -pedantic
/-practical
, #pragma pedantic
vs #pragma practical
, B^)
).
Ответ 7
Я просто скомпилировал это в GCC как C, так и С++. Я не получил сообщение об ошибке, поэтому он выглядит как синтаксис.
Ваш вопрос помечен как .net и c. Должно ли это быть помечено как С#? Этот язык может иметь разные правила, чем C.
Ответ 8
В C вам нужно поместить все объявления переменных в самом начале блока. Они должны поступать сразу после открытия {
перед любыми другими инструкциями в этом блоке.
Итак, что вы можете сделать, чтобы скомпилировать это:
static void Main()
{
{
int i;
}
{
int i;
}
}
Ответ 9
Вот ваш ответ от Документация MSDN.NET:
... Локальное пространство объявления переменной блока включает любые вложенные блоки. Таким образом, внутри вложенного блока невозможно объявить локальную переменную с тем же именем, что и локальная переменная в закрывающем блоке.