Is there any significant difference between using if/else and switch-case in C#?

Solution 1:

SWITCH statement only produces same assembly as IFs in debug or compatibility mode. In release, it will be compiled into jump table (through MSIL 'switch' statement)- which is O(1).

C# (unlike many other languages) also allows to switch on string constants - and this works a bit differently. It's obviously not practical to build jump tables for strings of arbitrary lengths, so most often such switch will be compiled into stack of IFs.

But if number of conditions is big enough to cover overheads, C# compiler will create a HashTable object, populate it with string constants and make a lookup on that table followed by jump. Hashtable lookup is not strictly O(1) and has noticeable constant costs, but if number of case labels is large, it will be significantly faster than comparing to each string constant in IFs.

To sum it up, if number of conditions is more than 5 or so, prefer SWITCH over IF, otherwise use whatever looks better.

Solution 2:

In general (considering all languages and all compilers) a switch statement CAN SOMETIMES be more efficient than an if / else statement, because it is easy for a compiler to generate jump tables from switch statements. It is possible to do the same thing for if / else statements, given appropriate constraints, but that is much more difficult.

In the case of C#, this is also true, but for other reasons.

With a large number of strings, there is a significant performance advantage to using a switch statement, because the compiler will use a hash table to implement the jump.

With a small number of strings, the performance between the two is the same.

This is because in that case the C# compiler does not generate a jump table. Instead it generates MSIL that is equivalent to IF / ELSE blocks.

There is a "switch statement" MSIL instruction that when jitted will use a jump table to implement a switch statement. It only works with integer types, however (this question asks about strings).

For small numbers of strings, it's more efficient for the compiler to generate IF / ELSE blocks then it is to use a hash table.

When I originally noticed this, I made the assumption that because IF / ELSE blocks were used with a small number of strings, that the compiler did the same transformation for large numbers of strings.

This was WRONG. 'IMA' was kind enough to point this out to me (well...he wasn't kind about it, but he was right, and I was wrong, which is the important part)

I also made a bone headed assumption about the lack of a "switch" instruction in MSIL (I figured, if there was a switch primitive, why weren't they using it with a hash table, so there must not be a switch primitive.... ). This was both wrong, and incredibly stupid on my part. Again 'IMA' pointed this out to me.

I made the updates here because it's the highest rated post, and the accepted answer.

However,I've made it Community Wiki because I figure I don't deserve the REP for being wrong. If you get a chance, please up vote 'ima''s post.

Solution 3:

Three reasons to prefer the switch:

  • A compiler targeting native code can often compile a switch statement into one conditional branch plus an indirect jump whereas a sequence of ifs requires a sequence of conditional branches. Depending on the density of cases a great many learned papers have been written about how to compile case statements efficiently; some are linked from the lcc compiler page. (Lcc had one of the more innovative compilers for switches.)

  • A switch statement is a choice among mutually exclusive alternatives and the switch syntax makes this control flow more transparent to the programmer then a nest of if-then-else statements.

  • In some languages, including definitely ML and Haskell, the compiler checks to see if you have left out any cases. I view this feature as one of the major advantages of ML and Haskell. I don't know if C# can do this.

An anecdote: at a lecture he gave on receiving an award for lifetime achievement, I heard Tony Hoare say that of all the things he did in his career, there were three that he was most proud of:

  • Inventing Quicksort
  • Inventing the switch statement (which Tony called the case statement)
  • Starting and ending his career in industry

I can't imagine living without switch.

Solution 4:

The compiler is going to optimize pretty much everything into the same code with minor differences (Knuth, anyone?).

The difference is that a switch statement is cleaner than fifteen if else statements strung together.

Friends don't let friends stack if-else statements.

Solution 5:

Actually, a switch statement is more efficient. The compiler will optimize it to a look up table where with if/else statements it cannot. The down side is that a switch statement can't be used with variable values.
You can't do:

switch(variable)
{
   case someVariable
   break;
   default:
   break;
}

it has to be

switch(variable)
{
  case CONSTANT_VALUE;
  break;
  default:
  break;
}