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 name
what' 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
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
```
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.