views:

201

answers:

3
+7  Q: 

C# scope question

Consider the following code sample:

                         // line #
{                        // 1
                         // 2
    {                    // 3
        double test = 0; // 4
    }                    // 5
                         // 6  
    double test = 0;     // 7
}                        // 8 

This gives the error

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

But I don't understand why? The outer test variable starts in line 7 and not in line 2, so where's the problem to declare a second variable called test on line 4 with a scope ending on line 5?

+10  A: 

Variables are scoped within the block they are declared in, it doesn't matter what line they are in.

Read about scopes in the C# language spec.

From the spec:

The scope of a local variable declared in a local-variable-declaration (Section 8.5.1) is the block in which the declaration occurs.

And:

Scopes can be nested, and an inner scope may redeclare the meaning of a name from an outer scope. (This does not, however, remove the restriction imposed by Section 3.3 that 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.)

Oded
Thanks for the explanation and link, Oded / Robert!BTW here's the relevant quote from the linked page http://msdn.microsoft.com/en-us/library/aa691132%28VS.71%29.aspx:"Scopes can be nested, and an inner scope may redeclare the meaning of a name from an outer scope. (This does not, however, remove the restriction imposed by Section 3.3 that 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.)"
stefan.at.wpf
@stefan.at.wpf - true. Answer updated to include this bit of information.
Oded
A: 

+1, I agree with you, but it's not how the spec is written. It makes writing the compiler easier I'm sure. Also, I think it could be argued that it is preferable not to do this anyways to make the code easier to understand.

tster
Thanks tster, I also guess this is the main reason and yes, it's really not useful to do sth. like in my sample (just switch the order of the blocks ...), just didn't understand why in the first moment ;-)
stefan.at.wpf
I *assure* you it does *not* make writing the compiler easier. The code in the compiler that implements this rule is some of the hairiest, most confusing code I've ever seen. There are *lots* of bugs in this code that you will never run into because they are all extremely obscure corner cases. The reason for this feature is because it prevents bugs in user code, not because it makes my job easier. It makes my job quite a bit harder.
Eric Lippert
@Eric Lippert, Thanks for the expert testimony.
tster
+3  A: 

This is a frequently asked question; see also:

http://stackoverflow.com/questions/3133680

http://stackoverflow.com/questions/2630244

http://stackoverflow.com/questions/2049330

http://stackoverflow.com/questions/1196941

The answer is: read the error message more carefully. The error message states exactly what the problem is: you are not allowed to use the same simple name to mean two different things in the same block.

For example:

class C
{
    int x;
    void M()
    {
        int x;
    }
}

Perfectly legal. Note that the scope of the outer x overlaps the scope of the inner x. It is not illegal to have overlapping scopes with the same name in scope in both.

This is not legal:

class C
{
    int x;
    void M()
    {
        Console.WriteLine(x); // this.x
        {
            int x;
        }
    }
}

Again, the two scopes both with an x overlapping is perfectly legal. What is illegal is that the simple name x is used two mean two different variables in the same block - that is, within the outer block of M(), which contains the inner block of M.

Programs where the same simple name is used to mean two different things in the same block are confusing and bug prone and therefore are illegal in C#.

For more details read my articles on the subject:

http://blogs.msdn.com/b/ericlippert/archive/tags/simple+names/

Eric Lippert
Thank you so much for this detailed answer!
stefan.at.wpf