2009-11-03 16 views
11

Acabo de notar que dado el siguiente código:Compilador Magic: ¿Por qué?

if (x.ID > 0 && !x.IsCool) 

el Microsoft C# 3.0 (VS2008 SP1) compilador optimizarlo a esto:

if (!((x.Id <= 0) || x. IsCool)) 

Se trata de depuración construir sin Optimización habilitado . ¿Por qué el compilador hace eso? ¿Es más rápido en términos de ejecución?

que utilizan reflector de averiguarlo (en realidad estaba buscando algo diferente)

+8

¿Cómo se enteró? –

+1

¿Y qué ocurre con un absorbente inductor de efectos secundarios? :) –

+0

@pst: los efectos secundarios en getters pueden ser ignorados por el compilador. Básicamente, el compilador no puede asumir efectos secundarios en getters y setters. –

Respuesta

49

El compilador C# ciertamente no genera un código C# equivalente para su fragmento. Está compilado a IL. Básicamente, lo que estás viendo (de Reflector, supongo) es el código equivalente de C# que un decompilador escupe para esa IL.

  1. La especificación de idioma no indica qué es un código "no optimizado". El compilador de C# puede generar cualquier código válido y funcionalmente equivalente. Incluso sin la activación de la optimización, el compilador podría realizar optimizaciones básicas. Además de eso, no se puede decir qué es natural para el compilador y si el compilador lo optimizó deliberadamente o no.

  2. La declaración if en su conjunto se evalúa como una secuencia de ramas condicionales basadas en los valores de cada expresión individual especificada en la cláusula "y".La expresión es no evaluada en un solo bloque de código con las instrucciones "y". La salida del decompilador es algo inferido de esas ramas. El descompilador no siempre puede inferir la expresión original que escribió. Simplemente genera algo equivalente.

Del mismo modo, la diferencia entre este fragmento:

if (a) { something(); } 
else { somethingElse(); } 

y este fragmento:

if (!a) { somethingElse(); } 
else { something(); } 

no es algo que te distinga por ver el código compilado.

+3

+1 Esta es la respuesta correcta y explicada de manera sucinta para arrancar. :) –

+1

No quería si esto realmente es una "optimización" (de ahí las comillas). Es el || valores juntos que me preguntaba. Pensé que IL usaría operaciones y operaciones booleanas reales, pero este no es el caso. debajo del capó solo se usa una combinación de ble.s, br.s y brtrue.s. –

8

Creo que estas dos expresiones son exactamente equivalentes desde el punto de vista de la semántica del lenguaje. Ambas formas implican un cortocircuito.

Estoy algo estupefacto porque la respuesta de Andrew ya tiene diez votos ascendentes; a mí me parece una tontería, pero tal vez realmente me estoy perdiendo algo sutil aquí.

EDITAR

Así que para resumir:

La pregunta del OP se pregunta "¿por qué sucede esto optimización".

De hecho, no hay 'optimización'. Los dos códigos fuente de C# son lógicamente equivalentes. ".Net Reflector" o cualquier otra herramienta de desmontaje es probable que descompile el mismo IL en uno u otro. En el nivel IL, solo hay un montón de saltos condicionales, por lo que no hay necesariamente una forma de saber "de qué manera es si y qué es lo demás" u otras equivalencias de DeMorgan similares.

Fascinantemente, la gente está muy contenta de votar con respuestas positivas o negativas a esta pregunta, incluso cuando (o tal vez porque) la pregunta original no tiene mucho sentido (o se basa en una suposición errónea).

Afortunadamente, con el tiempo prevalece la sabiduría de las multitudes (y las personas inteligentes como @Mehrdad). ¡Hurra por StackOverflow!

(Estoy convirtiendo mi respuesta en una wiki, porque no quiero representante para "contar historias sobre una pregunta" cuando se debe otorgar rep a "buenas respuestas a una pregunta". Pero creo que la historia de esta pregunta es interesante.)

+3

@Brian - Estaba estupefacto también considerando el hecho de que era 100% incorrecta :) Eso es lo que recibo por publicar fuera del -Quédate así sin pensar. –

+0

Tiene toda la razón, una diferenciación entre mayúsculas y minúsculas revela que las dos ramas ** ** idénticas son generadas por ambos códigos, de ahí el mismo cortocircuito. Sin embargo, esto es sutil y, a primera vista, pensé que Andrew tenía razón (luego hice todos los casos en mi cabeza). –

+1

:) Me alegra que el diseño de StackOverflow (edición, estilo wiki, votación) signifique que finalmente todo salga bien, incluso si puede ser una montaña rusa durante los primeros minutos de una pregunta. :) – Brian

6

El if compila a un código de operación condicional de salto. Al levantar la negación de la expresión, se puede optimizar intercambiando el objetivo de salto condicional con el bloqueo de caída.

Cuestiones relacionadas