ECMA-334 C# Language Specification9.5.4: Conditional compilation directives |
The conditional compilation directives are used to conditionally include or exclude portions of a source file.
pp-if-section
pp-elif-sections
opt pp-else-section
opt pp-endif
whitespace
opt #
whitespace
opt if
whitespace
pp-expression
pp-new-line
conditional-section
opt pp-elif-section
pp-elif-sections
pp-elif-section
whitespace
opt #
whitespace
opt elif
whitespace
pp-expression
pp-new-line
conditional-section
opt whitespace
opt #
whitespace
opt else
pp-new-line
conditional-section
opt whitespace
opt #
whitespace
opt endif
pp-new-line
input-section
skipped-section
skipped-section-part
skipped-section
skipped-section-part
skipped-characters
opt new-line
pp-directive
whitespace
opt not-number-sign
input-characters
opt input-character
except # #if
directive, zero or more #elif
directives, zero or one #else
directive, and an #endif
directive. Between the directives are conditional sections of source code. Each section is controlled by the immediately preceding directive. A conditional section may itself contain nested conditional compilation directives provided these directives form complete sets. end note]
A pp-conditional
selects at most one of the contained conditional-section
s for normal lexical processing:
pp-expression
s of the #if
and #elif
directives are evaluated in order until one yields true. If an expression yields true, the conditional-section
of the corresponding directive is selected. pp-expression
s yield false, and if an #else
directive is present, the conditional-section
of the #else
directive is selected. conditional-section
is selected. The selected conditional-section
, if any, is processed as a normal input-section: the source code contained in the section must adhere to the lexical grammar; tokens are generated from the source code in the section; and pre-processing directives in the section have the prescribed effects.
The remaining conditional-section
s, if any, are processed as skipped-sections: except for pre-processing directives, the source code in the section need not adhere to the lexical grammar; no tokens are generated from the source code in the section; and pre-processing directives in the section must be lexically correct but are not otherwise processed. Within a conditional-section
that is being processed as a skipped-section
, any nested conditional-section
s (contained in nested #if
...#endif
and #region
...#endregion
constructs) are also processed as skipped-section
s.
#define Debug // Debugging on
#undef Trace // Tracing off
class PurchaseTransaction
{
void Commit() {
#if Debug
CheckConsistency();
#if Trace
WriteToLog(this.ToString());
#endif
#endif
CommitHelper();
}
}
#else
section:
#define Debug // Debugging on
class PurchaseTransaction
{
void Commit() {
#if Debug
CheckConsistency();
#else
/* Do something else
#endif
}
}
results in the output:
class Hello
{
static void Main() {
System.Console.WriteLine(@"hello,
#if Debug
world
#else
Nebraska
#endif
");
}
}
hello,
#if Debug
world
#else
Nebraska
#endif
pp-expression
. The example:
always produces the same token stream (class Q
#if X
/*
#else
/* */ class Q { }
#endif
{
}
), regardless of whether or not X is defined. If X is defined, the only processed directives are #if
and #endif
, due to the multi-line comment. If X is undefined, then three directives (#if
, #else
, #endif
) are part of the directive set. end example]