2009-09-20 6 views
8

que he visto en la depuración de aplicaciones .NET 2.0 el siguiente códigocondicional ("Test") + #if DEBUG

[Conditional("DEBUG")] 
void AssertTableExists() { 
    #if DEBUG 
     ... 
    #endif 
} 

¿Hay alguna razón para usar la directiva #if? Quiero decir, por lo que entiendo, el método solo se llamará si se define DEBUG, por lo que no veo un punto para tener el #if en el cuerpo del método.

Respuesta

20

Casualmente respondí su pregunta en mi blog la semana pasada.

http://ericlippert.com/2009/09/10/whats-the-difference-between-conditional-compilation-and-the-conditional-attribute/

La directiva #if es necesario si el cuerpo del método se refiere a entidades que son ellas mismas declararán bajo #if directivas de depuración. Por ejemplo

#if DEBUG 
static private int testCounter = 1; 
#endif 

[Conditional("DEBUG")] void CheckConsistency() 
{ 
#if DEBUG 
    testCounter++; 
#endif 
... 

que no se compilen en el versión de lanzamiento si omite el DEBUG #if en el cuerpo del método.

9

En realidad, hay muchas diferencias. ConditionalAttribute se ve más limpio en el código pero tiene muchas limitaciones y al menos una ventaja sobre #if.

  • #if elimina por completo el código de compilación si no se define símbolo.

  • #if le da un mejor control sobre la granularidad: puede rodear una línea dentro de un método o método completo o ciertos miembros de una clase incluso de toda la clase.

  • #if le permite escriben condiciones complejas como esto:

    #if DEBUG & !NO_NETWORK 
    
  • #if tiene #else y #elif para permitir escenarios más complejos.

  • [condicional] sólo es aplicable a un método único conjunto de regresar void.

  • [Condicional] incluye el código en el ensamblado compilado pero elimina todas las llamadas al mismo. Si alguien hace referencia a su ensamblado, verá los métodos marcados con [Condicional] y podrá usarlos; esto es algo que no puede lograr con #if.

Es interesante abrir ensamblados de .NET Framework con reflector, encontrar métodos marcados como condicional [ "DBG"] y ver su uso. ¡Ninguno de ellos, ni siquiera los internos, se usan en ningún lado! Eso se debe a que Microsoft compiló .Net para su lanzamiento sin el símbolo "DBG" definido, pero en realidad estaban usando esos métodos para depurar .Net durante el desarrollo.

  • No es posible tener dos métodos con las mismas firmas marcados con [condicional] pero se puede lograr con #if.

Como última nota hay que decir que la compilación condicional a veces juega malas juegos cuando llegue comportamiento completamente diferente en depurar y liberar versiones y sólo se enteró de que después de implementar el código y los usuarios empiezan a quejarse. Por lo tanto, como regla general, intente evitar el cambio de comportamiento con #if, utilícelo solo para cambiar los datos de entrada.

Aquí hay un ejemplo del uso de #if - configuración de aplicación diferente para las versiones de depuración y liberación.

static string ConnectionString 
{ 
#if DEBUG 
    get { return "<debug connection string>"; } 
#else 
    get { return "<release connection string>"; } 
#endif 
} 
+1

ConditionalAttribute también se puede aplicar a otras definiciones de atributos; el atributo marcado no se aplicará durante la compilación si la condición no se cumple – thecoop