儿童范围&CS0136

以下代码无法编译声明“在此范围内无法声明名为’st’的局部变量,因为它会给’st’赋予不同的含义,’st’已在’子’范围内用于表示其他内容”:

var l = new List(); 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变量。 这是技术限制还是设计决策? 这就是我真正想要的;-)

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

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

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

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

这只是两个简单的规则:

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

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

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

匿名函数的可选匿名函数签名定义匿名函数的forms参数的名称和可选类型。 匿名函数的参数范围是匿名函数体。 与参数列表(如果给定)一起,anonymous-method-body构成一个声明空间。 因此,匿名函数的参数名称与本地变量,本地常量或其范围包括anonymous-method-expression或lambda-expression的参数的名称匹配是编译时错误。

这有帮助吗?

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