Inspired from a -5
question again!
I read [this comment] of @Quartermeister and been astonished!
So why this compiles
switch(1) {
case 2:
}
but this doesn't.
int i;
switch(i=1) {
case 2: // Control cannot fall through from one case label ('case 2:') to another
}
neither this
switch(2) {
case 2: // Control cannot fall through from one case label ('case 2:') to another
}
update:
The -5
question became -3
.
The main reasons for using a switch include improving clarity, by reducing otherwise repetitive coding, and (if the heuristics permit) also offering the potential for faster execution through easier compiler optimization in many cases.
A switch statement first evaluates its expression. It then looks for the first case clause whose expression evaluates to the same value as the result of the input expression (using the strict comparison, === ) and transfers control to that clause, executing all statements following that clause.
A switch statement is significantly faster than an if-else ladder if there are many nested if-else's involved. This is due to the creation of a jump table for switch during compilation. As a result, instead of checking which case is satisfied throughout execution, it just decides which case must be completed.
The switch statement in C is an alternate to if-else-if ladder statement which allows us to execute multiple operations for the different possibles values of a single variable called switch variable. Here, We can define various statements in the multiple cases for the different values of a single variable.
None of them should compile. The C# specification requires that a switch section have at least one statement. The parser should disallow it.
Let's ignore the fact that the parser allows an empty statement list; that's not what's relevant. The specification says that the end of the switch section must not have a reachable end point; that's the relevant bit.
In your last example, the switch section has a reachable end point:
void M(int x) { switch(2) { case 2: ; } }
so it must be an error.
If you had:
void M(int x) { switch(x) { case 2: ; } }
then the compiler does not know if x will ever be 2. It assumes conservatively that it could, and says that the section has a reachable end point, because the switch case label is reachable.
If you had
void M(int x) { switch(1) { case 2: ; } }
Then the compiler can reason that the endpoint is not reachable because the case label is not reachable. The compiler knows that the constant 1 is never equal to the constant 2.
If you had:
void M(int x) { switch(x = 1) { case 2: ; } }
or
void M(int x) { x = 1; switch(x) { case 2: ; } }
Then you know and I know that the end point is not reachable, but the compiler does not know that. The rule in the specification is that reachability is only determined by analyzing constant expressions. Any expression which contains a variable, even if you know its value by some other means, is not a constant expression.
In the past the C# compiler had bugs where this was not the case. You could say things like:
void M(int x) { switch(x * 0) { case 2: ; } }
and the compiler would reason that x * 0 had to be 0, therefore the case label is not reachable. That was a bug, which I fixed in C# 3.0. The specification says that only constants are used for that analysis, and x
is a variable, not a constant.
Now, if the program is legal then the compiler can use advanced techniques like this to influence what code is generated. If you say something like:
void M(int x) { if (x * 0 == 0) Y(); }
Then the compiler can generate the code as though you'd written
void M(int x) { Y(); }
if it wants. But it cannot use the fact that x * 0 == 0
is true for the purposes of determining statement reachability.
Finally, if you have
void M(int x) { if (false) switch(x) { case 2: ; } }
then we know that the switch is not reachable, therefore the block does not have a reachable end point, so this is, surprisingly, legal. But given the discussion above, you now know that
void M(int x) { if (x * 0 != 0) switch(x) { case 2: ; } }
does not treat x * 0 != 0
as false
, so the end point is considered reachable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With