Technically C# actually doesn’t have a true preprocessor, but it treats these statements as if they were preprocessor directives. These statements tell C# about how to process pieces of code. The directives are:
- Tests a Boolean value at compile time. If the value is false, then the code that follows is not compiled. In fact, the code isn’t even examined so it could contain syntax errors and the program could still compile.
- Ends an #if block and starts a new block of code. If the #if condition is false, then this block of code is compiled.
- Ends an #if block and tests a new Boolean condition.
- Ends an #if ... #elif ... #else ... #endif series.
- Defines a compile-time constant to be true. You can use the constant with an #if or #elif test.
- Undefines a compile-time constant.
- Generates a warning and adds it to the compiler’s output.
- Generates an error and adds it to the compiler’s output.
- Modifies the compiler’s line number.
- Starts a region that you can expand and collapse. This lets you easily group related pieces of code (for example, methods in a class) so you can collapse them in a group.
- Ends a region.
If they are present, #define directives must come at the top of the file. Note that you can also define a symbol with the /define compiler option.
A third way to define a symbol is to open the Project menu, select Properties, pick the Build tab, and enter the values you want to define in the Conditional Compilation Symbols text box. If you use this method, then the symbol is defined in all of the project’s files.
One of the most common uses for preprocessor directives is to perform different tasks depending on whether different symbols are defined. This example uses the following code to display different messages in its TextBox depending on which (if any) of the debug level values are defined.
// Use a value #defined in this file. #if DEBUG_LEVEL_1 txtDebugLevel.Text = "1"; #elif DEBUG_LEVEL_2 txtDebugLevel.Text = "2"; #else txtDebugLevel.Text = "Other"; #endif
The result is similar to what you get using a normal if-else statement except the code that is included is selected at compile time not at run time.
Note that any code that is not included in the compilation is not even examined by the compiler, so it may contain bugs. It also doesn’t add to the size of the finished executable.