为什么不能在嵌套的本地作用域中声明重复的variables名?

基于这个最近的问题 ,我不明白所提供的答案。 似乎你应该可以做这样的事情,因为他们的范围不重叠

static void Main() { { int i; } int i; } 

此代码无法编译以下错误:

名为'i'的局部variables不能在这个范围内声明,因为它会给'i'赋予不同的含义,'i'已经在'子'范围内用来表示别的东西

我不认为迄今为止的答案已经相当规范的关键线。

从8.5.1节:

局部variables声明中声明的局部variables的范围是声明出现的块 。 在局部variables的局部variables声明符之前的文本位置引用局部variables是错误的。 在局部variables的范围内,声明另一个局部variables或具有相同名称的常量是编译时错误。

(强调我的)

换句话说,“later”variables的作用域包含声明之前的块的部分,即它包含了包含“early”variables的“inner”块。

你不能在声明之前的地方引用后面的variables – 但它仍然在范围之内。

“局部variables或常量variables的范围扩展到当前块的结尾,不能在当前块或任何嵌套块中声明另一个具有相同名称的局部variables。 C#3.0的简介, http ://www.amazon.com/3-0-Nutshell-Desktop-Reference-OReilly/dp/0596527578/

“块的局部variables声明空间包括任何嵌套块,因此,在嵌套块中,不可能在封闭块中声明与局部variables同名的局部variables。 variables范围,MSDN, http://msdn.microsoft.com/en-us/library/aa691107%28v=vs.71%29.aspx

另一方面,这与JavaScript和F#范围规则相反。

从C#语言规范:

块的局部variables声明空间包括任何嵌套块。 因此,在一个嵌套块中,不可能在封闭块中声明一个与本地variables同名的局部variables。

实际上,这是不允许的,因为在C#中,它们的作用域实际上是重叠的。

编辑:只是为了澄清,C#的作用域是在块级解决,而不是逐行解决。 所以,尽pipe在声明之前不能引用代码中的variables,但它的范围也一直延伸到块的开头。

这是C#中第一个版本的规则。

允许重叠的范围只会导致混淆(程序员,而不是编译器)。

所以这是被禁止的。

这不是重叠范围的问题。 在C#中,一个简单的名字在声明的块内不能超过一个。 在你的例子中,名字i表示同一个外部块中的两个不同的东西。

换句话说,您应该能够将variables声明移到声明块的任何位置,而不会导致范围重叠。 由于将您的示例更改为:

 static void Main() { int i; { int i; } } 

会导致不同的variables的范围重叠,你的例子是非法的。

对于C#,ISO 23270( 信息技术 – 编程语言-C# ),§10.3( 声明 )说:

每个switch-blockfor-statementforeach-statementusing-statement为局部variables和局部常量创build一个声明空间,称为局部variables声明空间 。 名称通过局部variables声明局部常量声明引入到这个声明空间中。

如果块是实例构造函数,方法或运算符声明的主体,或者索引器声明的get或set访问器,则在此声明中声明的参数是块的局部variables声明空间的成员。

如果块是generics方法的主体,则在这种声明中声明的types参数是块的局部variables声明空间的成员。

局部variables声明空间的两个成员具有相同的名称是错误的。 局部variables声明空间和嵌套局部variables声明空间包含具有相同名称的元素是错误的。

[ 注意:因此,在嵌套块中,不可能在封闭块中声明局部variables或常量与局部variables或常量具有相同的名称。 只要两个块都不包含另一个嵌套块,就可以包含同名的元素。 尾注 ]

所以

 public void foobar() { if ( foo() ) { int i = 0 ; ... } if ( bar() ) { int i = 0 ; ... } return ; } 

是合法的,但是

 public void foobar() { int i = 0 ; if ( foo() ) { int i = 0 ; ... } ... return ; } 

是不合法的。 我个人觉得这个限制比较烦人。 我可以看到发出一个关于范围重叠的编译器警告,但编译错误? 太多的腰带和吊带,恕我直言。 我可以看到一个编译器选项和/或编译指示的优点,尽pipe(可能是-pedantic /的/ -practical#pragma pedantic vs #pragma practicalB^) )。

我只是把它编译成C和C ++。 我没有收到错误消息,所以它似乎是有效的语法。

你的问题被标记为.net和作为c。 这应该被标记为C#? 这种语言可能与C有不同的规则

在C中,你需要把所有的variables声明放在块的开头。 他们需要在开幕之后直接来到这个区块的任何其他陈述之前。

那么你可以做什么来编译它是这样的:

 static void Main() { { int i; } { int i; } } 

这是你从MSDN .NET文档中的答案:

…块的局部variables声明空间包括任何嵌套块。 因此,在一个嵌套块中,不可能在封闭块中声明一个与本地variables同名的局部variables。