In C#, directives influence what code is compiled, and how it is compiled. We can perform conditional compilation based on symbols.
With syntax like #define, directives can add or remove lines of code, without affecting runtime. Many programs can reside in one. Things become complex.
First, this program defines 3 symbols in the initial #define directives. The NET symbol is then undefined. In Main
, we can see that the #if PERLS block is compiled.
elif
, and #endif syntax.Boolean
value.#define PERLS #define PYTHONS #define NET #undef NET using System; class Program { static void Main() { #if PERLS Console.WriteLine("PERLS"); // Compiled. #endif #if DOT || NET Console.WriteLine("DOT OR NET"); // Skipped. #elif PYTHONS Console.WriteLine("PYTHONS"); // Compiled. #endif #if (PERLS || PYTHONS) && !NET Console.WriteLine("PERLS OR PYTHONS"); // Compiled. #endif } }PERLS PYTHONS PERLS OR PYTHONS
This directive organizes code. We create named "regions" of code, terminated with endregion. We can then collapse these regions in Visual Studio.
break
up your code.using System; #region class Example { } #endregion class Program { #region FIELDS int _field1; int _field2; #endregion static void Main() { #region BODY Console.WriteLine("Hello world!"); Console.WriteLine("How are you today?"); #endregion } }Hello world! How are you today?
This example shows that #else is conceptually equivalent to an #elif
with no condition. The #else directive is similar to an else
-statement.
using System; class Program { static void Main() { #if false Console.WriteLine(0); #else Console.WriteLine(1); #endif } }1
The warning and error directives make the compiler complain. This is helpful when generating code—you can force an error to occur if the code is somehow incorrect.
#warning Bad program class Program { static void Main() { #error Don't compile this } }.../Program.cs(1,10): warning CS1030: #warning: 'Bad program' [...] .../Program.cs(7,8): error CS1029: #error: 'Don't compile this' [...] The build failed. Fix the build errors and run again.
The line directive influences warnings and errors. The compiler will report line numbers based on your custom line directive.
using System; class Program { static void Main() { #line 999 throw new Exception(); #line default throw new Exception(); #line hidden throw new Exception(); } }(Comment out first two exceptions to skip them.) Unhandled Exception: ...Program.cs:line 999 Unhandled Exception: ...Program.cs:line 10 Unhandled Exception: ...Program.cs:line 0
Here we define the symbol B, then the symbol A, then undefine the symbol B. The program will compile with A being defined, and B being undefined.
if
-statement in the C# language itself.elif
directive is the same as #if, except it must follow an #if or other #elif
. The #else directive is the default case.elif
or #if #else directive structures.// Define B, then define A. // ... You can use undef at the top here too. // ... Try changing A to C. #define B #define A #undef B using System; class Program { static void Main() { // Use an if/elif/endif construct. #if A Console.WriteLine("a"); #elif B Console.WriteLine("b"); #elif C Console.WriteLine("c"); #endif // Use an if/else/endif construct. #if A Console.WriteLine("a2"); #else Console.WriteLine("!a2"); #endif } }a a2
The default compilation settings in Visual Studio are usually fine. But with pragma, you can adjust them. You can make some warnings disappear.
using System; class Program { static void Main() { // This example has unreachable code! // ... The pragma directives hide the warning. #pragma warning disable if (false) { Console.WriteLine("Perls"); } #pragma warning restore } }
Many useful directives exist in the C# language. Directives, along with comments, have no effect on program runtime. They instead change how a program text is compiled.