El compilador de C# csc.exe
y el lenguaje C# en sí mismo no exponen ninguna constante predefinida para conditional compilation. VisualStudio
solo agrega los valores DEBUG
y TRACE
, que se pueden configurar a través del IDE. El IDE también le permite agregar sus propios símbolos arbitrarios, pero dado que estos son valores esencialmente fijos (invariantes), la capacidad es de uso limitado.
Opciones personalizadas más potentes pueden configurarse editando manualmente su archivo de proyecto .csproj
.Puede configurar conditions aquí para selectively propagate símbolos de compilación condicional en C# basado en la enorme cantidad de medio ambiente y la información de configuración disponible en MSBuild (ver here y here, pero, en principio, no puede haber una lista completa, ya que los componentes dispares arbitrariamente contribuyen metadatos ad-hoc).
Consideremos un ejemplo de trabajo. Un caso en el que es útil compilar condicionalmente es si desea escribir código que se adapte a las herramientas que se descubran durante la compilación. De esta forma puede explotar las últimas características del lenguaje sin perder la capacidad de compilar en máquinas con herramientas más antiguas que, como era de esperar, rechazarían la sintaxis y/o palabras clave de los alienígenas. Para el caso particular de C# 7.0 en vs2017
podemos modificar el .csproj
de la siguiente manera:
archivo .csproj (extracto):

También puede identificar cada una de las más antiguas de C# compiladores, así , degradando graciosamente en el camino. Lo mismo vale para la detección de la versión .NET Framework
(oft-solicitó en StackOverflow [1] [2] [3] [4]) y cualesquiera otras condiciones de construcción ambiente. Estos se dejan como ejercicios para el lector, pero en caso de que quiera copiar/pegar las líneas resaltadas desde arriba, aquí está la versión de texto. Como una actualización sobre la pantalla, he añadido las comillas sencillas para la expresión condicional aquí (aunque todo parecía funcionar sin ellos)
<DefineConstants Condition="'$(VisualStudioVersion)'=='15'">CSHARP7</DefineConstants>
<!-- ... -->
<DefineConstants>DEBUG;TRACE;$(DefineConstants)</DefineConstants>
<!-- ... -->
<DefineConstants>TRACE;$(DefineConstants)</DefineConstants>
De todos modos, de esta manera, ahora se puede escribir condicional de código C# usando #if… #elif… #else… #endif
. Continuando con el caso de ejemplo, el siguiente código utiliza una nueva sintaxis de tupla, solo disponible en C# 7, para intercambiar elementos de la matriz. Por cierto, la versión de tupla no solo es más conciso y/o elegante; sino que también produce un excelente código IL:
#if CSHARP7
(rg[i], rg[j]) = (rg[j], rg[i]); // swap elements: tuple syntax
#else
var t = rg[i]; // swap elements: clunky
rg[i] = rg[j];
rg[j] = t;
#endif
Tenga en cuenta que el IDE Visual Studio
hace procesar correctamente el manual de .csproj
personalizaciones en todos los aspectos. Dada la .csproj
he mostrado anteriormente, el editor de código IDE reconoce correctamente y evalúa la compilación condicional para los fines de IntelliSense
, refactoring
, "oscurecimiento de salida" bloques inactivos de código, etc.
También he mencionado que MSBuild
tiene un tesoro de información disponible, de la cual $(VisualStudioVersion)
fue solo un ejemplo. Desafortunadamente, no es fácil descubrir qué valores están disponibles y qué valores pueden tener en el momento de la construcción. Un truco es poner temporalmente un proyecto C++
en su solución Visual Studio
(si aún no lo tiene) junto con su proyecto C#. Si hace clic con el botón derecho en project properties para este .vcxproj
y luego mira (p. Ej.) "Inclusión adicionales directorios" en la página C/C++
, un menú desplegable aparecerá en el extremo derecho cuando se hace clic para editar:

que obtendrá un cuadro de diálogo con un botón de "macros", que se puede haga clic para obtener una lista de todas las variables MSBuild
disponibles más sus valores esperados de acuerdo con la plataforma y la configuración que están actualmente seleccionadas en el IDE. No pase por alto los campos well-known-item-metadata (con el prefijo %
) en la parte inferior de la lista.

Usted puede obtener una idea de la cantidad de cosas es aquí desde el tamaño de la barra de desplazamiento en la captura de pantalla. (Están en orden alfabético, simplemente me desplacé a esta parte de la sección 'P' porque tenía información personal mínima). Sin embargo, es importante tener en cuenta que las variables (disponibles) y sus valores evolucionan con el tiempo durante el desarrollo de la compilación, por lo que puede encontrar elementos en esta lista que no están disponibles para su .csproj
en el momento en que se procesa .
¡Increíble! ¡Esta respuesta necesita más votos! Especialmente para la pista de C++ :-) – Matt