C#'s switch statement can compile to a CIL switch instruction, or if/else's, depending on the cases in the statement as mentioned here. Is there a way to force the compiler to always generate the if/else variant in a block of code?
-
16Why would you want to do that? – ilivewithian Apr 18 '09 at 10:46
4 Answers
The simplest way would be to use if/else in your code. Apart from anything else, that makes it clearer to the reader that that's what you want to happen instead of using a switch.
EDIT: Okay, so the readability isn't important for you - but basically if you want the compiled code to change, the source code is going to have to change. You could use the Mono compiler and modify it yourself, but I doubt that there's any way of getting the Microsoft compiler to effectively ignore that you're using a switch statement.

- 1,421,763
- 867
- 9,128
- 9,194
-
The switch statements are generated by a lexical analyser, so readability isn't a concern. Rewriting the generator to produce if/else's is a last resort :) – user55017 Apr 18 '09 at 11:02
Have you tried a different compiler (i.e., Mono), or tried to place your offending classes in a separate assembly and switch to a different language for it?

- 41
- 2
No, you have no control over how the C# compiler will emit the CIL instructions. And even if you could, the AOT or JIT compiler might translate the CIL instructions to native machine code instructions vastly different than what you might expect due to advance compiler optimizations.

- 1,242
- 10
- 22
How are you making the compiler do this? I did a test with VS2008:
public static int DoSomething(int i) {
switch (i) {
case 1: return 0;
case 100: return 1;
case 1000: return 2;
default: return 3;
}
}
compiles to:
.method public hidebysig static int32 DoSomething(int32 i) cil managed
{
.maxstack 2
.locals init (
[0] int32 CS$1$0000,
[1] int32 CS$4$0001)
L_0000: nop
L_0001: ldarg.0
L_0002: stloc.1
L_0003: ldloc.1
L_0004: ldc.i4.1
L_0005: beq.s L_0016
L_0007: ldloc.1
L_0008: ldc.i4.s 100
L_000a: beq.s L_001a
L_000c: ldloc.1
L_000d: ldc.i4 0x3e8
L_0012: beq.s L_001e
L_0014: br.s L_0022
L_0016: ldc.i4.0
L_0017: stloc.0
L_0018: br.s L_0026
L_001a: ldc.i4.1
L_001b: stloc.0
L_001c: br.s L_0026
L_001e: ldc.i4.2
L_001f: stloc.0
L_0020: br.s L_0026
L_0022: ldc.i4.3
L_0023: stloc.0
L_0024: br.s L_0026
L_0026: ldloc.0
L_0027: ret
}
No switch instruction there.
Perhaps you should file a bug with Microsoft?

- 33,800
- 13
- 85
- 120
-
I don't have a compiler available ATM, but I'd be shocked if a jump table were created for a 3 case switch with values 1-1000 (so 1000 entries). Probably something closer to case 1: case 50: – user55017 Apr 18 '09 at 12:16
-
So would I, but I would be surprised if the compiler didn't choose the optimal code also in your case. Note that just my three cases caused 20 IL instructions to be emitted. – erikkallen Apr 18 '09 at 12:50
-
1The compiler does choose the optimal code for execution speed, I want to optimise for memory usage. the 20 IL instructions still take much less memory than a 50-100 entry jump table. – user55017 Apr 18 '09 at 13:03
-
What does the JIT compiler do? It woudl be pointless to optimise the MSIL/CIL only to have the JIT compiler pessimize it. – Tim Long May 18 '09 at 21:42
-
1A C# switch statement generates IL switch instructions only if your values are adjacent (give or take a few holes). It they're not, it will go with bgt (conditional jumps). VB's Select works the same way, for the switches, but will use regular if's if the values are not adjacent. – Yann Schwartz Jun 03 '09 at 00:31