关于C#:为什么不能在嵌套的局部作用域中声明重复的变量名?

Why can't a duplicate variable name be declared in a nested local scope?

基于最近的这个问题,我不理解提供的答案。似乎您应该能够这样做,因为它们的作用域不重叠

1
2
3
4
5
6
7
static void Main()
{
  {
    int i;
  }
  int i;
}

此代码未能编译,出现以下错误:

A local variable named 'i' cannot be declared in this scope because it would give a different meaning to 'i', which is already used in a 'child' scope to denote something else


我认为到目前为止,任何答案都没有从规范中得到关键的一行。

根据第8.5.1节:

The scope of a local variable declared in a local-variable-declaration is the block in which the declaration occurs. It is an error to refer to a local variable in a textual position that precedes the local-variable-declarator of the local variable. Within the scope of a local variable, it is a compile-time error to declare another local variable or constant with the same name.

(强调我的)

换句话说,"later"变量的作用域包括声明前块的一部分,也就是说,它包括包含"earlier"变量的"inner"块。

不能在声明之前的位置引用后面的变量,但它仍然在范围内。


"局部变量或常量变量的范围扩展到当前块的末尾。不能在当前块或任何嵌套块中声明同名的另一个局部变量。"C 3.0 in a nutshell,http://www.amazon.com/3-0-nutshell-desktop-reference-oreilly/dp/0596527578/

"块的局部变量声明空间包括任何嵌套块。因此,在嵌套块中,不能声明与封闭块中的局部变量同名的局部变量。"变量作用域,msdn,http://msdn.microsoft.com/en-us/library/aa691107%28v=vs.71%29.aspx

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


从C语言规范:

The local variable declaration space of a block includes any nested blocks. Thus, within a nested block it is not possible to declare a local variable with the same name as a local variable in an enclosing block.

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

编辑:为了澄清,C的范围是在块级别上解决的,而不是逐行解决的。因此,虽然在代码中不能引用声明之前的变量是正确的,但它的作用域却一直延伸到块的开头也是正确的。


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

Each block, switch-block, for-statement, foreach-statement, or
using-statement creates a declaration space for local variables and
local constants called the local variable declaration space. Names are
introduced into this declaration space through local-variable-declarations
and local-constant declarations.

If a block is the body of an instance
constructor, method, or operator declaration, or a get or set accessor for
an indexer declaration, the parameters declared in such a declaration are
members of the block’s local variable declaration space.

If a block is the
body of a generic method, the type parameters declared in such a declaration
are members of the block’s local variable declaration space.

It is an error
for two members of a local variable declaration space to have the same name.
It is an error for a local variable declaration space and a nested local
variable declaration space to contain elements with the same name.

[Note: Thus, within a nested block it is not possible to declare a local
variable or constant with the same name as a local variable or constant
in an enclosing block. It is possible for two nested blocks to contain
elements with the same name as long as neither block contains the other.
end note]

所以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void foobar()
{
  if ( foo() )
  {
     int i = 0 ;
     ...
  }

  if ( bar() )
  {
    int i = 0 ;
    ...
  }

  return ;
}

是合法的,但

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void foobar()
{
  int i = 0 ;

  if ( foo() )
  {
     int i = 0 ;
     ...
  }

  ...

  return ;
}

是不合法的。就我个人而言,我觉得这种限制相当烦人。我可以看到发出一个关于范围重叠的编译器警告,但是编译错误?太多的皮带和吊带,imho。不过,我可以看到编译器选项和/或pragma的优点(可能是-pedantic/-practical#pragma pedantic#pragma practicalB^)


这是第一版C中的一条规则。

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

所以这是故意禁止的。


这不是重叠范围的问题。在C中,简单名称不能在声明它的块中表示多个事物。在您的示例中,名称i表示同一外部块中的两个不同的东西。

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

1
2
3
4
5
6
7
static void Main()
{
    int i;
    {
        int i;
    }
}

会导致不同i变量的范围重叠,您的示例是非法的。


在C语言中,您需要将所有变量声明放在块的最开始。它们需要在打开{之后,在这个块中的任何其他语句之前直接出现。

所以你可以做的是让它编译如下:

1
2
3
4
5
6
7
8
9
static void Main()
{
  {
    int i;
  }
  {
    int i;
  }
}


我刚在GCC中编译为C和AS C++。我没有收到任何错误消息,所以它似乎是有效的语法。

您的问题标记为.NET和C。是否应将其标记为C?这种语言可能与C语言有不同的规则。


以下是msdn.net文档中的答案:

...The local variable declaration space of a block includes any nested blocks. Thus, within a nested block it is not possible to declare a local variable with the same name as a local variable in an enclosing block.