Thursday, July 22, 2004

Another interesting discussion on MSDN Newsgroups:

The original question:

Hi,

   When I try and compile the a class containing the following method :

    public void doSomething() {
        for (int i=0; i<5; i++) {
            IList list = new ArrayList();
            Console.WriteLine( i / (list.Count) );
        }
        int i = 23;
        IList list = new ArrayList();
        Console.WriteLine( i / (list.Count) );
    }

I get the following errors :

D:\Forecaster\TestForecaster\TestBaseEntities.cs(402): 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

D:\Forecaster\TestForecaster\TestBaseEntities.cs(402): The name 'i' does not
exist in the class or namespace 'ForestResearch.UnitTests.TestBaseEntities'

D:\Forecaster\TestForecaster\TestBaseEntities.cs(403): A local variable
named 'list' cannot be declared in this scope because it would give a
different meaning to 'list', which is already used in a 'child' scope to
denote something else

D:\Forecaster\TestForecaster\TestBaseEntities.cs(403): The name 'list' does
not exist in the class or namespace
'ForestResearch.UnitTests.TestBaseEntities'

The C# Language spec states :
  a.. The scope of a local variable declared in a for-initializer of a for
statement (§8.8.3) is the for-initializer, the for-condition, the
for-iterator, and the contained statement of the for statement.
If the put the statements following the for statement in an anonymous block
like this then the compiler is happy :

    public void doSomething() {
        for (int i=0; i<5; i++) {
            IList list = new ArrayList();
            Console.WriteLine( i / (list.Count) );
        }
        {
            int i = 23;
            IList list = new ArrayList();
            Console.WriteLine( i / (list.Count) );
        }
    }

Interestingly if I do the converse (i.e. put the for statement in an
anonymous block and DON'T put the statements following in an anonymous
block) then I get the same compiler errors!

I'm using Microsoft Visual Studio 2002.

Questions :

1. I would have thought that the scope of 'i' is the for initializer and for
statement so that this identifier could be used again as I have done above
in my first example ?

2. Likewise I would have thought that the scope of the variable 'list'
should just be the block in which it is declared and so could be used again
as I have done in my first example ?

3. Why does my second example produce no compiler errors ?


Thanks in advance,

Really interesting because you would expect the compiler to work without a problem. After some basic research, I found out that it is a compiler feature designed to ensure that developers do not make a mistake while using variables in different scopes.

That is why when you put a curly brace around the code, it works fine - because then the compiler knows you are explicitly scoping your code into different execution scopes.

Funny though that the following code:

class CTest
{
       public void Foo()
       {
             int x = 4;
             Console.WriteLine(x);
       }
 
        int x = -1;
}

compiles without an issue!  I'm probably misusing the scope of a class-level variable and the compiler doesn't even bother protecting it now!

Strange!

Friday, July 30, 2004 1:58:45 PM (India Standard Time, UTC+05:30)
well, the compiler complains in the first case because you cannot explicitly specify which variable to use when you declare the 2 local variable. whereas for the code snippet mentioned at the end, the compiler doesnt bark since you can access both the variables explicitly (x would be the local var, this.x would be the class var). you could do a this.x = x; which is valid.

just my 2 cents.
Chandra Chivukula
Name
E-mail
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):