Professional C# 6 and .NET Core 1.0. Christian Nagel

Читать онлайн книгу.

Professional C# 6 and .NET Core 1.0 - Christian Nagel


Скачать книгу
a line of code:

      Use inline comments with care because they can make code hard to read. However, they can be useful when debugging if, for example, you temporarily want to try running the code with a different value somewhere:

      Comment characters included in string literals are, of course, treated like normal characters:

      XML Documentation

      In addition to the C-type comments, illustrated in the preceding section, C# has a very neat feature: the capability to produce documentation in XML format automatically from special comments. These comments are single-line comments, but they begin with three slashes (///) instead of the usual two. Within these comments, you can place XML tags containing documentation of the types and type members in your code.

      The tags in the following table are recognized by the compiler.

      Add some XML comments to the Calculator.cs file from the previous section. You add a <summary> element for the class and for its Add method, and a <returns> element and two <param> elements for the Add method:

Understanding C# Preprocessor Directives

      Besides the usual keywords, most of which you have now encountered, C# also includes a number of commands that are known as preprocessor directives. These commands are never actually translated to any commands in your executable code, but they affect aspects of the compilation process. For example, you can use preprocessor directives to prevent the compiler from compiling certain portions of your code. You might do this if you are planning to release two versions of it – a basic version and an enterprise version that will have more features. You could use preprocessor directives to prevent the compiler from compiling code related to the additional features when you are compiling the basic version of the software. In another scenario, you might have written bits of code that are intended to provide you with debugging information. You probably don’t want those portions of code compiled when you actually ship the software.

      The preprocessor directives are all distinguished by beginning with the # symbol.

      NOTE C++ developers will recognize the preprocessor directives as something that plays an important part in C and C++. However, there aren’t as many preprocessor directives in C#, and they are not used as often. C# provides other mechanisms, such as custom attributes, that achieve some of the same effects as C++ directives. Also, note that C# doesn’t actually have a separate preprocessor in the way that C++ does. The so-called preprocessor directives are actually handled by the compiler. Nevertheless, C# retains the name preprocessor directive because these commands give the impression of a preprocessor.

      The following sections briefly cover the purposes of the preprocessor directives.

      #define and #undef

      #define is used like this:

      This tells the compiler that a symbol with the given name (in this case DEBUG) exists. It is a little bit like declaring a variable, except that this variable doesn’t really have a value – it just exists. Also, this symbol isn’t part of your actual code; it exists only for the benefit of the compiler, while the compiler is compiling the code, and has no meaning within the C# code itself.

      #undef does the opposite, and removes the definition of a symbol:

      If the symbol doesn’t exist in the first place, then #undef has no effect. Similarly, #define has no effect if a symbol already exists.

      You need to place any #define and #undef directives at the beginning of the C# source file, before any code that declares any objects to be compiled.

      #define isn’t much use on its own, but when combined with other preprocessor directives, especially #if, it becomes very powerful.

      NOTE Incidentally, you might notice some changes from the usual C# syntax. Preprocessor directives are not terminated by semicolons and they normally constitute the only command on a line. That’s because for the preprocessor directives, C# abandons its usual practice of requiring commands to be separated by semicolons. If the compiler sees a preprocessor directive, it assumes that the next command is on the next line.

      #if, #elif, #else, and #endif

      These directives inform the compiler whether to compile a block of code. Consider this method:

      This code compiles as normal except for the Console.WriteLine method call contained inside the #if clause. This line is executed only if the symbol DEBUG has been defined by a previous #define directive. When the compiler finds the #if directive, it checks to see whether the symbol concerned exists, and compiles the code inside the #if clause only if the symbol does exist. Otherwise, the compiler simply ignores all the code until it reaches the matching #endif directive. Typical practice is to define the symbol DEBUG while you are debugging and have various bits of debugging-related code inside #if clauses. Then, when you are close to shipping, you simply comment out the #define directive, and all the debugging code miraculously disappears, the size of the executable file gets smaller, and your end users don’t get confused by seeing debugging information. (Obviously, you would do more testing to ensure that your code still works without DEBUG defined.) This technique is very common in C and C++ programming and is known as conditional compilation.

      The #elif (=else if) and #else directives can be used in #if blocks and have intuitively obvious meanings. It is also possible to nest #if blocks:

      #if and #elif support a limited range of logical operators too, using the operators !, ==, !=, and ||. A symbol is considered to be true if it exists and false if it doesn’t. For example:

      #warning and #error

      Two other very useful preprocessor directives are #warning and #error. These will respectively cause a warning or an error to be raised when the compiler encounters them. If the compiler sees a #warning directive, it displays whatever text appears after the #warning to the user, after which compilation continues. If it encounters a #error directive, it displays the subsequent text to the user as if it is a compilation error message and then immediately abandons the compilation, so no IL code is generated.

      You can use these directives as checks that you haven’t done anything silly with your #define statements; you can also use the #warning statements to remind yourself to do something:

      #region and #endregion

      The #region and #endregion directives are used to indicate that a certain block of code is to be treated as a single block with a given name, like this:

      This doesn’t look that useful by itself; it doesn’t affect the compilation process in any way. However, the real advantage is that these directives are recognized by some editors, including the Visual Studio editor. These editors can use the directives to lay out your code better on the screen. You find out how this works in Chapter 17.

      #line

      The #line directive can be used to alter the filename and line number information that is output by the compiler in warnings and error messages. You probably won’t want to use this directive very often. It’s most useful when you are coding in conjunction with another package that alters the code you are typing before sending it to the compiler. In this


Скачать книгу