TheDeveloperBlog.com


C# Define and Undef Directives

Define, Undef. The #define and #undef directives influence compilation. They should appear at the top of a source file. They can adjust compilation options for the entire file. As directives, they have no affect on runtime performance.


Example. We introduce the #define and #undef directives at the top of the file. The text defines the symbol B, then defines the symbol A, then undefines the symbol B. The program will compile with A being defined, and B being undefined.

Info: The undef directive is the opposite of the define directive. It doesn't matter if the symbol was never defined in the first place.

C# program that uses define and undef directives

// 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
    }
}

Output

a
a2

About #define. In the C# language, the #define line is considered a preprocessing directive. There are some invalid syntaxes for defined symbols. You cannot use a number value as the defined identifier, for example.

Tip: Instead of reading the language specification, you can just experiment in the compiler to see what works.

About #undef. The #undef directive ensures that after the textual point in the file, the specified identifier is not defined. Therefore, in the code, the #undef B cancels out the #define B directive, leaving B not defined.

The #if directive is evaluated as preprocessing time, not runtime. It works in a similar way as the if-statement in the C# language itself. In this program, we use the #if directive in two places.

If, Elif, Endif

So: When the "A" identifier is defined, the #if A directives will result in the following statements being compiled into the metadata.

About #elif. The #elif directive is the same as the #if directive, except it must follow an #if or other #elif directive itself. It is similar to the "else if" construct in the C# language.

Note: It is evaluated in textual order at preprocessing time. Another term for this is lexical order.

The #endif directive serves to terminate the #if #elif or #if #else directive structures. You must use it to signal that the preprocessor should stop ignoring code in a statement list that is being preprocessed out.

The #else directive can come after a #if or #elif directive statement. It provides the default case for a conditional directive construct in the C# language. You must follow the #else directive with a #endif directive.


Directives. The term "directive" indicates a line in the program that is not part of the program's execution logic. Directives provide hints about how the program is compiled, not what it does with instructions and the evaluation stack.

Info: In the C# language, the "using System" line is also a directive, but not a preprocessing directive.

Using System

Summary. We demonstrated the #define and #undef preprocessing directives. These provide a way to conditionally compile or remove parts of the source text. These directives can be a clue that a file is overly complex or not well-organized.

Note: Please see section 9.5 of the ECMA-344 "C# Language Specification", "Pre-processing directives" for a complete reference.