为什么不能在嵌套的局部范围内声明重复变量名?

时间:2022-05-10 16:44:41

Based on this recent question, I don't understand the answer provided. Seems like you should be able to do something like this, since their scopes do not overlap

基于这个最近的问题,我不理解所提供的答案。看起来您应该能够做这样的事情,因为它们的作用域没有重叠。

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

This code fails to compile with the following error:

此代码未能通过以下错误编译:

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

一个名为“i”的局部变量不能在此范围内声明,因为它将赋予“i”不同的含义,“i”已经在“子”范围内用于表示其他东西。

9 个解决方案

#1


38  

I don't think any of the answers so far have quite got the crucial line from the spec.

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

From section 8.5.1:

从部分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.

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

(Emphasis mine.)

(强调我的。)

In other words, the scope for the "later" variable includes the part of the block before the declaration - i.e. it includes the "inner" block containing the "earlier" variable.

换句话说,“后”变量的范围包括在声明之前的块的一部分,即它包含包含“早期”变量的“内部”块。

You can't refer to the later variable in a place earlier than its declaration - but it's still in scope.

在一个地方,您不能比它的声明更早地引用后面的变量——但是它仍然在范围内。

#2


8  

"The scope of local or constant variable extends to the end of the current block. You cannot declare another local variable with the same name in the current block or in any nested blocks." C# 3.0 in a Nutshell, http://www.amazon.com/3-0-Nutshell-Desktop-Reference-OReilly/dp/0596527578/

“局部变量或常量变量的范围扩展到当前块的末尾。您不能在当前块中或在任何嵌套块中声明另一个具有相同名称的本地变量。c# 3.0概括地说,http://www.amazon.com/3-0-Nutshell- desktoprefer-oreilly/dp/0596527578/。

"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." Variable Scopes, MSDN, http://msdn.microsoft.com/en-us/library/aa691107%28v=vs.71%29.aspx

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

On a side note, this is quite the opposite that of JavaScript and F# scoping rules.

另一方面,这与JavaScript和f#定义规则完全相反。

#3


6  

From the C# language spec:

从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.

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

Essentially, it's not allowed because, in C#, their scopes actually do overlap.

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

edit: Just to clarify, C#'s scope is resolved at the block level, not line-by-line. So while it's true that you cannot refer to a variable in code that comes before its declaration, it's also true that its scope extends all the way back to the beginning of the block.

编辑:澄清一下,c#的作用域是在块级别上解决的,不是逐行的。因此,虽然您不能在声明之前引用代码中的变量,但它的作用域一直扩展到块的开头。

#4


3  

This has been a rule in C# from the first version.

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

Allowing overlapping scopes would only lead to confusion (of the programmers, not the compiler).

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

So it has been forbidden on purpose.

所以这是被禁止的。

#5


2  

It's not a question of overlapping scopes. In C# a simple name cannot mean more than one thing within a block where it's declared. In your example, the name i means two different things within the same outer block.

这不是一个重叠的问题。在c#中,一个简单的名称不能意味着在声明的块中有一个以上的东西。在你的例子中,我指的是同一个外块中的两个不同的东西。

In other words, you should be able to move a variable declaration around to any place within the block where it was declared without causing scopes to overlap. Since changing your example to:

换句话说,您应该能够将一个变量声明移动到块中任何位置的任何位置,而不会导致作用域重叠。从改变你的例子到:

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

would cause the scopes of the different i variables to overlap, your example is illegal.

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

#6


2  

For C#, ISO 23270 (Information technology — Programming languages — C#), §10.3 (Declarations) says:

对于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.

每个块、开关块、for语句、foreach-statement或usingstatement为局部变量和称为局部变量声明空间的本地常量创建了一个声明空间。名称通过本地变量声明和本地常数声明引入到这个声明空间中。

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]

[注:因此,在嵌套块中,不可能在封闭块中声明本地变量或常量,其名称与本地变量或常量相同。两个嵌套块可以包含具有相同名称的元素,只要两个块不包含另一个。最后请注意)

So

所以

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

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

  return ;
}

is legal, but

是合法的,但

public void foobar()
{
  int i = 0 ;

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

  ...

  return ;
}

is not legal. Personally, I find the restriction rather annoying. I can see issuing a compiler warning about scope overlap, but a compilation error? Too much belt-and-suspenders, IMHO. I could see the virtue of a compiler option and/or pragma , though ( perhaps -pedantic/-practical, #pragma pedantic vs #pragma practical, B^)).

是不合法的。就我个人而言,我觉得这种限制相当烦人。我可以看到发出编译器警告的范围重叠,但是编译错误?belt-and-suspenders太多,恕我直言。我可以看到编译器选项和/或pragma的优点,尽管(也许-pedantic/-实用,#pragma pedantic vs #pragma实用,B))。

#7


1  

I just compiled this in GCC both as C and as C++. I received no error message so it appears to be valid syntax.

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

Your question is tagged as .net and as c. Should this be tagged as c#? That language might have different rules than C.

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

#8


1  

In C you need to put all variable declaration at the very beginning of a block. They need to come all directly after the opening { before any other statements in this block.

在C中,您需要在一个块的开始处放置所有变量声明。在此区块的任何其他语句之前,它们都需要直接返回。

So what you can do to make it compile is this:

所以你可以做的是:

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

#9


0  

Here's your answer from MSDN .NET Documentation:

以下是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.

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

#1


38  

I don't think any of the answers so far have quite got the crucial line from the spec.

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

From section 8.5.1:

从部分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.

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

(Emphasis mine.)

(强调我的。)

In other words, the scope for the "later" variable includes the part of the block before the declaration - i.e. it includes the "inner" block containing the "earlier" variable.

换句话说,“后”变量的范围包括在声明之前的块的一部分,即它包含包含“早期”变量的“内部”块。

You can't refer to the later variable in a place earlier than its declaration - but it's still in scope.

在一个地方,您不能比它的声明更早地引用后面的变量——但是它仍然在范围内。

#2


8  

"The scope of local or constant variable extends to the end of the current block. You cannot declare another local variable with the same name in the current block or in any nested blocks." C# 3.0 in a Nutshell, http://www.amazon.com/3-0-Nutshell-Desktop-Reference-OReilly/dp/0596527578/

“局部变量或常量变量的范围扩展到当前块的末尾。您不能在当前块中或在任何嵌套块中声明另一个具有相同名称的本地变量。c# 3.0概括地说,http://www.amazon.com/3-0-Nutshell- desktoprefer-oreilly/dp/0596527578/。

"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." Variable Scopes, MSDN, http://msdn.microsoft.com/en-us/library/aa691107%28v=vs.71%29.aspx

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

On a side note, this is quite the opposite that of JavaScript and F# scoping rules.

另一方面,这与JavaScript和f#定义规则完全相反。

#3


6  

From the C# language spec:

从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.

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

Essentially, it's not allowed because, in C#, their scopes actually do overlap.

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

edit: Just to clarify, C#'s scope is resolved at the block level, not line-by-line. So while it's true that you cannot refer to a variable in code that comes before its declaration, it's also true that its scope extends all the way back to the beginning of the block.

编辑:澄清一下,c#的作用域是在块级别上解决的,不是逐行的。因此,虽然您不能在声明之前引用代码中的变量,但它的作用域一直扩展到块的开头。

#4


3  

This has been a rule in C# from the first version.

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

Allowing overlapping scopes would only lead to confusion (of the programmers, not the compiler).

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

So it has been forbidden on purpose.

所以这是被禁止的。

#5


2  

It's not a question of overlapping scopes. In C# a simple name cannot mean more than one thing within a block where it's declared. In your example, the name i means two different things within the same outer block.

这不是一个重叠的问题。在c#中,一个简单的名称不能意味着在声明的块中有一个以上的东西。在你的例子中,我指的是同一个外块中的两个不同的东西。

In other words, you should be able to move a variable declaration around to any place within the block where it was declared without causing scopes to overlap. Since changing your example to:

换句话说,您应该能够将一个变量声明移动到块中任何位置的任何位置,而不会导致作用域重叠。从改变你的例子到:

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

would cause the scopes of the different i variables to overlap, your example is illegal.

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

#6


2  

For C#, ISO 23270 (Information technology — Programming languages — C#), §10.3 (Declarations) says:

对于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.

每个块、开关块、for语句、foreach-statement或usingstatement为局部变量和称为局部变量声明空间的本地常量创建了一个声明空间。名称通过本地变量声明和本地常数声明引入到这个声明空间中。

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]

[注:因此,在嵌套块中,不可能在封闭块中声明本地变量或常量,其名称与本地变量或常量相同。两个嵌套块可以包含具有相同名称的元素,只要两个块不包含另一个。最后请注意)

So

所以

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

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

  return ;
}

is legal, but

是合法的,但

public void foobar()
{
  int i = 0 ;

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

  ...

  return ;
}

is not legal. Personally, I find the restriction rather annoying. I can see issuing a compiler warning about scope overlap, but a compilation error? Too much belt-and-suspenders, IMHO. I could see the virtue of a compiler option and/or pragma , though ( perhaps -pedantic/-practical, #pragma pedantic vs #pragma practical, B^)).

是不合法的。就我个人而言,我觉得这种限制相当烦人。我可以看到发出编译器警告的范围重叠,但是编译错误?belt-and-suspenders太多,恕我直言。我可以看到编译器选项和/或pragma的优点,尽管(也许-pedantic/-实用,#pragma pedantic vs #pragma实用,B))。

#7


1  

I just compiled this in GCC both as C and as C++. I received no error message so it appears to be valid syntax.

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

Your question is tagged as .net and as c. Should this be tagged as c#? That language might have different rules than C.

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

#8


1  

In C you need to put all variable declaration at the very beginning of a block. They need to come all directly after the opening { before any other statements in this block.

在C中,您需要在一个块的开始处放置所有变量声明。在此区块的任何其他语句之前,它们都需要直接返回。

So what you can do to make it compile is this:

所以你可以做的是:

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

#9


0  

Here's your answer from MSDN .NET Documentation:

以下是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.

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