Child Scope & CS0136

Следующий код не может скомпилировать: "Локальная переменная с именем" st "не может быть объявлена ​​в этой области, потому что она придавала бы значение" st ", которое уже используется в области" child ", чтобы обозначить что-то еще":

        var l = new List<string>();
        l.Find(st => st.EndsWith("12"));
        string st = "why this fails?";

Я понимаю, почему это не сработает:

        string preParent = "";
        {
            string preParent = "Should fail cause we change the meaning";
        }

Когда мы делаем следующее, получаем "CS0103: имя" postParent "не существует в текущем контексте":

        {
            string postParent=string.Empty;
        }
        postParent = "Should this work?";

Я не понимаю, почему компилятор достаточно умен, чтобы увидеть, что postParent не входит в область видимости, но не позволит мне определить новую переменную, которая имеет то же имя, что и переменная, используемая в пределах дочерней области (которая очевидно, выходит за рамки этого пункта).

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

===========

Отредактировано:

Я думаю, что интересным является то, как вы можете иметь одну и ту же переменную в двух дочерних областях в одном методе, поэтому это действительно:

        {
            string thisWorks= string.Empty;
        }
        {
            string thisWorks= "Should this work?";
        }

Мне просто любопытно, что у вас могут быть две переменные с тем же именем, если они находятся на одном уровне (если вы посмотрите на область как дерево). Это имеет смысл, потому что вы можете иметь локальные переменные в двух методах одного и того же класса с тем же именем.

Я просто удивлен, что компилятор способен дифференцировать и разрешить это, в то время как он не позволит переменную postParent. И это техническое ограничение или это дизайнерское решение? Это то, к чему я действительно пытаюсь добраться, -)

Ответ 1

Да, компилятор реализует область действия. Обратите внимание, что область действия переменной - это лексический блок, частью которого она является, а не только с точки объявления, но и весь объем.

Компилятор жалуется, потому что назначение postParent выходит за пределы его области (это всего лишь вложенные фигурные скобки). Если вы попытались объявить новую переменную в том месте, где вы в настоящее время назначаете postParent, проблема будет связана с вложенным блоком, поскольку область postParent будет включать этот вложенный блок, даже если это было до объявления.

Области описаны в разделе 3.7 спецификации С# 3.0.

РЕДАКТИРОВАТЬ: отредактировать свой вопрос.

Это всего лишь два простых правила:

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

Я уверен, что язык мог быть спроектирован таким образом, что область видимости только начиналась в точке объявления, но я думаю, что проще (с точки зрения сложности языка) рассматривать области как просто блоки, поэтому все локальные переменные, объявленные в например, один и тот же блок имеет такую ​​же область видимости. Это делает жизнь намного проще при рассмотрении захваченных переменных, так как захват зависит от области действия, а вложенные области делают жизнь интересной...

EDIT: спецификация языка должна сказать об исходном примере выражения лямбда - раздел 7.14.1:

Необязательный анонимная функция-подпись анонимная функция определяет имена и, при необходимости, типы формальных параметры анонимной функции. Объем параметров анонимной функцией является анонимная функция тело. Вместе с список параметров (если задано), тело анонимного метода представляет собой пространство декларации. По этой причине является ошибкой времени компиляции для имени параметра анонимного функция, соответствующая имени локальной переменная, локальная константа или параметр в сферу выражение анонимного метода или лямбда-выражение.

Помогает ли это?

Ответ 2

Вы объявляете переменную в ограниченной области действия и пытаетесь использовать ее вне этой области. Компилятор предполагает, что вам не нужен доступ к нему, поэтому вы можете объявить переменную с тем же именем в другом месте в файле. Ваша попытка выполнить старый трюк, предполагающий переменную, будет немедленно выходить за пределы области действия. Например, это использовалось для работы в более старых версиях C/С++, но больше не работает.

for (int i=0; i<10; i++)
{
    cout <<"In the loop i is "<< i << endl;
}
cout << "outside of the loop i is " << i << endl; //this only compiles with old C/C++ compilers.