为什么可以';t在嵌套的局部作用域中声明重复的变量名

本文关键字:作用域 局部 变量名 声明 嵌套 为什么 | 更新日期: 2023-09-27 17:57:46

基于最近的这个问题,我不理解提供的答案。看起来你应该能够做这样的事情,因为他们的范围不重叠

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

此代码编译失败,出现以下错误:

不能在此作用域中声明名为"i"的局部变量,因为它将赋予"i"不同的含义,而"i"已在"child"作用域中用于表示其他

为什么可以';t在嵌套的局部作用域中声明重复的变量名

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

来自第8.5.1节:

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

(强调我的。)

换句话说,"later"变量的作用域包括声明之前的块部分,即它包括包含"early"变量的"内部"块。

您不能在声明之前的某个位置引用后面的变量,但它仍在作用域中。

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

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

顺便说一句,这与JavaScript和F#作用域规则完全相反。

来自C#语言规范:

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

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

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

这是C#从第一个版本开始的一条规则。

允许重叠的作用域只会导致(程序员的,而不是编译器的)混乱。

因此,它被故意禁止。

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

每个开关块用于语句foreach语句使用语句为局部变量和称为局部变量声明空间的局部常量。名称为通过局部变量声明引入该声明空间局部常量声明

如果块是实例的主体的构造函数、方法或运算符声明,或get或set访问器一个索引器声明,在这样的声明中声明的参数是块的局部变量声明空间的成员。

如果块是泛型方法的主体,在这样的声明中声明的类型参数是块的局部变量声明空间的成员。

这是一个错误使局部变量声明空间的两个成员具有相同的名称。对于局部变量声明空间和嵌套的局部变量声明空间,以包含具有相同名称的元素。

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

所以

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 ;
}

不合法。就我个人而言,我觉得这种限制很烦人。我可以看到发布了一个关于作用域重叠的编译器警告,但这是一个编译错误吗?腰带和吊带太多了,IMHO。不过,我可以看到编译器选项和/或杂注的优点(可能是-pedantic/-practical#pragma pedantic#pragma practicalB^))。

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

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

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

会导致不同i变量的作用域重叠,您的示例是非法的。

我刚刚在GCC中将其编译为C和C++。我没有收到错误消息,所以它看起来是有效的语法。

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

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

所以你能做的是让它编译:

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

以下是MSDN的答案。NET文档:

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