Reputation: 3409
Switch statements: I know what they do - I use them so many times, as per convention normally when I want to do different stuff based on the value of an Enum, but now it just hit me: Why are we using it? What was its original purpose? I mean, this:
switch(myVar) {
case Foo:
doSomething();
break;
case Bar:
doSomethingElse();
break;
default:
justAnotherThing();
break;
}
Has the exact same behaviour as:
if(myVar == Foo) {
doSomething()
}else if(myVar == Bar) {
doSomethingElse();
}else {
justAnotherThing();
}
Plus if
's lets you make inequality comparisons (>
, <
, !=
) if you need it. The only case that I may find a switch more useful is when you don't use the break
statement inside: but this happens not too often and I find it terrible on code-quality.
I really can't find any benefit of using switch
over if
... So why was it defined for?
Upvotes: 1
Views: 80
Reputation: 354734
Some languages allow inequality comparisons in switch
statements as well, e.g. Visual Basic:
Select Case x
Case < 5
// ...
Case 7
// ...
Case 10 To 15
// ...
Case Else
// ...
End Select
Basically, yes, the switch
can often be written as an if
/else if
ladder, with the distinction that switch
compares one value against a number of comparison values, if
/else if
can do anything in every single branch. But even that isn't the case in all languages, e.g. in PowerShell a switch
can do plenty of things that you usually have to use if
for:
switch -Regex ($x) {
'^\d+$' {'Number'}
}
or
switch ($x) {
{ $_ is [int] -or $_ is [double] } {'Number'}
{ $_ is [string] } {'Text'}
}
Generally, however, switch
is easier to read for the common case of comparing a single value against a finite set of options. Furthermore, it enables the compiler to do certain optimizations which are harder to analyse on if
/else if
, such as using binary search to determine the correct case instead of linear search, or even using a jump table or arithmetic. E.g. the following switch
switch (x) {
case 0:
// Do something with 0
break;
case 1:
// Do something with 1
break;
case 2:
// Do something with 2
break;
...
}
could be compiled into the equivalent of
Action[] actions = {
() => { /* Do something with 0 */ },
() => { /* Do something with 1 */ },
() => { /* Do something with 2 */ },
...
};
if (x >=0 && x <= n) {
actions[x]();
}
The simplicity and limitations of switch
are helpful in this case for an optimizing compiler because there's much less to analyse to determine what the overall structure is trying to do.
There are other features (sometimes maybe of dubious value), such as Duff's device, or being able to fall through to other cases (or goto
arbitrary other cases, which, e.g. C# allows).
You may just as well ask the question why we have if
statements and loops instead of just using goto
. Yes, structured programming constructs are, taken one by one, strictly inferior in what they can express, compared to the more general construct. But they are more readable, make the intent clearer, and tend to be safer and easier to maintain.
Upvotes: 4
Reputation: 522470
switch
is a pretty low-level statement, in the sense that the code in the case
statements is compiled into a continuous block of instructions in memory which is simply conditionally jumped into (depends on the language in question of course, modern high-level languages may behave quite different under the hood). That's also why you have the fall-through behaviour, once a starting address is determined simply all following instructions are executed unless broken out of.
So initially it was a very natural way to jump over or into a block of instructions. Many languages have adopted the switch
statement, many likely due to familiarity, but many likely also because it is indeed rather readable for certain cases, e.g.:
switch (someComplicatedCalculation($foo, $bar)) {
case CONSTANT_A:
...
case CONSTANT_B:
...
...
}
That's a pretty succinct way to express this, especially if you're maybe also depending on the fall-through behaviour.
Of course, other languages have never adopted switch
, e.g. Python, and require the use of if..elif..else
instead. In the end you can write similar code using either language construct, it's up to you.
Upvotes: 2