views:

654

answers:

18

Switches seem so useless as they can be replaced with if-else statements, which can do much more than just match a char/int/enum etc. I can only think of one good use for a switch, and that would be for interpreting command line args.

What are some realistic uses for a switch statement?

+6  A: 

I use switches when I am using an enum to dictate what actions my method should take. It helps when are mutually exclusive.

phsr
+3  A: 

There are a number of situations, one that we have to deal with a lot is if you have a lot of options, the syntax is a bit more compressed, and sometimes is easier to read than a if/then syntax.

Although an argument can be made to go either way, I find that switches, in the case of multiple options is easier to read, maintain and understand. I also have used it in a factory pattern type situation, which helps to document.

Mitchel Sellers
+1  A: 

It's the proper way to use the language. It lets the compiler do some optimizations and makes the code easier to read by someone who isn't you.

Also, in some languages you can switch an enum, and the compiler will warn if you miss values (I think).

John
+1  A: 

well you can remove breaks from a switch statement. That way you can have this:

CASE_A:
...
BASE_B
...

so that way you can have case_a combine all the other cases below it until it hits a break. Not as nice to do that with just ifs.

Chris H
This is also very error-prone, when someone comes along and doesn't realize that this is how the code is intended to behave.
danben
It's occasionally useful, in which case it should be /* COMMENTED IN CAPS TO TRY TO MAKE PEOPLE NOTICE THE LACK OF A BREAK; */.
David Thornley
Also, some languages (I'm thinking C#) force you to declare fallthrough explicitly, or the case has to otherwise be empty.
Chris
+16  A: 

You need to remember that switches are easier to maintain - a whole bunch of nested ifs and elses can quickly become a pain to maintain.

Switches allow for easier insertion of a new case.

Ink-Jet
For nested ifs, switches are definitely easier to maintain. For if/else-ifs (which act just like a switch) are just as easy to maintain as a switch
phsr
+6  A: 

Switches are optimized in many languages for certain contexts. Often when possible they create a jump table or even hash table. Really, when it's possible to use a switch, it's very likely going to perform better than the (logically) same code using if/else.

Dan Tao
+1  A: 

It helps readability - at a glance, I know that the decision for which block of code should run is based on different values of the same variable.

mbeckish
+21  A: 

There are a few cases where switch is more readable and comes in handy. Usually when you have grouping of options.

Here is one of them:

    int numDays = 0;
    int month = 2;
    int year = 2010;

    // find the number of days in the month
    switch (month) {
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
            numDays = 31;
            break;
        case 4:
        case 6:
        case 9:
        case 11:
            numDays = 30;
            break;
        case 2:
            if ( ((year % 4 == 0) && !(year % 100 == 0))
                 || (year % 400 == 0) )
                numDays = 29;
            else
                numDays = 28;
            break;
        default:
            System.out.println("Invalid month.");
            break;
    }
Yada
Yea, I imagined it would be the same case with command line options. Like if -f were similiar to -F, one could use that fall-through concept.
Kavon Farvardin
@Kavon and that's how a lot of C programs processes switch arguments, using getopt() in a while() and switch() on the name.
kb
+20  A: 

There's two reasons to use a switch vs if/else, in my mind:

  • The compiler may be able to optimize for the switch better.
  • The switch statement more clearly expresses the logic of the code better. Specifically, the idea that you're taking a different branch depending on the value of something, rather than depending on more complicated logic. This is, by far, the more important reason to me.
RHSeeger
I came across the following link: http://www.blackwasp.co.uk/SpeedTestIfElseSwitch.aspx which seems to support your optimization argument (at least for .NET). I agree with your second point as well.
Scott A. Lawrence
+1 this optimization is especially important for embedded code that is processing messages in a recursive descent style. However, some compilers will only apply lookup table optimizations if the numerical values are in order or order-independent.
D.Shawley
I also like gcc's extension: switch (foo) {case 1 ... 10: doSomething(); break;case 11 ... 200: doSomethingElse(); break;}
ggiroux
+3  A: 

I always use switches if I'm comparing the same variable for multiple values - a switch is a lot quicker to code (and easier to maintain) than a long if-elseif chain. Imagine changing the variable name, with a switch it'll be a single edit, with an if-elseif chain it'll be several.

Also, depending on the language of choice you can use the case fall through "feature" where as with the if-elseif chain you'd end up with duplicated code.

Mike Anchor
A: 

It may be easier for the compiler to turn a switch statement into a dispatch table than it would be to turn the equivalent if/else soup into a dispatch table. If (and only if) that's true, you should then have O(1) dispatch to the relevant code, instead of O(log n) (or O(n), if the if/else soup is badly written).

In some (although not all) cases it may also be easier to check that you've covered the necessary tests using switch than a wodge of if/else.

Vatine
Problem is, if/else soup that runs in O(n) is easier to understand.
David Thornley
Not always. Look at the "days of the month" example, I find that about as readable as an if/else construction. The one slight drawback is that is places months with a common number of days in one place, instead of listing each month, increasing. Doing that would still allow the compiler to use a jump table, although it would (possibly, depending on how clever the compiler is) cause larger code size.
Vatine
+1  A: 

A couple of points:

  1. Some languages let you switch on other value types, such as string (Coldfusion case in point)
  2. A switch statement may very well be much easier code to read than a big block of if/elseif/else statements
  3. In switch statements you can break at the end of a case or allow the code to continue processing further cases in the statement. This functionality allows you to easily model some rules that if/elseif/else statements would not let you do as easily.
  4. As others mention, keep in mind compilers and engines have optimizers, and switch statements are optimized differently.
Jay
+1  A: 

Duff's Device. Its usefulness in modern times is debatable, but its awesomeness is not.

rmeador
s/it's/its/g; (ignore this parenthetical: just padding out comment to 15 or more characters)
Anonymous
doh! fixed. I hate it when people misuse it's/its... usually I'm very good about it. Sorry.
rmeador
+2  A: 

In the case of Perl, using the switch statement can significantly reduce the complexity of your code.

Just compare these two examples.

  • Using given/when:

    use feature qw'switch';
    my $num_days;
    given( $month) {
      when( [ 1,3,5,7,8,10,12 ] ){ $num_days = 31 }
      when( [ 4,6,9,11 ] ){ $num_days = 30 }
      when( 2 ){
        $num_days = 29;
        $num_days = 28 if     $year % 4;
        $num_days = 28 unless $year % 100;
        $num_days = 29 unless $year % 400;
      default{ print "Invalid month.\n" }
    }
    
  • Using for as a replacement for the new ~~ (smart-match) operator.

    my $num_days;
    for( 1,3,5,7,8,10,12 ){
      if( $month == $_ ){
        $num_days = 31;
        last;
      }
    }
    for( 4,6,9,11 ){
      if( $month == $_ ){
        $num_days = 30;
        last;
      }
    }
    if( $month == 2 ){
      $num_days = 29;
      $num_days = 28 if     $year % 4;
      $num_days = 28 unless $year % 100;
      $num_days = 29 unless $year % 400;
    }
    unless( defined $num_days ){
      print "Invalid month.\n"
    }
    
Brad Gilbert
Neither of those Perl examples are any more readable. ;)
Kavon Farvardin
A: 

I prefer using a map to a switch in most cases.

if (actionMap.contains(choice)) {
  Action a = actionMap.get(choice);
  a.execute();
} else {
  //do something else
}

But in cases where the choices are too complicated to turn into a map or when multiple actions might be taken a switch is better.

switch (choice) {
  case 1: actionOne(); break;
  case 2: if(actionOne()) {actionTwo()}; break; 
  case 3: if(!actionOne() && (actionTwo() > 1)) {actionThree()}; result = 7;break; 
  default: result = actionTwo();
}

Sadly, sometimes requirements are complicated. Switch is useful in those cases where is simplified version of nested if/else constrcts.

sal
+1  A: 

Switch statements are great for writing finite state machine,Click here to learn more about them

Salman Paracha
+1  A: 

Seems to me that the main advantage of a switch is that it makes it immediately obvious to the reader that all the options depend on the same variable. You certainly could write an if/elseif/elseif block that accomplished the same thing, but then the reader would have to carefully check that indeed it is the same variable being tested every time.

There's also the nightmare maintenance scenario where you have a long if/elseif on the same variable and someone decides to change the variable name, and so he changes all of the if's ... except he misses one.

As others have pointed out, there's also the fact that the compiler can usually optimize it better.

Jay
A: 

Don't ask a python programmer this question as the language doesn't have a switch statement and encourage the use of dictionaries instead.

To answer your question, I can think of one case where a switch statement is useful. It is useful when the language / compiler / static analyzer can make sure that you're checking all cases. This works good with enums.

If you add another item to an enumeration, you can now get warnings in all of the places where you are doing a switch on that kind of enumeration telling you that you're missing a case.

eric.frederich
I don't think this is an advantage as a final `else` block at the end of a `if..else if...`-chain achieves the same thing... `switch` is not `enum`-friendlier than `if`.
mxp