Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

For loop counter variable scope seems to have a dual personality? [duplicate]

Tags:

scope

c#

The code below produces this error in Visual Studio 2012; "A local variable named 'x' cannot be declared in this scope because it would give a different meaning to 'x', which is already used in a 'child' scope to denote something else"

for (int x = 0; x < 9; x++) 
  {
     //something
  }
int x = 0;

However. When modified as below I get this error; "The name 'x' does not exist in the current context"

for (int x = 0; x < 9; x++) 
  {
     //something
  }
x = 0;

Is this a huge contradiction or am I missing something?

like image 764
user3174847 Avatar asked Jan 08 '14 19:01

user3174847


3 Answers

So far no one except Rik has put their finger on the correct answer.

Read the error messages again, very carefully. They are clearly explaining the errors. The first error is:

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

Actually read the error message. It says it is illegal to use the same name to mean two different things. The error has nothing to do with the scope of the outer x per se; it has to do with the fact that x is used to mean two things in the same outer scope.

As Rik points out, the purpose of this rule is to avoid situations where the developer becomes confused about the meaning of x. A given name almost always means the same thing throughout a block. (There are some subtle exceptions but let's not go into those today.) This rule also helps prevent bugs introduced by re-ordering statements within a method and thereby subtly changing the meaning of the names. If the meaning of a name is invariant within a block then code edits within that block can be made with confidence.

A number of the answers say that scopes are not allowed to overlap. Yes they are. Local variable scopes are not allowed to overlap, but scopes are allowed to overlap. For example:

class C
{
    int x;
    void M()
    {
        int y = this.x;
        for(int x = 0; x < 10; ++x) {}
    }
}

Perfectly legal even though there are two things called x in scope at the same time. But this is not legal:

class C
{
    int x;
    void M()
    {
        int y = x; // Means this.x
        for(int x = 0; x < 10; ++x) {} // means local x
    }
}

Now the simple name x means two different things inside the body of M, and that is what is illegal. Again, make sure you understand this: using the same name to mean two things in the same scope is what is illegal. It is not illegal to overlap scopes.

Now your second error:

"The name 'x' does not exist in the current context"

The name x is only valid inside the for statement. A for statement:

for (declarations ; condition ; increment ) body

is logically equivalent (modulo break and continue behaviour)to

{
    declarations;
    while(condition)
    {
        body
        increment
    } 
}

Note the outer braces. Anything in that declaration can be used throughout the condition, body or increment, but is not in scope outside.

like image 84
Eric Lippert Avatar answered Oct 18 '22 04:10

Eric Lippert


The first is an error because it is equivalent to this:

int x;
for (int x = 0; x < 9; x++) 
{
   //something
   // 'x' is ambiguous here
}
x = 0;

The way variable declarations work in C#, that is the same as your first sample.

The second is an error because the 'x' variable defined in the loop is only valid in the loop.

like image 6
Joel Coehoorn Avatar answered Oct 18 '22 04:10

Joel Coehoorn


C# is stopping you from creating a confusing situation in which it is easy to make mistakes about what x actually refers to.

like image 5
Rik Avatar answered Oct 18 '22 05:10

Rik