Explanation:
Preprocessor directives are instructions to the C# compiler to perform some action
during compilation. There is no equivalent functionality in Java. The term preprocessor directive is misleading because the
compilation process does not include a preprocessing step, but the term is a legacy
of C/C++ and has remained to avoid confusion.
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
The following pre-processing directives are available:
#define and #undef, which are used
to define and undefine, respectively, conditional compilation symbols
#if, #elif, #else,
and #endif, which are used to conditionally skip sections
of source code
#line, which is used to control line numbers emitted for
errors and warnings
#error and #warning, which are used
to issue errors and warnings, respectively #region and #endregion, which are used to explicitly mark sections of
source code
A pre-processing directive always occupies a separate line of source code and always
begins with a # character and a pre-processing directive
name. White space 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, when
compiled, the program:
#define A
#undef B
class C {
#if A void F() {}
#else void G() {} #endif
#if B
void H() {}
#else
void I(){}
#endif
}
results in the exact same sequence of tokens as the program:
class C {
void F() {}
void I() {}
}
Thus, whereas the two programs are quite different lexically, they are identical
syntactically.
C# preprocessor is fundamentally very similar to C preprocessor and the whole concept
in C# has been taken from C language specification.
The C preprocessor is a macro processor that is used automatically by the C compiler
to transform your program before actual compilation. It is called a macro processor
because it allows you to define macros, which are brief abbreviations for longer
constructs.
But in C# only concept has been taken from C. But the C# compiler does not have
a separate preprocessor, the directives described in this C# are processed as if
there was one. Unlike C and C++ directives, you cannot use these directives to create
macros.
A preprocessor directive must be the only instruction on a line. Preprocessing directives
are lines in your program that start with `#'. Whitespace is allowed before and
after the `#'. The `#' is followed by an identifier that is the directive name.
For example, `#define' is the directive The C# language's preprocessor directives
are as follows:
·#if
·#else
·#elif
·#endif
·#define
·#undef
·#warning
·#error
·#line
·#region
·#endregion
Main use of directives are:
1.Conditional compilation. Using special preprocessing directives,
you can include or exclude parts of the program according to various conditions.
2.Line control. If you use a program to combine or rearrange source
files into an intermediate file, which is then compiled, you can use line control
to inform the compiler of where each source line originally came from.
3.Error and Warning reporting. The directive `#error' causes the
preprocessor to report a fatal error and the directive `#warning' is like the directive
`#error', but causes the preprocessor to issue a warning and continue preprocessing.
Region and Unregion is new directives. It was not in C and C++ list of directives.
I don't know the intention of C# developers to excludes number of directive from
C and C++ list but they picked what people use atmost from list of C and C++ directive.
Before telling meaning of each preprocessor directive I want to explain how to define
preprocessor directive. There are two method to define directive.
1.Define in your C# program
2.Define them at command line on compile time
Here is example for first way:
Example:
#define TEST
using System;
public class MyClass
{
public static void Main()
{
#if (TEST)
Console.WriteLine("TEST is defined");
#else
Console.WriteLine("TEST is not defined");
#endif
}
}
Output
TEST is defined
In other way you can define it at command line. So program will be like this:
Example
using System;
public class MyClass
{
public static void Main()
{
#if (TEST)
Console.WriteLine("TEST is defined");
#else
Console.WriteLine("TEST is not defined");
#endif
}
}
At compile time user can define as below:
csc /define:TEST MyClass.java
Output
TEST is defined
And if the command line will be like:
csc MyClass.java
Output
TEST is not defined
Now its time to explain about various preprocessor define.
#if directive
The `#if' directive in its simplest form consists of
#if expressioncontrolled text#endif /* expression */
The comment following the `#endif' is not required, but it is a good practice because
it helps people match the `#endif' to the corresponding `#if'. Such comments should
always be used, except in short conditionals that are not nested.
Above two example have shown how to use `#if` directive.
#else directive
The `#else' directive can be added to a conditional to provide alternative text
to be used if the condition is false. This is what it looks like:
#if expressiontext-if-true#else /* Not expression */text-if-false#endif /* Not expression
*/
If expression is nonzero, and thus the text-if-true is active, then `#else' acts
like a failing conditional and the text-if-false is ignored.
#elif directive
`#elif' stands for "else if". Like `#else', it goes in the middle of a `#if'-`#endif'
pair and subdivides it; it does not require a matching `#endif' of its own. Like
`#if', the `#elif' directive includes an expression to be tested.
The text following the `#elif' is processed only if the original `#if'-condition
failed and the `#elif' condition succeeds. More than one `#elif' can go in the same
`#if'-`#endif' group. Then the text after each `#elif' is processed only if the
`#elif' condition succeeds after the original `#if' and any previous `#elif' directives
within it have failed. `#else' is equivalent to `#elif 1', and `#else' is allowed
after any number of `#elif' directives, but `#elif' may not follow `#else'.
Example
#define DEBUG
#define VC_V6
using System;
public class MyClass
{
public static void Main()
{
#if (DEBUG && !VC_V6)
Console.WriteLine("DEBUG is defined");
#elif (!DEBUG && VC_V6)
Console.WriteLine("VC_V6 is defined");
#elif (DEBUG && VC_V6)
Console.WriteLine("DEBUG and VC_V6 are defined");
#else
Console.WriteLine("DEBUG and VC_V6 are not defined");
#endif
}
}
Output
DEBUG and VC_V6 are defined
#endif directive
#endif specifies the end of a conditional directive, which began
with the #if directive.
#define directive
#define lets you define a symbol, such that, by using the symbol
as the expression passed to the #if directive, the expression will evaluate to true
#undef directive
#undef lets you undefine a symbol, such that, by using the symbol
as the expression in a #if directive, the expression will evaluate to false.
Example
// compile with /D:DEBUG
#undef DEBUG
using System;
public class MyClass
{
public static void Main()
{
#if DEBUG
Console.WriteLine("DEBUG is defined");
#else
Console.WriteLine("DEBUG is not defined");
#endif
}
}
Output
DEBUG is not defined
The `#error' and `#warning' Directives
The directive `#error' causes the preprocessor to report a fatal error. The tokens
forming the rest of the line following `#error' are used as the error message.
The directive `#warning' is like the directive `#error', but causes the preprocessor
to issue a warning and continue preprocessing. The tokens following `#warning' are
used as the warning message.
Example 1
#define DEBUG
public class MyClass
{
public static void Main()
{
#if DEBUG
#error DEBUG is defined
#endif
}
}
Example 2
#define DEBUG
public class MyClass
{
public static void Main()
{
#if DEBUG
#warning DEBUG is defined
#endif
}
}
#line
#line is a directive that specifies the original line number and source file name
for subsequent input in the current preprocessor input file.
Example
using System;
public class MyClass
{
public static void Main()
{
#line 100 "abc.sc" // change file name in the compiler output
intt i; // error will be reported on line 101
}
}
#region
#region lets you specify a block of code that you can expand or collapse when using
the outlining feature of the Visual Studio Code Editor.
Example
#region MyClass definition
public class MyClass
{
public static void Main()
{
}
}
#endregion
#endregion
#endregion marks the end of a #region block.
|