Tutorial C#
Como ya se ha comentado, la
principal utilidad del preprocesador en C# es la de permitir determinar cuáles
regiones de código de un fichero fuente se han de compilar. Para ello, lo que se
hace es encerrar las secciones de código opcionales dentro de directivas de
compilación condicional, de modo que sólo se compilarán si determinados
identificadores de preprocesado están definidos. Para definir un identificador
de este tipo la directiva que se usa sigue esta sintaxis:
#define
<nombreIdentificador>
Esta directiva define un
identificador de preprocesado <nombreIdentificador>.
Aunque más adelante estudiaremos detalladamente cuáles son los nombres válidos como
identificadores en C#, por ahora podemos considerar que son válidos aquellos
formados por uno o más caracteres alfanuméricos tales que no sean ni true
ni false
y no empiecen con un numero. Por ejemplo, para definir un
identificador de preprocesado de nombre PRUEBA
se haría:
#define
PRUEBA
Por convenio se da a estos
identificadores nombres en los que todas las letras se escriben en mayúsculas,
como en el ejemplo anterior. Aunque es sólo un convenio y nada obliga a usarlo,
ésta será la nomenclatura que usaremos en el presente documento, que es la
usada por Microsoft en sus códigos de ejemplo. Conviene familiarizarse con ella
porque por un lado hay mucho código escrito que la usa y por otro usarla
facilita la lectura de nuestro código a los demás al ser la notación que
esperarán encontrar.
Es importante señalar que
cualquier definición de identificador ha de preceder a cualquier aparición de
código en el fichero fuente. Por ejemplo, el siguiente código no es válido,
pues antes del #define
se ha incluido código fuente (el class
A):
class A
#define
PRUEBA
{}
Sin embargo, aunque no pueda
haber código antes de un #define,
sí que es posible incluir antes de él otras directivas de preprocesado con
total libertad.
Existe una forma alternativa de
definir un identificador de preprocesado y que además permite que dicha
definición sólo sea válida en una compilación en concreto. Esta forma consiste
en pasarle al compilador en su llamada la opción /d:<nombreIdentificador> (forma
abreviada de /define:<nombreIdentificador>),
caso en que durante la compilación se considerará que al principio de todos los
ficheros fuente a compilar se encuentra definido el identificador indicado. Las
siguientes tres formas de llamar al compilador son equivalentes y definen
identificadores de preprocesado de nombres PRUEBA
y TRAZA durante la compilación de
un fichero fuente de nombre ejemplo.cs:
csc /d:PRUEBA /d:TRAZA ejemplo.cs
csc /d:PRUEBA,TRAZA ejemplo.cs
csc /d:PRUEBA;TRAZA ejemplo.cs
Nótese en el ejemplo que si
queremos definir más de un identificador usando esta técnica tenemos dos
alternativas: incluir varias opciones /d en la llamada al
compilador o definir varios de estos identificadores en una misma opción /d
separándolos mediante caracteres de coma (,) o punto y coma (;)
Si se trabaja con Visual
Studio.NET en lugar de directamente con el compilador en línea de comandos,
entonces puede conseguir mismo efecto a través de View à
Property Pages à
Configuration Options à Build
à
Conditional Compilation Constants, donde nuevamente usado el punto y
coma (;)
o la coma (,)
como separadores, puede definir varias constantes. Para que todo funcione bien,
antes de seleccionar View
ha de seleccionar en el Solution Explorer (se abre con View à
Solution Explorer) el proyecto al que aplicar la definición de las
constantes.
Finalmente, respecto al uso de #define sólo queda comentar que es posible definir
varias veces una misma directiva sin que ello provoque ningún tipo de error en
el compilador, lo que permite que podamos pasar tantos valores a la opción /d
del compilador como queramos sin temor a que entren en conflicto con
identificadores de preprocesado ya incluidos en los fuentes a compilar.