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

C#.Net

C# Problem Overview


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

C# Solutions


Solution 1 - C#

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

From section 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.

Solution 2 - C#

"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/

"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

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

Solution 3 - C#

From the C# language spec:

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

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.

Solution 4 - C#

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

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

So it has been forbidden on purpose.

Solution 5 - C#

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

> 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]

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^)).

Solution 6 - C#

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.

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.

Solution 7 - C#

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

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

Solution 8 - C#

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.

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

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

Solution 9 - C#

Here's your answer from MSDN .NET Documentation:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAducciView Question on Stackoverflow
Solution 1 - C#Jon SkeetView Answer on Stackoverflow
Solution 2 - C#Teoman SoygulView Answer on Stackoverflow
Solution 3 - C#Sean UView Answer on Stackoverflow
Solution 4 - C#Henk HoltermanView Answer on Stackoverflow
Solution 5 - C#Nicholas CareyView Answer on Stackoverflow
Solution 6 - C#GabeView Answer on Stackoverflow
Solution 7 - C#jbruniView Answer on Stackoverflow
Solution 8 - C#x4uView Answer on Stackoverflow
Solution 9 - C#contactmattView Answer on Stackoverflow