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.
|