2010-09-07 3 views
3

Что делает заявление if, когда оно скомпилировано в IL?Что такое if, если смотреть в IL?

Это очень простая конструкция в C#. Может ли кто-нибудь дать мне более абстрактное определение того, что это на самом деле?

+0

Вы можете проверить это с помощью 'ildasm.exe' из командной строки Visual Studio. –

+0

Это очень простая конструкция, период. Я не знаю в IL, но в коде сборки вы выполняете сравнение, а затем ветку. Очень просто в asm, поэтому нужно предположить, что он так же прост в языке высокого уровня. – Jonathan

+0

На ваш вопрос ответили утверждением этого вопроса ранее. http://stackoverflow.com/questions/3659093/ms-c-compiler-and-non-optimized-code/3660295#3660295 –

ответ

8

Вот несколько if заявления, и как они переводят к IL:

ldc.i4.s 0x2f      var i = 47; 
stloc.0 

ldloc.0       if (i == 47) 
ldc.i4.s 0x2f 
bne.un.s L_0012 

ldstr "forty-seven!"     Console.WriteLine("forty-seven!"); 
call Console::WriteLine 

L_0012: 
ldloc.0       if (i > 0) 
ldc.i4.0 
ble.s L_0020 

ldstr "greater than zero!"    Console.WriteLine("greater than zero!"); 
call Console::WriteLine 

L_0020: 
ldloc.0       bool b = (i != 0); 
ldc.i4.0 
ceq 
ldc.i4.0 
ceq 
stloc.1 

ldloc.1       if (b) 
brfalse.s L_0035 

ldstr "boolean true!"     Console.WriteLine("boolean true!"); 
call Console::WriteLine 

L_0035: 
ret 

Одна вещь, чтобы отметить здесь: инструкции IL всегда «противоположен». if (i > 0) означает что-то, что эффективно означает «если i <= 0, а затем перепрыгнуть через тело блока if».

+0

Ошибка копирования-вставки в куске, начиная с L_0020: повторение ltc.i4.0, затем ceq? –

+1

@AndyDent Нет, это точный результат работы компилятора. Вы можете утверждать, что он может быть написан короче, но если вы просто удалите один 'ldc.i4.0' +' ceq', значение изменится: тогда оно будет означать 'i == 0' вместо' i! = 0 '. – Timwi

+0

понял! (Я думаю), в большой форме, что ИЛ эквивалентен b = ((i == 0) == 0) –

3

Это зависит от состояния if. Например, если вы проверяете ссылку на null, компилятор выдает команду brfalse (или brtrue в зависимости от того, что вы написали).

фактическогоif условия будет отличаться в зависимости от самого состояния, но в dissasembler как ILDASM или отражатель будет лучшим инструментом для изучения более.

1

Простой пример:

ldloc.1     // loads first local variable to stack 
ldc.i4.0     // loads constant 0 to stack 
beq      // branch if equal 

Это было бы равно

if(i == 0) //if i is the first local variable 

Другие МФС будут отличаться, в том числе условных ветвей. Это слишком сложно объяснить в одном посте, вам лучше искать введение в IL-Code.

Существует хорошая статья на codeproject относительно этого.

+0

'ldloc.1' загружает вторую локальную переменную. ☺ Кроме того, в вашем примере 'if' переводит' beq', а не 'ceq'. – Timwi

+0

Обычно ldloc.0 является локальным классом. вы правы с беком, конечно. – Femaref

3

Используется инструкция перехода, которая будет переходить к целевой команде в зависимости от значения (ов) в верхней части стека.

brfalse Branch to target if value is zero (false) 
brtrue Branch to target if value is non-zero (true) 
beq  Branch to target if equal 
bge  Branch to target if greater than or equal to 
bgt  Branch to target if greater than 
ble  Branch to target if less than or equal to 
blt  Branch to target if less than 
bne.un Branch to target if unequal or unordered