以下代码无法编译声明"在此范围内无法声明名为'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节:
匿名函数的可选匿名函数签名定义匿名函数的形式参数的名称和可选类型.匿名函数的参数范围是匿名函数体.与参数列表(如果给出)一起,anonymous-method-body构成一个声明空间.因此,匿名函数的参数名称与本地变量,本地常量或其范围包括anonymous-method-expression或lambda-expression的参数的名称匹配是编译时错误.
这有帮助吗?