Детский прицел & CS0136 - PullRequest
       16

Детский прицел & CS0136

22 голосов
/ 17 ноября 2008

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

        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. И это техническое ограничение или это было дизайнерское решение? Вот к чему я действительно стремлюсь; -)

Ответы [ 2 ]

12 голосов
/ 17 ноября 2008

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

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

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

РЕДАКТИРОВАТЬ: Чтобы ответить на ваш вопрос, отредактируйте.

Это просто два простых правила:

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

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

РЕДАКТИРОВАТЬ: спецификация языка имеет это сказать об исходном примере лямбда-выражения - это раздел 7.14.1:

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

Это помогает?

0 голосов
/ 17 ноября 2008

Вы объявляете переменную в ограниченной области и пытаетесь использовать ее вне этой области. Компилятор предполагает, что вам не нужен доступ к нему, поэтому вы можете объявить переменную с таким же именем где-нибудь еще в файле. Вы пытаетесь сделать старый трюк на C, предполагая, что переменная будет жить сразу за пределами области видимости. Например, раньше он работал в старых версиях C / 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.
...