What’s wrong with switch statements?

Recently I’ve been noticing a surprising pattern in code I’m reviewing for the kernel. A lot of people seem to have taken to writing code that I’d expect to look like this:

switch (thing) {
case VALUE:
        /* Stuff */
        break;
case BAR:
        /* Nonsense */
        break;
default:
        /* Whatever */
        break;
}

with if statements instead:

if (thing == VALUE) {
        /* Stuff */
} else if (thing == BAR) {
        /* Nonsense */
} else {
        /* Whatever */
}

(where stuff, nonsense and whatever are usually a bit larger). I really don’t understand where this has come from – the if based form isn’t nearly so idiomatic for selecting between a range of values and this seems to have come from nowhere pretty much. Is there some code base out there where this is common practice or something?

Comments (13)

  1. Nick Dyer wrote::

    Possibly related to the lack of switch in python?

    Tuesday, December 20, 2011 at 1:34 pm #
  2. Elessar wrote::

    Switch statements are less powerful: in most languages they cannot operate on strings, or they do no allow to use things like regexes. Thus, perhaps some people get used to use if statements instead?

    Tuesday, December 20, 2011 at 1:53 pm #
  3. niol wrote::

    If you forget break, it will lead to a bug. If you forget a bracket, it will not compile.

    Tuesday, December 20, 2011 at 2:15 pm #
  4. Colin wrote::

    when the meat of the statement is big it’s easier to see what is going on using “if”. When you use “switch” you have to look up a long way to see what is being tested.

    Tuesday, December 20, 2011 at 3:19 pm #
  5. Aaron Toponce wrote::

    Switch statements are generally more powerful than standard ‘if’ conditionals. They have readability, which makes them easier to understand, on their side. They’re easier to debug, and as a result, easier to maintain.

    @Elessar- Can you provide examples of languages where switch statements cannot operate on strings? Python doesn’t have direct “switch” support, but it can be easily emulated using dictionaries, which of course, support strings. Perl uses “when”, which is quite powerful, and operates on strings. Visual Basic has “Case” statements which allow operating on strings. C++ has the STL map container. Many other languages support operating on strings, either with a direct “switch/case” function, or functionality builtin elsewhere in the language.

    Tuesday, December 20, 2011 at 4:05 pm #
  6. John Lightsey wrote::

    Perl also lacks a switch statement. It probably just depends on the language the author programs in most frequently.

    Tuesday, December 20, 2011 at 4:10 pm #
  7. Alvin wrote::

    Since version 5.10, Perl also has a switch statement as part of the core distribution.
    http://perldoc.perl.org/Switch.html

    Tuesday, December 20, 2011 at 4:43 pm #
  8. I’d say the both ways also differ in what is being expressed. In the one case one has multiple cases being formally on the same level. In the other case you have some decision tree to decide what is used. While sometimes such a decision tree might involve different variables and only after some modifications ending up to be only about one variable, there are also cases where the logic is about some decision tree. Even if everything is about the same variable, so a later case might never happen even if it was a switch statement, it can be more expressive to write it as the “first check this condition, otherwise check something else” that it is meant to be.

    The cases you have seen might not have been from the second case, but perhaps the places they got the pattern from had.

    Tuesday, December 20, 2011 at 5:20 pm #
  9. Mark Brown wrote::

    The particular use that I’m seeing a lot of is where people are writing “depending on the value of this enumeration do something” which really doesn’t fit with decision trees or anything like that.

    For the Python (or whatever) programmers I can see that happening, though I’m not sure there’s as large a crossover between audio driver authors and people programming with those languages.

    Tuesday, December 20, 2011 at 5:36 pm #
  10. Bernhard Rlink, actually I’m dealing with a lot of decision tree in kernel from what I witnessed there are two common practices:
    using a data structure that will dynamically resolve a unique state – that paradigm actually use a macro call / function call :
    value = dtree_get_end_state(&value)

    so you will see a switch case for enamurators.

    in cases of getting some number (result and not a state) you would witness a small if else (since switch case can’t be done here).

    the second paradigm is actually coding the dtree (example when taking the exported trees from weka like systems) – this will resolve in an ugly canonical if else structure.

    about the original code I witnessed this kind of practice in audio processing cards propriety code (that can be loaded for specific kernels).

    Tuesday, December 20, 2011 at 11:03 pm #
  11. Anonymous wrote::

    @Aaron: C, the language in question. Switch in C doesn’t do the right thing on char*, for the same reason that == doesn’t; you need strcmp.

    Switch also doesn’t let you write more complex conditions than “subject_of_switch == constant value”. You can’t compare to a non-constant value, you can’t add other conditions, and you can’t call arbitrary predicate functions.

    Also, switch has a lot more visual noise when writing a simple condition; it only makes sense when switching between several different values.

    Wednesday, December 21, 2011 at 12:23 am #
  12. pwnguin wrote::

    Two reasons: firstly, switch is error prone. Just today we encountered a problem at work where the RENAME case fell through to DELETE. Oops.

    Secondly, there’s a legacy concern that lesser compilers will optimize switch poorly. Probably wrong but a pervasively held belief.

    Wednesday, December 21, 2011 at 6:02 am #
  13. barmic wrote::

    In my opinion, the switch statements is quite difficulte to use (don’t forget break), but this statement have few benefits :
    - the value tested is write once
    - the code is more readable (you know that all case is the evaluation of ==)

    For this lats point, when the case blocs is too long I think that the using of functions is a good idea to limit the size of switch to one screen.

    Wednesday, December 21, 2011 at 8:36 am #