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

21

272

What is the benefit/downside to using a switch statement vs. an if/else in C#. I can't imagine there being that big of a difference, other than maybe the look of your code.

Is there any reason why the resulting IL or associated runtime performance would be radically different?

Related: What is quicker, switch on string or elseif on type?

Edaphic answered 28/12, 2008 at 0:16 Comment(3)
Related topic: https://mcmap.net/q/35713/-is-switch-case-always-wrongZelazny
This question is only interesting in theory for the majority of developers, unless you often find yourself iterating ONE BILLION times. (Then use a switch statement and go from 48 to 43 seconds...) Or in the words of Donald Knuth: "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil" en.wikipedia.org/wiki/Program_optimization#When_to_optimizeDecarlo
I often use if/else instead of switch because of the wonky shared scoping of switch.Dagmardagna
Z
418

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.

Zane answered 28/12, 2008 at 8:6 Comment(7)
Are you sure the C# compiler will produce a hash table? The point I made about the hash table in our comment discussion above was about native compilers, not the C# compiler. What threshold does the C# compiler use to produce a hash table?Peshitta
About ten I think. 20 to be on the safe side. And btw, my anger is not you, but on people upvoting and accepting.Zane
A bit of experimentation suggests count <= 6: "if"; count >= 7: dictionary. That's with the MS .NET 3.5 C# compiler - it could change between versions and vendors, of course.Bialy
As a follow up, for practical applications, is there any real world difference most of the time? I find switch statements in C# to be odd, their syntax isn't quite like anything else and I find that they make my code less readable, is it worth bothering to use switch statements, or should I just program with else ifs and only come back and replace them if I hit performance bottlenecks?Lecher
I made a specific test for 18 strings used in our app (3-35 chars long). IFs were faster by 18%.Swatter
@JanSlodicka there are going to be specific cases that don't match the average rule. For example if 90% of your tests are going to match the first if, then if/else if is going to be faster for your case then the average assumption that all results are equally likely.Centering
@Centering Sure, that might be IF's advantage. If I have apriori information about the distribution of incoming strings, then I can write more efficient code.Swatter
P
63

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.

Peshitta answered 28/12, 2008 at 0:16 Comment(9)
There is a switch primitive in MSIL, and c# statements do compile into generally C-like lookup. Under certain circumstances (target platform, cl switches etc) switch may be expanded into IFs during compilation, but it's only a fallback compatibility measure.Zane
Ok... yes there is a switch instructionn. I'm sorry. The switch instruction does not work for string types. I updated my response. Thanks for the correction.Peshitta
I'm sorry you feel that way. Most of what I said was correct, except for a small mistake, which you helped me to fix. Overall, I think stack overflow did it's job there.Peshitta
All I can do is apologize for making a stupid mistake. Believe me, I feel dumb about it. Seriously though, I think it's still the best answer. It is possible, in native compilers, to use a hash table to implement a jump, so this isn't some horribly wrong thing. I made one mistake.Peshitta
ima, if there are errors, point them out. Sounds like Scott will be happy to correct the post. If not, others who have attained the ability to correct an answer will do so. That's the only way a site like this will work, and it seems, in general, it is working. Or take your ball and go home :)Philadelphia
A compiler might be able to optimize a large switch case into a binary search, which it might not do with an if/else blockBannockburn
@Scott: I would encourage you to edit the second and third paragraphs to explicitly state "for strings". People may well not read the update at the bottom.Bialy
(Btw, I don't see anything in this question that says it's about strings. It was marked as a dupe of a string question, but this question doesn't say.)Bialy
As mentioned in 5th paragraph above, from which(how many) condition the c# compiler will generate "jump table". Because you said that for small conditions it will not generate".Joannejoannes
M
24

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.

Maziemazlack answered 28/12, 2008 at 0:22 Comment(0)
R
19

Actually, a switch statement is more efficient. The compiler will optimize it to a lookup table whereas with if/else statements it cannot. The downside 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;
}
Richrichara answered 28/12, 2008 at 0:20 Comment(9)
do you have any kind of numbers? I'm curious s to how well a compiler could optimise a swtich statement over a If/ElseEdaphic
yes I believe a switch statement always optimizes to O(1) where an if else statement will be O(n) where n is the position of the correct value in the if/else if statements.Richrichara
In the case of C# this is not true, See my post below for more information.Peshitta
I am not totally certain of that, but I can't find information in the book I swear I found it in. Are you sure you aren't looking at the MSIL code without optimization. It won't create the jump table unless you compile with optimization on.Richrichara
I compiled in both debug and retail mode, and in both cases it generates if / else blocks. Are you sure the book you were looking at was talking about C#? The book was probably either a compiler book or a book about C or C++Peshitta
I don't give a hoot about efficiency here - the main issue is readability. Silly for this to be chosen the best answer. Chose the one that makes the code easy to maintain.Bandeen
Readability aside, I just tested and the switch statement is slightly faster (on an int comparison). I can post the code if anyone is interested.Leninist
According to these tests of the if-else vs switch statement vs the ternary operator, the if-else structure was always the fastest. The code is posted on the test page.Filide
@ScottWisniewski In light of your edits to your previous answer, could some of the comments here be cleaned up?Eade
T
19

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.

Tecumseh answered 28/12, 2008 at 6:27 Comment(0)
J
19

I didn't see anyone else raise the (obvious?) point that the supposed efficiency advantage of the switch statement is dependent on the various cases being approximately equally likely. In cases where one (or a few) of the values are much more likely, the if-then-else ladder can be much faster, by ensuring the most common cases are checked first:

So, for example:

if (x==0) then {
  // do one thing
} else if (x==1) {
  // do the other thing
} else if (x==2) {
  // do the third thing
}

vs

switch(x) {
  case 0: 
         // do one thing
         break;
  case 1: 
         // do the other thing
         break;
  case 2: 
         // do the third thing
         break;
}

If x is zero 90% of the time, the "if-else" code can be twice as fast as the switch-based code. Even if the compiler turns the "switch" into some kind of clever table-driven goto, it still won't be as fast as simply checking for zero.

Jowers answered 15/10, 2009 at 22:32 Comment(2)
No premature optimization! In general, if you have more than just a few cases and they're switch-compatible, the switch statement is better (more readable, sometimes faster). If you know that one case is much more likely, you can pull that out to form an if-else-switch construct and if it's measurably faster, you leave that in. (Repeat, if needed.) IMO that's still reasonably readable. If the switch degenerates and gets too small, a regex-replace will do most of the work of transforming it into an else if-chain.Vocal
The original question (three years ago!) just asked for advantage&disadvantages between if/else and switch. This is one example. I have personally seen this sort of optimization make a significant difference in the runtime of a routine.Jowers
N
8

often it will look better - ie will be easier to understand what's going on. Considering the performance benefit will be extremely minimal at best, the view of the code is the most important difference.

So, if the if/else looks better, use it, otherwise use a switch statement.

Norris answered 28/12, 2008 at 0:22 Comment(0)
B
5

As per this link, IF vs Switch comparison of iteration test using switch and if statement, is like for 1,000,000,000 iterations, Time taken by Switch Statement=43.0s & by If Statement = 48.0s

Which is literally 20833333 iterations per second, So, Should we really need to focus more,

P.S:Just to know the performance difference for small list of conditions.

Bloomfield answered 27/10, 2013 at 6:13 Comment(0)
D
4

Side topic, but I often worry about (and more often see) if/else and switch statement get way too large with too many cases. These often hurt maintainability.

Common culprits include:

  1. Doing too much inside of multiple if statements
  2. More case statements than humanly possible to analyze
  3. Too many conditions in the if evaluation to know what is being looked for

To fix:

  1. Extract to Method refactoring.
  2. Use a Dictionary with method pointers instead of a case, or use an IoC for added configurability. Method factories also can be helpful.
  3. Extract the conditions to their own method
Dormeuse answered 28/12, 2008 at 4:9 Comment(1)
real sample code about babysteps (1,2,3 steps)?Prudery
B
4

If you are just using if or else statement the base solution is using the comparsion ? operator

(value == value1) ? (type1)do this : (type1)or do this;

You can do the or routine in a switch

switch(typeCode)
{
   case TypeCode:Int32:
   case TypeCode.Int64:
     //dosomething here
     break;
   default: return;
}
Brathwaite answered 31/7, 2010 at 17:12 Comment(1)
the ? is called the ternary conditional operator - learn.microsoft.com/en-us/dotnet/csharp/language-reference/…Hughhughes
R
2

This doesn't actually answer your question, but given there will be little difference between the compiled versions, I would urge you to write your code in a way that best describes your intentions. Not only is there a better chance of the compiler doing what you expect, but it will make it easier for others to maintain your code.

If your intention is to branch your program based on the value of one variable/attribute, then a switch statement best represents that intention.

If your intention is to branch your program based on different variables/attributes/conditions, then a if/else if chain best represents that intention.

I will grant that cody is right about people forgetting the break command, but almost as frequently I see people doing complicated if blocks where they get the { } wrong, so lines that should be in the conditional statement are not. It's one of the reasons I always include { } on my if statements even if there's one line in it. Not only is it easier to read, but if I need to add another line in the conditional, I can't forget to add it.

Rhiamon answered 28/12, 2008 at 6:21 Comment(0)
E
2

Interest question. This came up a few weeks ago at work and we found an answer by writing an example snippet and viewing it in .NET Reflector (reflector is awesome!! i love it).

This is what we discovered: A valid switch statement for anything other than a string gets compiled to IL as a switch statement. However IF it is a string it is rewritten as a if/else if/else in IL. So in our case we wanted to know how switch statements compare strings e.g is case-sensitive etc. and reflector quickly gave us an answer. This was useful to know.

If you want to do case-sensitive compare on strings then you could use a switch statement as it is faster than performing a String.Compare in an if/else. (Edit: Read What is quicker, switch on string or elseif on type? for some actual performance tests) However if you wanted to do a case-insensitive then it is better using a if/else as the resulting code is not pretty.

switch (myString.ToLower())
{
  // not a good solution
}

The best rule of thumb is to use switch statements if it makes sense (seriously), e.g:

  • it improves the readability of your code
  • you are comparing a range of values (float, int) or an enum

If you need to manipulate the value to feed into the switch statement (create a temporary variable to switch against) then you probably should be using an if/else control statement.

An update:

It is actually better to convert the string to uppercase (e.g. ToUpper()) as that has been apparently there are further optimizations that the just-in-time compiler can do as when compared to the ToLower(). It is a micro optimization, however in a tight loop it could be useful.


A little side note:

To improve the readability of switch statements try the following:

  • put the most likely branch first i.e. most accessed
  • if they are all likely to occur, list them in alphabetical order so it is easier to find them.
  • never use the default catch-all for the last remaining condition, that's lazy and will cause issues later on in the code's life.
  • use the default catch-all to assert an unknown condition even though it highly unlikely it will ever occur. that is what asserts are good for.
Extragalactic answered 28/12, 2008 at 11:54 Comment(2)
In many cases using ToLower() is the right solution, especially if there are lots of cases and the hash table gets generated.Carse
"If you need to manipulate the value to feed into the switch statement (create a temporary variable to switch against) then you probably should be using an if/else control statement." - Good advice, thanks.Unleash
P
1

Not just C#, but all C-based languages, I think: because a switch is limited to constants, it's possible to generate very efficient code using a "jump table". The C case is really a good old FORTRAN computed GOTO, but the C# case is still tests against a constant.

It is not the case that the optimizer will be able to make the same code. Consider, eg,

if(a == 3){ //...
} else if (a == 5 || a == 7){ //...
} else {//...
}

Because those are compound booleans, the generated code has to compute a value, and shortcircuit. Now consider the equivalent

switch(a){
   case 3: // ...
    break;
   case 5:
   case 7: //...
    break;
   default: //...
}

This can be compiled into

BTABL: *
B3:   addr of 3 code
B5:
B7:   addr of 5,7 code
      load 0,1 ino reg X based on value
      jump indirect through BTABL+x

because you are implicitly telling the compiler that it doesn't need to compute the OR and equality tests.

Paraselene answered 28/12, 2008 at 0:21 Comment(1)
There is no reason a good optimizer cannot handle the 1st code, as long as the optim is implemented. "The compiler cannot optimize" just depends on semantic differences which only the human can reconcile (i.e. if f() is called, it doesn't know that f() always returns 0 or 1).Carse
A
1

The switch statement is definitely the faster then a if else if. There are speedtest that have been supplied on it by BlackWasp

http://www.blackwasp.co.uk/SpeedTestIfElseSwitch.aspx

--Check it out

But depends heavily on the possibilities that you're trying to account for, but I try to use a switch statement whenever possible.

Antemundane answered 15/10, 2009 at 21:30 Comment(0)
O
1

My 2 cents on it. Well most of the times if performance is not a criteria than it's more about code readability. If the the number of if/else statements are too many than using switch statement is better.

Octaviaoctavian answered 18/10, 2020 at 2:30 Comment(0)
R
0

My cs professor suggested not to you switch statements since so often people forgot the break or use it incorrectly. I can;t recall exactly what he said but something along the lines that looking at some seminal code base that showed examples of the switch statement (years ago) had a tons of mistakes in it also.

Rutherfurd answered 28/12, 2008 at 0:45 Comment(1)
Not really an issue in C#. See: #174655 ... and also read #188961 for a discussion on why living in fear may not be the best policy...Tameika
G
0

Something that I just noticed is that you can combine if/else and switch statements! Very useful when needing to check preconditions.

if (string.IsNullOrEmpty(line))
{
    //skip empty lines
}
else switch (line.Substring(0,1))
{
    case "1":
        Console.WriteLine(line);
        break;
    case "9":
        Console.WriteLine(line);
        break;
    default:
        break;
}
Gleeman answered 2/10, 2009 at 13:48 Comment(2)
I know this is old, but I think technically you aren't "combining" anything. Any time you have an "else" without the curly brackets, the next statement will be executed. That statement could be a one-line statement, typically shown indented on the next line, or composite statements such as is the case with if, switch, using, lock, etc. In other words, you can have "else if", "else switch", "else using", etc. Having said that, I do like how it looks and almost looks intentional. (Disclaimer: I haven't tried all these so I MAY be wrong!)Capone
Nelson, you are 100% correct. I figured out why this happens after I had posted this answer.Gleeman
P
0

I Think Switch Is More Faster Than If Conditions like see if There is a program like :

Write a Program to enter any number (between 1 – 99) and check it is in which slot a) 1 – 9 then slot one b) 11 – 19 then slot two c) 21-29 then slot three and so on till 89-99

Then On If You Have Have To Make Many Conditions But Son Switch Case You Have TO Just Type

Switch ( no /10 )

and on case 0 = 1-9 ,case 1 = 11-19 and so on

it will Be So Easy

There Are Many More Such Examples Also!

Picky answered 29/8, 2014 at 15:52 Comment(0)
C
0

a switch statement basicly is a comparison for equality. keyboard event's have a great advantage over switch statement's when having easy to write and read code then an if elseif statement would, missing a {bracket} could get troubling as well.

char abc;
switch(abc)
{
case a: break;
case b: break;
case c: break;
case d: break;
}

An if elseif statement is great for more then one solution if(theAmountOfApples is greater then 5 && theAmountOfApples is less then 10) save your apples else if(theAmountOfApples is greater then 10 || theAmountOfApples == 100) sell your apples. I dont write c# or c++ but I did learn it before I learned java and they are close languages.

Concord answered 25/4, 2015 at 1:49 Comment(0)
S
0

One possible downside of switch statements is its lack of multiple conditions. You can have multiple conditions for the if (else) but not multiple cases statements with different conditions in a switch.

Switch statements are not suitable for logic operations beyond the scope of simple Boolean equations/expressions. For those Boolean equations/expressions, it is eminently suitable but not for other logic operations.

You have much more freedom with the logic available in If statements but the readability can suffer if the If statement becomes unwieldy or is handled poorly.

Both have there place depending on the context of what you are faced with.

Suggest answered 19/6, 2017 at 9:43 Comment(0)
A
0

After reading all the answers before me and browsing all over the web I can say switch case statements can help you to make your code look more neat and manageable. And the performance is also better than else if statements when I tested in my project, because I have to check more than 10 cases (it might sound weird!).

Asdic answered 11/8, 2022 at 9:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.