4

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?

Community
  • 1
  • 1
user55017
  • 41
  • 2

4 Answers4

7

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.

Jon Skeet
  • 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
2

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?

ballarewt
  • 41
  • 2
0

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.

tgiphil
  • 1,242
  • 10
  • 22
0

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?

erikkallen
  • 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
  • 1
    The 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
  • 1
    A 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