22

以下代码无法编译,说明“无法在此范围内声明名为 '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 变量。这是技术限制还是设计决定?这就是我真正想要达到的目的;-)

4

2 回答 2

13

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

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

范围在 C# 3.0 规范的第 3.7 节中进行了描述。

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

这只是两个简单的规则:

  • 当另一个同名的局部变量在范围内时,您不能声明局部变量
  • 局部变量的范围是声明发生的块

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

编辑:语言规范对原始 lambda 表达式示例有这样的说法 - 这是第 7.14.1 节:

匿名函数的可选匿名函数签名定义匿名函数的形式参数的名称和可选类型。匿名函数的参数范围是anonymous-function-body。与参数列表(如果给定)一起,匿名方法体构成了一个声明空间。因此,匿名函数的参数名称与范围包括匿名方法表达式或 lambda 表达式的局部变量、局部常量或参数的名称匹配是编译时错误。

这有帮助吗?

于 2008-11-17T20:24:50.427 回答
-2

您在有限范围内声明变量并尝试在该范围之外使用它。编译器假定您不想访问它,因此您可以在文件的其他位置声明一个具有相同名称的变量。您尝试执行假设变量将立即存在于范围之外的旧 C 技巧。例如,这曾经在旧版本的 C/C++ 中有效,但现在不再有效。

for (int i=0; i<10; i++)
{
    cout <<”In the loop i is “&lt;< i << endl;
}
cout << “outside of the loop i is “ << i << endl; //this only compiles with old C/C++ compilers.
于 2008-11-17T20:28:13.133 回答