38

Often when I hear about the switch statement, its put off as a way to replace long if...else chains. But it seems that when I use the switch statement I'm writing more code that I would be just writing if...else. You also have other issues like keeping all variables for all calls in the same scope.

Here's some code that represents the flow I normally write (thanks to diam)

String comment;   // The generated insult.
int which = (int)(Math.random() * 3);  //  Result is 0, 1, or 2.

if (which == 0) {
    comment = "You look so much better than usual.";
} else if (which == 1) {
    comment = "Your work is up to its usual standards.";
} else if (which == 2) {
    comment = "You're quite competent for so little experience.";
} else {
    comment = "Oops -- something is wrong with this code.";
}

Then they want me to replace that with this:

String comment;   // The generated insult.
int which = (int)(Math.random() * 3);  //  Result is 0, 1, or 2.

switch (which) {
    case 0:  
             comment = "You look so much better than usual.";
    break;
    case 1:  
             comment = "Your work is up to its usual standards.";
    break;
    case 2:  
             comment = "You're quite competent for so little experience.";
    break;
    default: 
             comment = "Oops -- something is wrong with this code.";
}

Seems like a lot more code in a much more awkward syntax. But is there really an advantage to using the switch statement?

5

10 Answers 10

62

For this particular situation, it seems to me that both if and case are poor choices. I'd use a simple array:

String comments[] = {
    "You look so much better than usual.",
    "Your work is up to its usual standards.",
    "You're quite competent for so little experience."
};

String comment = comments[(int)(Math.random() * 3)];

As a side note, you should generally compute the multiplier based on the size of the array rather than hard-coding the 3.

As to when you would use a case/switch, the difference from a cascade of if statements (or at least one major difference) is that switch can semi-automatically optimize based on the number and density of values, whereas a cascade of if statements leaves the compiler with little choice but to generate code as you've written it, testing one value after another until it finds a match. With only three real cases, that's hardly a concern, but with a sufficient number it can/could be significant.

9
  • That example was only an example BTW. Didn't know though that the compiler can optimize like that
    – TheLQ
    Oct 30, 2010 at 21:29
  • 6
    @JBRWilkinson. In this case, the out of bounds value is only possible via a compiler bug, which I'm disinclined to spend much time on (a bug in my code to test the result is about as likely as in the generating code). In a situation where an out of bounds value was a real concern (e.g., the index was being received from other code) I'd just check the bounds first, and use it as an index only after the check. Nov 1, 2010 at 19:23
  • 4
    I think this answer is very specific about the example, while the question was more generic than that...
    – Khelben
    Nov 2, 2010 at 16:06
  • 5
    @Khelben: it sounds to me like you didn't bother reading the whole answer. The last paragraph addresses the wider issues. There is a problem though: I find very few situations in which I consider either a case statement or a cascade of if statements suitable. Most of the time, they're a (mediocre) substitute for some sort of map/array type of thing, and you're better off using one of the latter directly. Nov 2, 2010 at 17:20
  • 1
    @Titou: unless the compiler is utterly braindead, the array is going to be built once at compile time, and after that you're just using a static structure. For example, if you were doing this in C or C++, you'd want to make that a static const array, to assure that it always existed (but no language was given in the question, so I tried not to assume one in the answer either). Sep 27, 2016 at 14:48
24

The problem with the if...else if... chain is that when I come along to read it, I have to look at every single if condition to understand what the program is doing. For example, you might have something like this:

if (a == 1) {
    // stuff
} else if (a == 2) {
    // stuff
} else if (a == 3) {
    // stuff
} else if (b == 1) {
    // stuff
} else if (b == 2) {
    // stuff
}

(obviously, for a small number of statements like this, it's not so bad)

I'd have no way of knowing that you changed condition variable half-way through without reading every single statement. However, because a switch limits you to a single condition variable only, I can see at a glance what's happening.

At the end of the day, though, I'd prefer neither switch or a chain of if...else if. Often a better solution is some kind of jump table or dictionary for cases like in the original question, or polymorphism (if your language supports that). It's not always possible, of course, but I'd look for a solution that avoids switch as a first step...

2
  • 4
    polymorphism has the disadvantage of fragmenting the code, making it harder to understand as compared to be in a single location. Hence you may hesitate somewhat before changing into that.
    – user1249
    Jan 3, 2012 at 10:34
  • Why is a jump table / dictionary better than a switch ?
    – Titou
    Sep 27, 2016 at 14:22
15
switch (which) {
  case 0: comment = "String 1"; break;
  case 1: comment = "String 2"; break;
  case 2: comment = "String 3"; break;
  default: comment = "Oops"; break;
}

The above way of writing this type of switch case is fairly common. The reason why you felt the switch case if bulkier is because your body was only one line and with a switch case you also needed the break statement. So the switch case had twice the body size of if else. With more substantial code, the break statement will not add much to the body. For single line body, it is a common practice to write the code in the same line as the case statement.

As others have already mentioned, a switch case makes the intent more clear, you want to make a decision based on the value of a single variable/expression. My comments are purely from a readability point of view and not performance based.

2
  • 3
    If you put the switch in a method and have each case return the proper string, you can eliminate the break statements. Mar 25, 2014 at 17:40
  • Your solution is also the fastest.
    – Titou
    Sep 27, 2016 at 14:28
8

In this case the switch statement more clearly matches the intent of the code: pick an action to take based on a single value.

The if statements on the other hand are much harder to read - you have to look at all of them to be sure what's going on. To me it's less code (even if the character count may be slightly higher) as there's less to mentally parse.

8

I agree with Jerry that an array of strings is better for this particular case, but that in general it's better to use a switch/case statement than a chain of elseifs. It's easier to read, and sometimes the compiler can do a better job of optimizing that way, but there's another benefit as well: it's a heck of a lot easier to debug.

When you hit that switch, you only have to step one time to end up on the right branch, instead of carefully stepping over several if statements one at a time, and possibly hitting the key too quickly and stepping past it and missing something and having to start over.

3

I prefer switch in those kind of cases, it matches much better the point of the code, execute a different statement for each different input value. The if..else acts more like a "trick" to achieve the same effect.

switch statements are also cleaner, it's easy to have a typo hidden in all those ==

Also, for big blocks in C, switch is faster.

else..if can be more appropriate when you have something like ranges (between 1 and 100, do this, between 100 and 200 do that), or in C, when you try to make switch with elements like strings (that is possible in other languages). Which is a same.

I tend to use a lot of switches when I program in C.

3

I generally don't like either approach. Long switch or if statements just beg to be refactored to an object oriented abstraction (however your example I would classify as short, not long).

I would personally wrap that kind of code into a separate helper method.

private string GetInsult()
{
    int which = (int)(Math.random() * 3);  //  Result is 0, 1, or 2.

    switch (which) {
        case 0: return "You look so much better than usual.";
        case 1: return "Your work is up to its usual standards.";
        case 2: return "You're quite competent for so little experience.";
        default: return "Oops -- something is wrong with this code.";
    }
}

public void Foo()
{
    string comment = GetInsult();
    Print(comment);
}

Placing the switch in a separate method allows you to place return statements directly inside the switch statement (at least in c#), eliminating the need for break statements either, making the code much easier to read.

And this is imho much nicer than the if/else if/else if approach.

3
  • 3
    I personally hate the "put it in another method because it looks ugly" way to solve things. Clutters method list and looks worse IMHO. I would only do this if A) the code is duplicated somewhere or B) Could be useful elsewhere
    – TheLQ
    Jan 3, 2012 at 16:11
  • 1
    what method list? and why is your method list being cluttered worse than your code being cluttered? I thought we moved past the "keep everything in one single method so you can see everything at once" age
    – sara
    Jun 1, 2016 at 18:04
  • @TheLQ I agree with you in general, but in this very case the "comment=" is indeed factored by Pete's proposal.
    – Titou
    Sep 27, 2016 at 14:35
2

Pick something that is efficient, terse, and then document not just what you've done, but why.

Code can be revisited, and not always by its original author.

There are times when you might deliberately choose one implementation over another because you're forward-thinking about code that doesn't exist.

0
0

In python, there is no switch statement, because if/elif/else is nice:

a = 5

if a==1:
    print "do this"
elif a == 2:
    print "do that"
elif a == 3:
    print "do the other"
elif 3 < a < 9:
    print "do more"
elif 9 <= a < 15:
    print "do nothing"
else:
    print "say sorry"

Simple right?

6
  • Elif is just an if statement with a few letters missing. It's definitely more like an if statement than a switch statement. The fact the Python does NOT have a switch makes one who hates them (like me) think that they're not alone. Jan 2, 2012 at 21:40
  • Python formatting works at stackoverflow but not at programmers.stackexchange.com :( Jan 2, 2012 at 22:05
  • You should alert them at meta unless it's a known topic. Thanks for givin' me a witness. Jan 3, 2012 at 22:45
  • ya, found out they have it going on at meta.programmers.stackexchange.com/questions/308/… Jan 3, 2012 at 23:34
  • 1
    @Yar, Reminds me of my wikipedia admin days... Oh Joy. (am I completely off-topic yet?) Jan 4, 2012 at 23:54
0

One of the things that makes the C/C# style switch particularly annoying is the insistence on the case value being literals. One nice thing about VB/VB.NET is that select/case allows each case to be any boolean expression. That is convenient. Insofar as a series of mutually exclusive boolean expressions is often helpful, a series of if/else ifs is more flexible, not to mention being more efficient to type and read.

Not the answer you're looking for? Browse other questions tagged or ask your own question.