Variable breaking scope

How come this gives a 's' does not exist in the current context error (as expected):

public static void Main()
{
    foreach(var i in new[]{1, 2, 3}) {
        int s = i;
    }

    Console.WriteLine(s);
}

(ideone)

But this gives a 's' cannot be redeclared error?

public static void Main()
{
    foreach(var i in new[]{1, 2, 3}) {
        int s = i;
    }

    int s = 4;
}

(ideone)

The first error tells me that s doesn't exist outside of the foreach, which makes sense, but the second error says otherwise. Why (and how!?) would I ever need to access a variable from a child scope?

Jon Skeet
people
quotationmark

The first error tells me that s doesn't exist outside of the foreach, which makes sense

Indeed - it's right.

but the second error says otherwise.

No, it doesn't. It's telling you that you can't declare the first (nested) variable s, because the second one is already in scope. You can't access it before the declaration, but it's in scope for the whole block.

From the C# 5 specification, section 3.7:

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

So yes, it extends upwards to the enclosing {., basically.

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

That final part (emphasis mine) is why you're getting an error.

Why (and how!?) would I ever need to access a variable from a child scope?

Not sure what you mean here, but the rule is basically there to make it harder for you to write hard-to-read or fragile code. It means there are fewer places where moving the declaration of the variable up or down (but still in the same block, at the same level of nesting) produces code which is valid but with a different meaning.

people

See more on this question at Stackoverflow