2010-11-19 14 views
21

Creo que esta es una pregunta simple, así que supongo que me falta algo obvio. Realmente nunca utilizo las directivas de preprocesador pero estaba buscando el código de alguien que sí lo hizo y pensé que era algo con lo que debería estar familiarizado.¿Cuándo utilizar las directivas de preprocesador en .net?

así que miré en el ejemplo de MSDN here que tiene el código:

#define DEBUG 
// ... 
#if DEBUG 
    Console.WriteLine("Debug version"); 
#endif 

Mis dos preguntas son:

  • en el ejemplo anterior, ¿por qué ellos definen de depuración? Tenía la impresión de que se configuró si compila en el modo de lanzamiento de depuración v.
  • mirando el otro ejemplo que tiene #define MYTEST y luego escribe en la consola dependiendo de si está 'definido', pero ¿cómo difiere esto de solo usar una variable? ¿Que me estoy perdiendo aqui?

Respuesta

4

Si usa la variable, todo su código está compilado, cuando usa las directivas del preprocesador, solo parte del código se incluye en el archivo ejecutable/dll.

5

en el ejemplo anterior ¿por qué definen DEBUG? Tenía la impresión de que se configuró si compila en el modo de lanzamiento de depuración v.

Probablemente porque es un código de ejemplo. Está destinado a demostrar cómo trabajan #ifdef y amigos. No esperaría que definiera símbolos como ese en los archivos fuente, a menos que sea para una prueba rápida.

mirando el otro ejemplo que tiene "#define MYTEST" y luego escribe en la consola dependiendo de si está 'definido', pero ¿cómo difiere esto de solo usar una variable? ¿Que me estoy perdiendo aqui?

Si MYTEST no se define en tiempo de compilación, el compilador no emite realmente el código entre las #if y #endif bloques. Por lo tanto, la IL resultante será más pequeña.

Además, tenga en cuenta que estos no son directivas de preprocesador en C#.

+1

[MSDN los llama "directivas de preprocesador"] (http://msdn.microsoft.com/en-us/library/ed8yd1ha.aspx) –

+0

Pero no lo son. Del mismo artículo: * "el compilador no tiene un preprocesador por separado" *. – cdhowie

+4

Probablemente se llaman con más precisión * símbolos de compilación condicional *. Son similares a los encontrados en C++, pero el compilador de C# no tiene un preprocesador por separado. (http://blogs.msdn.com/b/csharpfaq/archive/2004/03/09/86979.aspx) –

2

Tengo un código que necesita un manejo diferente cuando se utiliza el entorno Mono en lugar del CLR, así tengo una directiva Mono en algunos de mis módulos. Creo que este es un mejor ejemplo que depurar

+0

Si el código necesita un manejo diferente, debe verificar si se está ejecutando bajo Mono en tiempo de ejecución y modificar el comportamiento en consecuencia; de esa manera todavía puedes enviar un binario a todas las plataformas. ('if (Type.GetType (" System.MonoType ")! = null) {...}' es la forma recomendada de probar si se está ejecutando en el tiempo de ejecución Mono. Tenga en cuenta que ejecutar en Mono no implica ejecutar en Linux ; Mono está disponible para Windows y para otras plataformas como OS X.) Sin embargo, probar qué tiempo de ejecución está utilizando generalmente es una mala idea. Si estás trabajando en un error Mono, prueba si el error está presente en su lugar. – cdhowie

8

Generalmente, los símbolos de compilación opcionales/condicionales serán proporcionados por el script de compilación. Es bastante raro ver #define, excepto código de depuración muy (si ves lo que quiero decir).

Re utilizando una variable; A menudo uso tales condiciones para manejar código que debe ejecutarse en diferentes tiempos de ejecución (mono, cf, silverlight, etc.). Una variable no puede ser suficiente porque el código no se puede compilar con la plataforma incorrecta (tipos/métodos faltantes, etc.).

En el ejemplo presentado, probablemente hubiera usado Debug.WriteLine; como está decorado con [Conditional("DEBUG")], todas las llamadas se eliminan automáticamente si DEBUG no está definido en la compilación.

4

Me gustaría dar un ejemplo donde he usado la directiva de preprocesador en mi proyecto.

Mi programa crea muchos archivos intermedios en el disco. Utilicé la directiva #DEBUG para eliminar esos archivos solo si mi proyecto está en modo de lanzamiento; de lo contrario, guardo esos archivos para poder ver esos archivos intermedios y determinar qué está sucediendo en el interior.

Cuando mi aplicación está funcionando en el servidor de producción, construyo el proyecto en modo de lanzamiento para que esos archivos se eliminen una vez que se haya completado el procesamiento.

#if (DEBUG==false) 
    deleteTempFiles() 
#endif 
+3

Normalmente hago i # f! DEBUG, sé lo mismo, pero ligeramente más delgado –

+0

@Neil, Tu forma de hacerlo también es correcta, pero prefiero DEBUG = false porque es más clara de leer y comprender. – Shekhar

+0

Recomiendo encarecidamente que no se desactive ningún código de producción en las configuraciones de depuración, ya que puede tener efectos secundarios que nunca se obtendrán al depurar (sí, sé que no debería, pero vamos a conocer la vida, ¿verdad?) Para su ejemplo, lo haría al revés: si está configurado DEPURAR, copie los archivos temporales en otro lugar para su inspección antes de cometer una golpiza. Aunque admito que hay situaciones en las que tienes que burlarte de cosas (servicios de transacciones, etc.). – ofi

16

De hecho, recomendaría usar el atributo condicional en lugar de las declaraciones #if en línea.

[Conditional("DEBUG")] 
private void DeleteTempProcessFiles() 
{ 
} 

Esto no sólo es más limpio y más fácil de leer, ya que no acaban de tener #if, #else dentro de su código. Este estilo es menos propenso a errores durante las ediciones normales de código y también como errores de flujo lógico.

+1

No tenía conocimiento de este estilo. Gracias por publicar. – Shekhar

+0

Se debe tener en cuenta que el método siempre se emitirá independientemente de si se cumple la condición. El atributo solo afecta si * se emitirán * llamadas a este método *; esto hace posible definir un método en una biblioteca y darle '[Conditional (" DEBUG ")]' y esto afectará la compilación contra esta biblioteca. – cdhowie

+0

Excelente, también hay más información sobre esto aquí http://stackoverflow.com/q/3788605/932917 – mstaffeld

1

Lo he usado para muchas cosas. Depurar mensajes que solo quiero en compilaciones de depuración; limpiar archivos temporales; incluye funciones de diagnóstico o acciones.

Cuestiones relacionadas