CATEGORII DOCUMENTE |
The pre-processing directives provide the ability to conditionally skip sections of source files, to report error and warning conditions, and to delineate distinct regions of source code. The term "pre-processing directives" is used only for consistency with the C and C++ programming languages. In C#, there is no separate pre-processing step; pre-processing directives are processed as part of the lexical analysis phase.
pp-directive:
pp-declaration
pp-conditional
pp-line
pp-diagnostic
pp-region
pp-new-line:
whitespaceopt
single-line-commentopt
new-line
The following pre-processing directives are available:
#define and #undef, which are used to define and undefine conditional symbols (2.5.3).
#if, #elif, #else, and #endif, which are used to conditionally skip sections of source code (2.5.4).
#line, which is used to control line numbers emitted for errors and warnings (2.5.5).
#error and #warning, which are used to issue errors and warnings (2.5.6).
#region and #endregion, which are used to explicitly mark sections of source code (2.5.7).
A pre-processing directive always occupies a separate line of source code and always begins with a # character and a pre-processing directive name. Whitespace may occur before the # character and between the # character and the directive name.
A source line containing a #define, #undef, #if, #elif, #else, #endif, or #line directive may end with a single-line comment. Delimited comments (the /* */ style of comments) are not permitted on source lines containing pre-processing directives.
Pre-processing directives are not tokens and are not part of the syntactic grammar of C#. However, pre-processing directives can be used to include or exclude sequences of tokens and can in that way affect the meaning of a C# program. For example, the program:
#define
A
#undef B
class C
#else
void G()
#endif
#if B
void H()
#else
void I()
#endif
}
produces the exact same sequence of tokens as the program:
class C
{
void F()
void I()
}
Thus, whereas the two programs are lexically quite different, they are syntactically identical.
The conditional compilation functionality provided by the #if, #elif, #else, and #endif directives is controlled through pre-processing expressions and conditional compilation symbols.
conditional-symbol:
Any identifier-or-keyword
except true or false
A conditional compilation symbol has two possible states: defined or undefined. At the beginning of the lexical processing of a source file, a conditional compilation symbol is undefined unless it has been explicitly defined by an external mechanism (such as a command-line compiler option). When a #define directive is processed, the conditional compilation symbol named in the directive becomes defined in that source file. The symbol remains defined until an #undef directive for that same symbol is processed, or until the end of the source file is reached. An implication of this is that #define and #undef directives in one source file have no effect on other source files in the same program.
When referenced in a pre-processing expression, a defined conditional compilation symbol has the boolean value true, and an undefined conditional compilation symbol has the boolean value false. There is no requirement that conditional compilation symbols be explicitly declared before they are referenced in pre-processing expressions. Instead, undeclared symbols are simply undefined and thus have the value false.
The name space for conditional compilation symbols is distinct and separate from all other named entities in a C# program. Conditional compilation symbols can only be referenced in #define and #undef directives and in pre-processing expressions.
Pre-processing expressions can occur in #if and #elif directives. The !, ==, !=, && and || operators are permitted in pre-processing expressions, and parentheses may be used for grouping.
pp-expression:
whitespaceopt
pp-or-expression whitespaceopt
pp-or-expression:
pp-and-expression
pp-or-expression whitespaceopt || whitespaceopt pp-and-expression
pp-and-expression:
pp-equality-expression
pp-and-expression whitespaceopt && whitespaceopt pp-equality-expression
pp-equality-expression:
pp-unary-expression
pp-equality-expression whitespaceopt == whitespaceopt pp-unary-expression
pp-equality-expression whitespaceopt != whitespaceopt pp-unary-expression
pp-unary-expression:
pp-primary-expression
! whitespaceopt pp-unary-expression
pp-primary-expression:
true
false
conditional-symbol
( pp-expression )
When referenced in a pre-processing expression, a defined conditional compilation symbol has the boolean value true, and an undefined conditional compilation symbol has the boolean value false.
Evaluation of a pre-processing expression always yields a boolean value. The rules of evaluation for a pre-processing expression are the same as those for a constant expression (7.15), except that the only user-defined entities that can be referenced are conditional compilation symbols.
The declaration directives are used to define or undefine conditional compilation symbols.
pp-declaration:
whitespaceopt # whitespaceopt define whitespace
conditional-symbol pp-new-line
whitespaceopt # whitespaceopt undef whitespace
conditional-symbol pp-new-line
The processing of a #define directive causes the given conditional compilation symbol to become defined, starting with the source line that follows the directive. Likewise, the processing of an #undef directive causes the given conditional compilation symbol to become undefined, starting with the source line that follows the directive.
Any #define and #undef directives in a source file must occur before the first token (2.4) in the source file, or otherwise a compile-time error occurs. In intuitive terms, #define and #undef directives must precede any "real code" in the source file.
The example:
#define
#if
Professional ||
#define Advanced
#endif
namespace
Megacorp.Data
#endif
}
is valid because the #define directives precede the first token (the namespace keyword) in the source file.
An #undef directive may undefine a name that is not defined. The example below defines a name and then undefines it twice; the second #undef has no effect but is still legal.
#define
A
#undef A
#undef A
The conditional compilation directives are used to conditionally include or exclude portions of a source file.
pp-conditional:
pp-if-section pp-elif-sectionsopt pp-else-sectionopt pp-endif
pp-if-section:
whitespaceopt # whitespaceopt if pp-expression pp-new-line
conditional-sectionopt
pp-elif-sections:
pp-elif-section
pp-elif-sections pp-elif-section
pp-elif-section:
whitespaceopt # whitespaceopt elif pp-expression pp-new-line
conditional-sectionopt
else-section:
whitespaceopt # whitespaceopt else pp-new-line
conditional-sectionopt
endif-line:
whitespaceopt # whitespaceopt endif pp-new-line
conditional-section:
input-section
skipped-section
skipped-section:
skipped-section-part
skipped-section skipped-section-part
skipped-section-part:
skipped-charactersopt
new-line
pp-directive
skipped-characters:
whitespaceopt
not-number-sign input-charactersopt
not-number-sign:
Any input-character except
#
Conditional compilation directives must be written as sets consisting of, in order, an #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.
A pp-conditional selects at most one of the contained conditional-sections for normal lexical processing:
The pp-expressions 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.
If all pp-expressions yield false, and if an #else directive is present, the conditional-section of the #else directive is selected.
Otherwise, no 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-sections, 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-sections (contained in nested #if#endif and #region#endregion constructs) are also processed as skipped-sections.
The following example illustrates how conditional compilation directives can nest:
#define
Debug // Debugging on
#undef Trace // Tracing off
class
PurchaseTransaction
}
Except for pre-processing directives, skipped source code is not subject to lexical analysis. For example, the following is valid despite the unterminated comment in the #else section:
#define Debug // Debugging on
class
PurchaseTransaction
}
Note, however, that pre-processing directives are required to be lexically correct even in skipped sections of source code.
Pre-processing directives are not processed when they appear inside multi-line input elements. For example, the program:
class
Hello
}
produces the output:
hello,
#if Debug
world
#else
#endif
In peculiar cases, the set of pre-processing directives that are processed might depend on the evaluation of the pp-expression. The example:
#if X
/*
#else
/* */ class Q
#endif
always produces the same token stream (class Q ), regardless of whether X is defined or not. 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.
Line directives may be used to alter the line numbers and source file names that are reported by the compiler in output such as warnings and errors.
pp-line:
whitespaceopt # whitespaceopt line whitespaceopt line-indicator pp-new-line
whitespaceopt # whitespaceopt line default
line-indicator:
decimal-digits whitepaceopt file-nameopt
file-name:
' file-name-characters '
file-name-characters:
file-name-character
file-name-characters
file-name-character
file-name-character:
Any input-character except
'
When no #line directives are present, the compiler reports true line numbers and source file names in its output. The #line directive is most commonly used in meta-programming tools that generate C# source code from some other text input. When processing a #line directive that includes a line-indicator, the compiler treats the line after the directive as having the given line number (and file name, if specified).
A #line default directive reverses the effect of all preceding #line directives. The compiler reports true line information for subsequent lines, precisely as if no #line directives had been processed.
Note that the file-name of a #line directive differs from an ordinary string literal in that escape characters are not processed; the '' character simply designates an ordinary backslash character within a file-name.
The diagnostic directives are used to explicitly generate error and warning messages that are reported in the same way as other compile-time errors and warnings.
pp-diagnostic:
whitespaceopt # whitespaceopt error whitespaceopt pp-message
whitespaceopt # whitespaceopt warning whitespaceopt pp-message
pp-message:
input-charactersopt new-line
The example:
#warning Code review needed before check-in
#if
Debug && Retail
#error A build can't be both debug
and retail
#endif
class Test
always produces a warning ("Code review needed before check-in"), and produces an error ("A build can't be both debug and retail") if the conditional symbols Debug and Retail are both defined.
The region directives are used to explicitly mark regions of source code.
pp-region:
pp-start-region conditional-sectionopt pp-end-region
pp-start-region:
whitespaceopt # whitespaceopt region whitespaceopt pp-message
pp-end-region:
whitespaceopt # whitespaceopt endregion whitespaceopt pp-message
No semantic meaning is attached to a region; regions are intended for use by the programmer or automated tools to mark a section of source code. The message specified in a #region or #endregion directive likewise has no semantic meaning; it merely serves to identify the region. Matching #region and #endregion directives may have different pp-messages.
The lexical processing of a region:
#region
#endregion
corresponds exactly to the lexical processing of a conditional compilation directive of the form:
#if true
#endif
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 975
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved