Roslyn: Case blocks in a switch statement share scope

Created on 24 Jan 2017  路  8Comments  路  Source: dotnet/roslyn

Version Used:
MSBuild 14.0.25420.1,

Steps to Reproduce:
I have a few IDEOnes replicating the issue.

These ones shouldn't compile but do:

http://ideone.com/OGWLPR
http://ideone.com/HBoPmY

This should compile but does not:
http://ideone.com/nUOmZ1

Expected Behavior:
Case blocks shouldn't share scope, and instead should declare local scopes.
I expect

error CS0103: The namewhat' does not exist in the current context,`

in the bad examples.

Actual Behavior:
The case blocks act as there is no separation and share scope.

This has lead to quite a few SO questions and blog posts, and requires a bit of ugly syntax to workaround.

See:
http://stackoverflow.com/questions/11409709/c-sharp-switch-case-share-the-same-scope
https://blogs.msdn.microsoft.com/ericlippert/2009/08/13/four-switch-oddities/
https://www.google.com/search?q=case+blocks+in+a+switch+scope+C%23+stack+overflow

Area-Language Design Discussion

Most helpful comment

Note: i personally hate C-style scoping for switches. But this is what we've inherited, and we cannot change that now. For future constructs (like 'match') my hope is that we'll go with a much more sensible scoping strategy.

All 8 comments

While the pain is real, that change would break so much existing code.
What's wrong with:

c# switch (i) { case 1: { var what = "WHERE"; break; } case 2: { var what = "WHAT"; break; } }

ReSharper even makes it super easy to type and format this way.

The syntax is more clunky and it doesn't follow the other keywords style, leading to confusion.

if, do, while, foreach, and else all create their own local scopes, and don't require braces.
Why should case break this pattern?

if, do, while, foreach, and else all create their own local scopes, and don't require braces.
Why should case break this pattern?

Either way, even if cases each had their own scope, they still wouldn't be comparable to if, do, while, foreach, and else because cases can have multiple statements without braces.
Basically, cases are fancy goto labels. switch...case is more comparable to goto than it is to if, for, using, etc.

I wish cases had their own scopes and didn't require break because it's so verbose, but how on earth could that be changed without breaking existing code? Keep in mind that goto case is rather useful once in a while.

Because that's how 'case' worked in C and C# inherited the behavior from C. We cannot change that behavior because it will break lots and lots and lots of code.

Also:

Why should case break this pattern?

Because people can fall-through labels in C#. Meaning they'll want to declare the local in one section of the switch block, but still refer to it in a label they jumped to.

Note: i personally hate C-style scoping for switches. But this is what we've inherited, and we cannot change that now. For future constructs (like 'match') my hope is that we'll go with a much more sensible scoping strategy.

Because people can fall-through labels in C#. Meaning they'll want to declare the local in one section of the switch block, but still refer to it in a label they jumped to.

Are you referring to goto case?

If it makes you feel better (or worse), this works:

```c#
switch(obj) {
case int v: break;
case long v: break;
}

// no v in scope

```

Was this page helpful?
0 / 5 - 0 ratings