Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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?

share|improve this question
    
Sorry about the tags, I really have no idea what to tag it –  TheLQ Oct 30 '10 at 20:27
    
Ugh. Yeah, that's certainly bulkier, but only in the C family, because its syntax for case statements is so ugly. –  Mason Wheeler Oct 30 '10 at 21:23
4  
This sort of thing has been discussed a lot on stackoverflow: - stackoverflow.com/questions/449273/… - stackoverflow.com/questions/767821/… - stackoverflow.com/questions/97987/switch-vs-if-else –  Yevgeniy Brikman Oct 30 '10 at 22:48
1  
You should avoid both whenever possible. It's much better to create a data structure and do a lookup, even if the lookup target is a function or class. –  kevin cline Jan 3 '12 at 4:03
    
switch is faster, at least in .net. I don't know about Java. –  Knerd Mar 25 at 17:44

10 Answers 10

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.

share|improve this answer
    
That example was only an example BTW. Didn't know though that the compiler can optimize like that –  TheLQ Oct 30 '10 at 21:29
    
@TheLQ - it depends on the language and the compiler of course. But yes, this is a simple optimization to perform, and pretty much essential. –  Stephen C Oct 31 '10 at 0:38
5  
@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. –  Jerry Coffin Nov 1 '10 at 19:23
2  
I think this answer is very specific about the example, while the question was more generic than that... –  Khelben Nov 2 '10 at 16:06
2  
@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. –  Jerry Coffin Nov 2 '10 at 17:20

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...

share|improve this answer
    
Oh yeah, polimorphism. That's not the answer I came here for, but it's the right one. –  Yar Jan 2 '12 at 21:20
3  
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 '12 at 10:34
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.

share|improve this answer
    
If you put the switch in a method and have each case return the proper string, you can eliminate the break statements. –  Robert Harvey Mar 25 at 17:40

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.

share|improve this answer

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.

share|improve this answer

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.

share|improve this answer

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.

share|improve this answer
    
+1 for "not just what, but why" –  Andrew Jan 4 '13 at 11:21

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?

share|improve this answer
    
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. –  Yar Jan 2 '12 at 21:40
1  
@Yar, you are not alone. –  Christopher Mahan Jan 2 '12 at 21:57
    
Python formatting works at stackoverflow but not at programmers.stackexchange.com :( –  Christopher Mahan Jan 2 '12 at 22:05
    
You should alert them at meta unless it's a known topic. Thanks for givin' me a witness. –  Yar Jan 3 '12 at 22:45
1  
@Yar, Reminds me of my wikipedia admin days... Oh Joy. (am I completely off-topic yet?) –  Christopher Mahan Jan 4 '12 at 23:54

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.

share|improve this answer

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.

share|improve this answer
    
return is nice with switch because it avoids the break. –  user1249 Jan 3 '12 at 10:38
1  
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 '12 at 16:11

protected by gnat Mar 25 at 17:35

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

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