How different languages prevent fallthru hazards or not in switch case
I used Gemini 2.5 Flash to generate the answer because I forget the details for languages I haven't used in a while and I didn't want to make misstatements. I haven't double-checked the answers for languages I haven't been using frequently recently, they look about right for the ones I remember:
missing a break in a switch case statement that many languages inherited from C isn't just a hazard in C++, and JavaScript, but several other languages as well, right? I know various popular static analyzers flag this in a number of languages, and require you to have a formatted comment or configure the linter to specially allow fallthru in specific pieces of code.
Yes, that's correct. The "fallthrough" behavior of a switch statement—where the code continues to execute into the next case block if a break statement is omitted—is a shared hazard in many languages that inherited their syntax from C.
This is a well-known source of bugs, and it's why many popular static analyzers and linters are configured by default to flag missing break statements. They often require an explicit comment, like // fallthrough or // intentional fallthrough, to let you bypass the warning and signal to other developers that the omission was deliberate.
Here's a look at why this behavior is so widespread and how other languages handle it:
Why it's a Shared Problem
The switch statement in C was designed to jump to a specific case label and then continue executing code from that point onward until it encountered a break statement or the end of the switch block. This design, while enabling some clever optimizations and coding patterns, made it easy to introduce logical bugs through simple oversights.
Because so many popular languages were designed to be syntactically familiar to C programmers, they adopted this behavior. This includes:
How Languages Mitigate the Risk
To combat this bug-prone design, languages have evolved to introduce safer alternatives or stricter rules:
In short, the fallthrough hazard is a legacy of C's design that has been passed down through generations of programming languages, but the modern consensus is that it's a bug waiting to happen. As a result, language designers and tooling creators have worked to either remove the behavior or make it a much more explicit and intentional act.
So are we saying that there can't be accidental fallthru in either Java or C#?
EDIT -- Yes, we are! But I think the rest of the reply after that is good.
No, we're not saying that. You've hit on a critical distinction.
Accidental fallthrough is not possible in either Java or C#. Both languages' compilers are designed to prevent this classic bug.
Java's Behavior
In Java, if you omit a break or other jump statement (return, throw) from the end of a case block that contains code, the compiler will raise a compile-time error. It forces you to explicitly choose how to exit the case block.
The only exception is if a case block is completely empty. In that scenario, Java allows the code to fall through to the next case block without a break.
int status = 1;
switch (status) {
case 1:
// Java compiler will NOT throw an error here, it's allowed.
case 2:
System.out.println("This will print for both status 1 and 2.");
break;
}
C#'s Behavior
C# has an even stricter rule. It forbids fallthrough completely between non-empty case blocks. The compiler will produce an error if you omit a break, return, goto, or other jump statement at the end of a non-empty case.
Like Java, C# allows fallthrough only for empty case blocks. This is often used to group multiple cases that share the same code.
int status = 1;
switch (status) {
case 1:
case 2: // This is valid, as the first case is empty.
Console.WriteLine("This will print for both status 1 and 2.");
break;
}
In summary, both languages were designed to eliminate the fallthrough bug that plagues C and JavaScript, making their switch statements much safer by default.
Author comment -- as usual, every language has those general shared footguns that they solve for you, by refusing to compile, and those that they leave in your hands fully loaded. When you move back and forth between code in different languages, always remember to context-switch your footguns, or better yet, always run and pay attention to your linter no matter which language you are working in at the moment.