
Both codes generate the same output. So to see the difference we need to dive little deeper and look at the IL code that gets generated:

The left hand side is the IL code from If-Then-Else while on the right hand side is the IL code from Select-Case. Can you see the difference? Let me explain.
After loading the value of ‘i=15’ on to the evaluation stack (both cases), the If-Then-Else construct executes the instruction bne.un.s (i.e. branch if not equal to OR CMP and JMP in assembly language) 3 times. On the other hand the ‘Select-Case’ creates a ‘jump table’ i.e. a ‘lookup table’ using the switch instruction. The lookup table is 0-indexed. So instead of examining every single case statement separately, we can jump to the right case by simply calculating the offset into the address table.
Here’s how it works:
After the value i=15 is loaded on to the evaluation stack, the integer value 1 is pushed on the stack .Then the instruction sub is executed and the result is pushed on the stack. So in this case the value 14 is pushed to the top of the stack. Now the offset = 14 which gives the address IL_0055 and the execution pointer directly jumps to the specified location. From there it sets ‘j=6’ and prints the value of ‘j’.Similarly if we set i=2, then the offset = 1, which gives the address IL_0050 and execution pointer directly jumps to the specified location. From there it sets ‘j=6’ and then unconditionally jumps (br.s) to IL_0058. It then prints the value of ‘j’ and exits.
Now imagine if you have 50 comparisons to make. If you use If-Then-Else construct you would use 50 bne.us.s (i.e. CMP and JMP) instructions to get to the last match (worst case scenario). While with Select-Case you can jump to the last matching case with a single table lookup. So in terms of worst-case time-complexity we have replaced a O(n) algorithm with O(1) i.e. constant-time algorithm when using Select-Case.
So does this mean the Select-Case construct always performs better than If-Then-Else? There’s your ‘gotcha’! It turns out that the ‘address lookup table’ solution implemented by ‘Select-Case’ can be applied to almost all real-world scenarios with only the offset calculation becoming more complex. There’s only one exception to this rule:


As we see the resulting code does the comparison by examining every case separately i.e. executing the instruction bne.un.s 3 times essentially making it same as the If-Then-Else construct and we get an O(n) algorithm. So in this situation it’s no better than If-Then-Else.
What if we are comparing non-Integers e.g. double? Let’s look at the source code and the underlying IL code:


Again we see that with the same set of cases, when we did Integer comparison, Select-Case generated the lookup table. But with Double it does it the long way i.e. just like If-Else construct and thereby giving us O(n) algorithm.Now what if we are comparing strings? How does Select-Case match up to If-Then-Else? Let’s take a look at the following code:


Again both produce the same output; but what about their IL code?

Surprise! In both cases the compiler uses the instruction bne.us.s to do the individual comparison for each case. Select-case does not generate an ‘address lookup table’ in this scenario. So we get O(n) algorithm when doing string comparison with both Select-Case and If-Then-Else construct i.e.both are same perfromance wise.
Can we do any better when doing string comparison with Select-Case construct?. As it turns out we can do better by using Enumerations when doing string comparison with Select-Case. Let’s re-write the code as follows:

Here's the generated IL code:

As you can see when used with Enumeration, the compiler goes back to generating the ‘address lookup table’ for the Select-Case thereby making it an efficient O(1) algorithm. So it begs the question, if we use Enumeration to do string comparison will If-Else construct will it be as efficient as Select-Case? The answer is no (obviously !!!)
So next time when you are about to make a decision as to which construct to use Select-Case or If-Else, here's the comparison chart to you help you with that decision:
No comments:
Post a Comment