儿童范围& CS0136

时间:2008-11-17 20:18:18

标签: c# compiler-construction scope

以下代码无法编译声明“在此范围内无法声明名为'st'的局部变量,因为它会给'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变量。这是技术限制还是设计决策?这就是我真正想要的; - )

2 个答案:

答案 0 :(得分:12)

是的,编译器正在强制执行范围。请注意,变量的范围是它所属的词汇块 - 不仅仅是从声明开始,而是整个范围。

编译器抱怨,因为postParent的赋值超出了它的范围(它只是嵌套的大括号)。如果您尝试在当前分配给postParent的位置声明一个新变量,则问题将出现在嵌套块上,因为postParent的范围将包括嵌套块,即使它在宣言之前。

范围在C#3.0规范的第3.7节中描述。​​

编辑:回复您的问题编辑。

这只是两个简单的规则:

  • 当另一个具有相同名称的本地变量在范围
  • 时,您无法声明局部变量
  • 局部变量的范围是声明发生的块

我确信语言可以设计为范围仅在声明点开始,但我认为将范围视为块只是更简单(在语言复杂性方面) - 所以所有局部变量都在声明例如,相同的块具有相同的范围。这也使得在考虑捕获的变量时生活变得更加简单 - 因为捕获的内容取决于范围,嵌套的范围使生活变得有趣......

编辑:语言规范有关于原始lambda表达式示例的说法 - 它的第7.14.1节:

  

可选   匿名函数签名   匿名函数定义名称   以及可选的正式类型   匿名函数的参数。   参数的范围   匿名函数是   匿名函数体。和...一起   参数列表(如果给定),   匿名方法体构成了一个   宣言空间。出于这个原因,它   是名称的编译时错误   匿名的参数   用于匹配本地名称的函数   变量,局部常量或参数   其范围包括   anonymous-method-expression或   λ-表达。

这有帮助吗?

答案 1 :(得分:-2)

您在有限范围内声明变量并尝试在该范围之外使用它。编译器假定您不希望访问它,因此您可以在文件中的其他位置声明具有相同名称的变量。你试图做旧的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.