[Proposal] Case fall through should be allowed #603
Replies: 41 comments 4 replies
-
C allows for case fallthrough and it's a massive source of bugs, which is why it was decided that C# would disallow it. |
Beta Was this translation helpful? Give feedback.
-
Explicitly writing |
Beta Was this translation helpful? Give feedback.
-
That's a matter of opinion. Writing structured code that doesn't require implicit, or explicit, "goto next case" is the real way to go. It's worth watching Jules May's "If considered harmful" talk for a detailed description of why test/goto's like this probably account for 95% of all bugs in existing code. |
Beta Was this translation helpful? Give feedback.
-
That's actually a good point. |
Beta Was this translation helpful? Give feedback.
-
Thank you. I make them occasionally 😉 |
Beta Was this translation helpful? Give feedback.
-
Funnily enough, I actually didn't realise that C# didn't allow case fallthrough. The fact that it doesn't, however, begs the question "Why the he** is the |
Beta Was this translation helpful? Give feedback.
-
C# does allow for case fallthrough, but only under the specific scenario of a switch-section with an empty statement-list. And the |
Beta Was this translation helpful? Give feedback.
-
@HaloFour Sure thing. You can, of course, use other control statements. But why can't I write this? void M(int i)
{
switch (i)
{
case 1: Console.WriteLine("one");
case 2: Console.WriteLine("two");
default: Console.WriteLine("Some other number");
}
} |
Beta Was this translation helpful? Give feedback.
-
Probably because most people (at the time) would expect that syntax would fallthrough. Forcing the developer to exit the switch-section but not automatically doing so keeps the expected syntax and avoids bugs. If C# were being designed today the argument might have been different. |
Beta Was this translation helpful? Give feedback.
-
As Eric Lippert explains here, C# does not support cases with empty statement lists. That is a C-language way of thinking about C#'s switches. In reality, C# treats it as multiple case labels for a section of the @Richiban, |
Beta Was this translation helpful? Give feedback.
-
@HaloFour @DavidArno Ahh, okay. Thanks for the info. Since I've never done any C or other similar level programming I'm not able to think in the historical context in which C# was first designed. Still, surely there's the possibility that this requirement can be removed now? After all, it's not a breaking change if the |
Beta Was this translation helpful? Give feedback.
-
Theoretically. It couldn't possibly break (pun unintended) any existing source. But is that really worthwhile? Sure, you eliminate six characters (and likely a newline) per switch-section, which isn't a massive improvement. And that still doesn't change the perceived expectation, especially for anyone coming from C, C++, Objective-C or Java, and there are significantly more developers using those languages than any of the "modern" languages.
Still under design but based on the various discussions on the Roslyn repo it seems that such a construct would be strictly for expressions. A section could not contain multiple statements nor could it produce a value of
Probably because then the language would have two identical ways of doing something with very slightly different syntax and behavior. It seems a little silly to me to chase "modern" constructs as that is a continuously moving target. Eventually even Apple Swift will seem passé and some people will clamor that it (and every other language) copy the syntax from the new hotness. |
Beta Was this translation helpful? Give feedback.
-
I prefer the explicit |
Beta Was this translation helpful? Give feedback.
-
You're right; "modern" was absolutely the wrong word here. I think I use it simply because I am very unsympathetic to the "That's the way it's always been done" argument. What I really meant was "non-C" programming. There are plenty of programmers who (whether it's through discovery of their own or through teaching) simply don't use 'jump' keywords such as
is, I'm sorry, completely nuts. Why on earth would they do that? It means that:
with the only difference being whether you're writing a statement or an expression!? |
Beta Was this translation helpful? Give feedback.
-
@Richiban Is having |
Beta Was this translation helpful? Give feedback.
-
I actually think there's a lot of interest for this. However, that doesn't mean we'd want to reuse existing statement forms when making expression forms. For one thing, it can just be harder to easily grok what's going on when you're scanning the code. For that reason, i think we're strongly behind some sort of expression-based pattern matching construct. However, that doesn't necessarily mean we'd try to reuse the switch/case keywords in it. I personally would like something pretty lightweight. 'switches' are already pretty heavyweight , and that feels like it would be unfortunate to me in an expression context. At the very least, i can't see why we'd keep 'case' (or any other keyword) when it can so easily be elided in expression contexts. |
Beta Was this translation helpful? Give feedback.
-
This is what I mean; that the team doesn't seem interested in making current statements into expressions. Similarly, there doesn't seem to be a lot of interest in making the new expression forms supported as statements. On Roslyn there were several requests that expression |
Beta Was this translation helpful? Give feedback.
-
My idea to making the switch (i) break // additional `break` introduces the new (optional) way
{
case 0: "zero";
case 1: "one";
case 2: // warning, empty case breaks and does not fall through
case 3: "three";
default: "some other number";
} |
Beta Was this translation helpful? Give feedback.
-
@CyrusNajmabadi I'm glad to hear that the new match statement is going to be lighter weight; switch/case really was too verbose. I'm going to make this point only once more (I'm aware that we're hijacking the thread somewhat with this discussion) but I really recommend against disallowing A little anecdote that explains why I'm hot on this topic right now: I'm currently teaching my SO how to program (she's done none at all before) and this is something that comes up regularly that she finds really confusing. I think she's largely got the difference between an expression and a statement (although she really backed me into a corner when it came to methods that return data but you ignore the result. "Is an expression or a statement?!" "Uhh... both?"), but I still see her trying to assign a Anyway, I think that if a new match statement is introduced to the language it's going to have a bunch of advantages and a lighter syntax so we should move away from switch as a result, not create this artificial divide for no reason other than to not have essentially deprecated |
Beta Was this translation helpful? Give feedback.
-
@DavidArno I'm noticing the If Considered Harmful talk affecting the way I factor my code. Thanks for that. The talk was slow but worthwhile. |
Beta Was this translation helpful? Give feedback.
-
You could also do switch(myInt)
{
case 0: case0Func(); break;
case 1: case0Func();
case1Func();
break;
default: defaultFunc(); break;
} Which will make them more readable too. |
Beta Was this translation helpful? Give feedback.
-
Since it is now proposed that switch expressions allow the use of statement expressions, I'd argue that the most readable way to express that would be: myInt switch
{
0 => case0Func();
1 => case1Func();
_ => defaultFunc();
};
...
void case1Func()
{
case0Func();
....
} No fall-through required and if |
Beta Was this translation helpful? Give feedback.
-
@DavidArno the immediate thought i have is that defeats the true purposes of case fall through, the few but very specialized optimizations you can make in tight loops. In a tight loop that's going to explode the stack with thousands/millions of method calls. Unless the compiler is smart enough to inline so intelligently it creates the proper CLR level case fall through with no stack usage at all. But that seems like a very tall order. |
Beta Was this translation helpful? Give feedback.
-
Sorry if someone has already proposed this already, but what about using As an example, say
This would allow |
Beta Was this translation helpful? Give feedback.
-
This already has meaning in the language. The swithc may be in a continuable construct (like a for-loop). Such things are common. This would make the meaning very confusing. |
Beta Was this translation helpful? Give feedback.
-
@CyrusNajmabadi I think I understand your point, but a switch can also be in a breakable construct and we allow break in switch statements so to me that feels like the language is getting more consistent (switch [or case?] becomes both breakable and continuable -- more like other constructs like for and while). |
Beta Was this translation helpful? Give feedback.
-
Though I do understand it could be backwards-incompatible. |
Beta Was this translation helpful? Give feedback.
-
I literally wrote code yesterday that continued out of a switch statement. I would imagine it would be very backwards incompatible. |
Beta Was this translation helpful? Give feedback.
-
FWIW, Swift has a |
Beta Was this translation helpful? Give feedback.
-
We could consider some of the features that were in the more powerful PL/I This was much less primitive than the feeble C switch, allowing expressions in places that C only allows constants. Might there be scope for making a In fact such an extension would have automatically provided the "type" pattern support as just being a special case of a more general expression based match. switch (variable.GetType())
{
case typeof(string)
;
break;
case typeof(List<string>)
;
break;
} |
Beta Was this translation helpful? Give feedback.
-
C# should really allow proper case fall through. There is no reason it needs to derivate from C with how switch behaves.
Perhaps an alternative would be similar to
switch unchecked(foo)
and this would allow proper case fall through without changing anything existing.Having located dotnet/roslyn#168 it already seems like this is supported and that something just specifically bars us from using it normally. Whatever disallows us to use case fall through should be turned off or have an opt-out.
Original thread: dotnet/roslyn#1426
Beta Was this translation helpful? Give feedback.
All reactions