2009-04-27 9 views
5

Esta es mi primera pregunta de StackOverflow así que ¡sé agradable! :-)¿Está 'desaprobado #IF DEBUG' en la programación moderna?

Recientemente me encontré con el siguiente ejemplo en algún código fuente C#:

public IFoo GetFooInstance() 
{ 
    #IF DEBUG 
     return new TestFoo(); 
    #ELSE 
     return new Foo(); 
    #ENDIF 
} 

que me llevan a estas preguntas:

  1. es el uso de "debug #IF" no oficial ¿obsoleto? Si no, ¿qué se considera una buena implementación de su uso?
  2. Utilizando una fábrica de clases y/o herramientas como MOQ, RhinoMocks, etc., ¿cómo podría implementarse el ejemplo anterior?

Respuesta

6

El uso de un contenedor de IoC, la función entera se convierte en redundante, en lugar de llamar GetFooInstance que tendría un código similar a:

ObjectFactory.GetInstance<IFoo>(); 

La configuración de su contenedor COI podría estar en código o a través de un archivo de configuración.

+1

Esta respuesta combinada con la respuesta/razonamiento de Mitch Wheat parece ser la mejor respuesta al problema. Gracias chicos. – Michael

+0

Esto no responde a la pregunta inicial que todavía se usa y dónde/cuándo, etc.:( – peteski

4

Nope. Lo utilizamos todo el tiempo para espolvorear información de diagnóstico en nuestros ensamblajes. Por ejemplo, tengo el siguiente atajo utilizado para depurar:

#if DEBUG 
     if(???) System.Diagnostics.Debugger.Break(); 
#endif 

¿Dónde puedo cambiar? a cualquier expresión relevante como Name == "Popcorn". Esto asegura que nada del código de depuración se filtre en la versión de lanzamiento.

+1

¿Cuál sería la ventaja de esto sobre un punto de interrupción condicional? – Richard

+0

La capacidad de activar o desactivar la configuración de depuración modificando una variable. –

+0

Solía ​​hacer eso pero últimamente comencé a usar Debug.Assert(): hace un trabajo muy similar pero sin el dolor de cabeza ocasionado por el ejecutable de depuración que tiene una ruta de ejecución de código ligeramente diferente que el ejecutable de la versión. –

-2

su compilador debe ser lo suficientemente inteligente como para darse cuenta de que:

final DEBUG=false; 
... 
if(DEBUG) 
    return new debugMeh(); 
else 
    return new meh(); 

el método nunca tiene que ser llamado y puede, de hecho, ser compilado fuera del montaje final.

Eso, más el hecho de que incluso la diferencia de rendimiento no optimizado no sería significativo, lo que hace que el uso de una sintaxis diferente sea innecesaria.

EDIT: Me gustaría señalar algo interesante aquí. Alguien en los comentarios que acaba de decir que esto:

#IF DEBUG 
    return new TestFoo(); 
#ELSE 
    return new Foo(); 
#ENDIF 

era más fácil escribir que esto:

if(DEBUG) 
    return new TestFoo(); 
else 
    return new Foo(); 

Me resulta realmente sorprendente las longitudes que la gente vaya a defender el camino que han hecho cosas como correcto Otro dijo que tendrían que definir una variable DEBUG en cada archivo. No estoy seguro acerca de C#, pero en Java por lo general poner un

public static final DEBUG=true; 

en nuestro registrador u otro objeto central de la fábrica (aunque en realidad encontrar mejores maneras de hacer esto - como el uso de DI).

No digo que las mismas instalaciones no existan en C#, estoy sorprendido de la cantidad de personas que acudirán para demostrar que la solución que tienen es la correcta.

+0

Un simple #if es más fácil de escribir y comunica su intención mejor que el código anterior –

+0

I agrego Robert. Además, la declaración regular if se evaluará en el código de publicación (y se determina que es falsa). Eso puede ser una Preocupación por algunas personas –

+0

También puede establecer el símbolo DEBUG globalmente. La variable debería definirse en cada clase por separado ... – MartinStettner

1

Al igual que algunos de los otros carteles que se han mencionado, utilizo sentencias #if todo el tiempo para depurar escenarios.

El estilo de código que ha publicado es más un patrón de creación de fábrica, que es común. Lo uso con frecuencia, y no solo no lo considero depreciado, considero que el uso de las sentencias #if y #define es una herramienta importante en mi bolsa de trucos.

Creo que CastleWindsor (http://www.castleproject.org/container/index.html) también tiene un contenedor IoC. Creo que el patrón general es que en el archivo de configuración, declaras que TestFoo o IFoo será la clase creada cuando CastleWindsor inicialice el contenedor IoC.

-1

No acepto #if; en lugar de utilizar if con una constante manifiesta:

#define DEBUG 0 // actually in a header or on a command line 

public IFoo GetFooInstance() 
{ 
    if (DEBUG) 
     return new TestFoo(); 
    else 
     return new Foo(); 
} 

¿Por qué es #IF malo? Porque en la versión #IF, , no todos los códigos están marcados. Para códigos complicados y de larga duración, bitrot puede establecerse, y de repente necesita DEBUG pero el código no se compilará. Con la versión if, el código siempre se compila e, incluso con la configuración de optimización más mínima, el compilador eliminará por completo el código inalcanzable. En otras palabras, siempre y cuando DEBUG es conocido ser siempre 0 (y #define lo hará por usted), no hay ninguna tiempo de ejecución costó a la utilización de if.

Y tiene la garantía de que si cambia DEBUG de 0 a 1, el sistema se compilará.

+1

Sin embargo, al usar ese código, se mueve el IF condicional al tiempo de ejecución. r que el tiempo de compilación, lo que puede dar como resultado una ejecución más lenta. Por supuesto, es un ejemplo simple, pero a veces se vuelven complejos ... –

+1

@Billy: la clave es garantizar que la condición sea una constante en tiempo de compilación --- de esa manera se asegura que no haya costo de tiempo de ejecución, y el tiempo de ejecución es exactamente lo mismo en ambos sentidos. –

+0

Suponiendo que se realiza la optimización, y confiar en el compilador de C# para hacer este tipo de cosas es incompleto en el mejor de los casos. No le gusta hacer nada más que optimizaciones muy simples, por ejemplo, 1 + x + 5 no se convertirá constante en 6 + x. Combine eso con el pobre motor de alineación del JIT (ignorando 3.5 SP1) y puede tener resultados inesperados de manera inadvertida. – Promit

1

Sí. Yo les recomiendo vivamente contra el uso de "#IF DEBUG" excepto en raras circunstancias

Era lugar común en C, pero no se debe utilizar en una lengua moderna como C#, por varias razones:

  1. de código (y la cabecera) los archivos se convierten en pesadilla
  2. es muy fácil cometer un error y dejar de entrada/salida de un condicional para una versión de lanzamiento
  3. prueba se convierte en una pesadilla: necesidad de probar muchas combinaciones de generaciones
  4. No todo el código se compile verificado , a menos que usted compilar para TODOS los posibles símbolos condicionales!

@ La respuesta de Richard muestra cómo puede reemplazar el uso de IoC (mucho más limpio).

Cuestiones relacionadas