2009-04-18 2 views
4

Оператор switch C# может компилироваться в инструкцию переключения CIL или если/else's, в зависимости от случаев в заявлении, как указано here. Есть ли способ заставить компилятор всегда генерировать вариант if/else в блоке кода?Как остановить инструкцию оператора C# от генерации инструкции переключателя CIL

+15

Зачем вам это нужно? – ilivewithian

ответ

7

Самый простой способ - использовать if/else в коде. Помимо всего прочего, это дает читателю более четкое представление о том, что именно вам нужно , вместо того чтобы использовать коммутатор.

EDIT: Хорошо, поэтому читаемость не важна для вас - но в основном, если вы хотите, чтобы скомпилированный код изменился, исходный код должен измениться. Вы можете использовать компилятор Mono и изменить его самостоятельно, но я сомневаюсь, что есть способ заставить компилятор Microsoft эффективно игнорировать то, что вы используете оператор switch.

+0

Операторы switch генерируются лексическим анализатором, поэтому читаемость не вызывает беспокойства. Перезапись генератора для создания, если/else's является последней инстанцией :) – user55017

2

Вы пробовали использовать другой компилятор (т. Е. Mono) или пытались разместить свои классы-нарушители в отдельной сборке и переключиться на другой язык?

0

Как вы это делаете, компилятор? Я сделал тест с VS2008:

public static int DoSomething(int i) { 
    switch (i) { 
     case 1: return 0; 
     case 100: return 1; 
     case 1000: return 2; 
     default: return 3; 
    } 
} 

компилирует:

.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 
} 

Нет инструкции выключателя там.

Возможно, вы должны зарегистрировать ошибку в Microsoft?

+0

У меня нет компилятора ATM, но я был бы шокирован, если бы была создана таблица прыжка для 3-х корпусного коммутатора со значениями 1-1000 (так что 1000 записей). Вероятно, что-то ближе к случаю 1: случай 50: – user55017

+0

Так бы я, но я был бы удивлен, если бы компилятор не выбрал оптимальный код и в вашем случае. Обратите внимание, что только мои три случая вызвали выброс 20 IL-инструкций. – erikkallen

+1

Компилятор действительно выбирает оптимальный код для скорости выполнения, я хочу оптимизировать использование памяти. 20 IL-команд по-прежнему занимают гораздо меньше памяти, чем таблица перехода на 50-100 записей. – user55017

0

Нет, у вас нет контроля над тем, как компилятор C# выдаст инструкции CIL. И даже если бы вы могли, компилятор AOT или JIT мог бы перевести инструкции CIL на инструкции машинного кода, значительно отличающиеся от того, что вы ожидаете из-за оптимизации оптимизатора компилятора.

 Смежные вопросы

  • Нет связанных вопросов^_^