2011-09-05 15 views
7

C# tiene un conditional operator y las declaraciones IF y sospechaba que el operador condicional sería azúcar sintáctica. Entonces, en tiempo de compilación tendría el mismo efecto que una operación IF.¿Por qué tal diferencia en IL entre IF y el operador condicional?

Sin embargo no lo hacen (ver a continuación), sí tienen IL diferente. Tratando de entenderlo y la suposición que tengo es que esta es una optimización del rendimiento que obtiene el operador condicional porque tiene un alcance limitado.

Me gustaría saber si mi suposición es correcta o no, y tal vez si hay más en esto?

También en la IL del IF hay algunas comprobaciones (L_000c, L_000d, L_000f) alrededor de valores int que no puedo entender el significado. Esto es lo que me ha llevado a pensar que esta es una solución más robusta, a costa del rendimiento debido a su mayor alcance.


Código de SI

var result = ""; 
if (Environment.Is64BitOperatingSystem) 
{ 
    result = "Yes"; 
} 
else 
{ 
    result = "No"; 
} 
Console.WriteLine(result); 

Código de operador condicional (Me doy cuenta de las diferencias, pero no importa cómo lo cambio - Asignar a la variable etc ... hace muy poca diferencia)

Console.WriteLine("Is the OS x64? {0}", Environment.Is64BitOperatingSystem ? "Yes" : "No"); 

IL para IF

L_0001: ldstr "" 
L_0006: stloc.0 
L_0007: call bool [mscorlib]System.Environment::get_Is64BitOperatingSystem() 
L_000c: ldc.i4.0 
L_000d: ceq 
L_000f: stloc.2 
L_0010: ldloc.2 
L_0011: brtrue.s L_001d 
L_0013: nop 
L_0014: ldstr "Yes" 
L_0019: stloc.0 
L_001a: nop 
L_001b: br.s L_0025 
L_001d: nop 
L_001e: ldstr "No" 
L_0023: stloc.0 
L_0024: nop 
L_0025: ldloc.0 
L_0026: call void [mscorlib]System.Console::WriteLine(string) 

IL f o condicional

L_002c: ldstr "Is the OS x64? {0}" 
L_0031: call bool [mscorlib]System.Environment::get_Is64BitOperatingSystem() 
L_0036: brtrue.s L_003f 
L_0038: ldstr "No" 
L_003d: br.s L_0044 
L_003f: ldstr "Yes" 
L_0044: call void [mscorlib]System.Console::WriteLine(string, object) 
+3

Solo para estar seguro: ¿Está compilando en modo Release (Los NOP hacen que se vea como el Modo de depuración a primera vista)? En el modo de depuración, el compilador no realiza todas las optimizaciones para facilitar la depuración. –

+1

¿Este es el modo de depuración o versión? Los "nop" intercalados se usan para puntos de ruptura, hasta donde yo sé. –

+1

¿Ambos están en modo de lanzamiento? –

Respuesta

6

si

IL_0000: call  bool [mscorlib]System.Environment::get_Is64BitOperatingSystem() 
IL_0005: brfalse.s IL_000f 
IL_0007: ldstr  "Yes" 
IL_000c: stloc.0     // <------ Difference 1 
IL_000d: br.s  IL_0015 
IL_000f: ldstr  "No" 
IL_0014: stloc.0 
IL_0015: ldloc.0 
IL_0016: call  void [mscorlib]System.Console::WriteLine(string) 

? (Operador ternario)

IL_001b: call  bool [mscorlib]System.Environment::get_Is64BitOperatingSystem() 
IL_0020: brtrue.s IL_0029 
IL_0022: ldstr  "No"   // <------ Difference 2 
IL_0027: br.s  IL_002e 
IL_0029: ldstr  "Yes" 
IL_002e: stloc.0 
IL_002f: ldloc.0 
IL_0030: call  void [mscorlib]System.Console::WriteLine(string) 

(casi) mismo código para ambos en modo de lanzamiento. El if agrega un segundo stdloc.0 que el compilador no optimiza. Y la otra diferencia es que el true y el false están invertidos.

(así me entero de que yo debería disparar SIEMPRE hasta WinMerge!)

y esto sería una cuestión interesante. ¿Por qué están invertidos? ¿Hay alguna lógica?

+0

Yip, bien manchado. El problema es el modo de lanzamiento frente al modo de depuración. –

+2

Usted dice "la única diferencia", pero por supuesto, en el '?'case,' 001b'-'0029' está calculando el * valor * de la expresión condicional, y luego se asigna a una variable en '002e', mientras que bajo la instrucción if, hay dos posibles asignaciones (' 000c' y '0014'), que por supuesto podría ser para variables no relacionadas, y la instrucción' if' no * tiene * un valor. –

+0

@Damien_The_Unbeliever Correcto. Corregido Esto me enseña que WinMerge es el mejor amigo del programador :-) – xanatos

Cuestiones relacionadas