原文: https://www.programiz.com/csharp-programming/preprocessor-directives

在本教程中,我们将学习预处理器指令,C# 中的可用指令以及何时,为什么以及为什么使用它们。

顾名思义,预处理器指令是在实际编译开始之前进行处理的语句块。 C# 预处理器指令是影响编译过程的编译器命令。

这些命令指定要编译的代码部分或如何处理特定的错误和警告。

C# 预处理器指令以# (hash)符号开头,所有预处理器指令都持续一行。 预处理器指令由new line而不是semicolon终止。

C# 中可用的预处理器指令为:

Preprocessor directives in C#

#if

检查预处理器表达式是否为真

  1. #if preprocessor-expression
  2. code to compile
  3. #endif

#elif

#if一起使用以检查多个预处理器表达式

  1. #if preprocessor-expression-1
  2. code to compile
  3. #elif preprocessor-expression-2
  4. code to compile
  5. #endif

#else

#if一起使用以创建复合条件指令。

  1. #if preprocessor-expression
  2. code to compile
  3. #elif
  4. code to compile
  5. #endif

#endif

#if一起使用以指示条件指令的结尾

  1. #if preprocessor-expression
  2. code to compile
  3. #endif

#define

用于定义符号

  1. #define SYMBOL

#undef

用于取消定义符号

  1. #undef SYMBOL

#warning

允许我们从代码中生成 1 级警告

  1. #warning warning-message

#error

允许我们从代码中生成错误

  1. #error error-message

#line

允许我们修改编译器的行号和文件名以显示错误和警告

  1. #line line-number file-name

#region

允许我们创建一个使用 Visual Studio 代码编辑器时可以扩展或折叠的区域

  1. #region region-description
  2. codes
  3. #endregion

#endregion

指示区域的结尾

  1. #region region-description
  2. codes
  3. #endregion

#pragma

为编译器提供特别的说明,以编译其中出现的文件。

  1. #pragma pragma-name pragma-arguments

#define指令

  • #define指令允许我们定义符号。

  • #if伪指令一起使用时定义的符号将求值为true

  • 这些符号可用于指定编译条件。

  • 语法

    1. #define SYMBOL
  • 例如
    1. #define TESTING


在这里,TESTING是一个符号。


#undef指令

  • #undef指令允许我们取消定义符号。

  • #if伪指令一起使用时,未定义的符号将计算为false

  • 语法

    1. #undef SYMBOL
  • 例如:
    1. #undef TESTING


在这里,TESTING是一个符号。


#if指令

  • #if指令用于测试预处理器表达式。

  • 预处理器表达式可以仅由符号组成,也可以由符号的组合以及&&(AND),||(OR),!(NOT)等运算符组成。

  • #if指令后跟#endif指令。

  • 仅当使用#if测试的表达式的值为true时,才会编译#if指令中的代码。

  • 语法

    1. #if preprocessor-expression
    2. code to compile<
    3. #endif
  • 例如
    1. #if TESTING
    2. Console.WriteLine("Currently Testing");
    3. #endif

示例 1:如何使用#if指令?

  1. #define CSHARP
  2. using System;
  3. namespace Directive
  4. {
  5. class ConditionalDirective
  6. {
  7. public static void Main(string[] args)
  8. {
  9. #if (CSHARP)
  10. Console.WriteLine("CSHARP is defined");
  11. #endif
  12. }
  13. }
  14. }

当我们运行程序时,输出将是:

  1. CSHARP is defined

在上述程序中,CSHARP符号是在程序开头使用#define指令定义的。 在Main()方法内部,#if指令用于测试CSHARP是否为true。 仅当定义了CSHARP时,才编译#if指令内的代码块。


#elif指令

  • #elif指令与#if指令一起使用,可让我们创建复合条件指令。

  • 在测试多个预处理器表达式时使用它。

  • 仅当用#elif测试的表达式的值为真时,才编译#elif指令中的代码。

  • 语法

    1. #if preprocessor-expression-1
    2. code to compile
    3. #elif preprocessor-expression-2
    4. code-to-compile
    5. #endif
  • 例如
    1. #if TESTING
    2. Console.WriteLine("Currently Testing");
    3. #elif TRAINING
    4. Console.WriteLine("Currently Training");
    5. #endif

#else指令

  • #else指令与#if指令一起使用。

  • 如果前面的#if#elif指令(如果存在)中的表达式都不为真,则将编译#else指令中的代码。

  • 语法

    1. #if preprocessor-expression-1
    2. code to compile
    3. #elif preprocessor-expression-2
    4. code-to-compile
    5. #else
    6. code-to-compile
    7. #endif
  • 例如
    1. #if TESTING
    2. Console.WriteLine("Currently Testing");
    3. #elif TRAINING
    4. Console.WriteLine("Currently Training");
    5. #else
    6. Console.WriteLine("Neither Testing nor Training");
    7. #endif

#endif指令

  • #endif指令与#if指令一起使用以指示#if指令的结尾。

  • 语法

    1. #if preprocessor-expression-1
    2. code to compile
    3. #endif
  • 例如
    1. #if TESTING
    2. Console.WriteLine("Currently Testing");
    3. #endif

示例 2:如何使用条件指令(ifelifelseendif)?

  1. #define CSHARP
  2. #undef PYTHON
  3. using System;
  4. namespace Directive
  5. {
  6. class ConditionalDirective
  7. {
  8. static void Main(string[] args)
  9. {
  10. #if (CSHARP && PYTHON)
  11. Console.WriteLine("CSHARP and PYTHON are defined");
  12. #elif (CSHARP && !PYTHON)
  13. Console.WriteLine("CSHARP is defined, PYTHON is undefined");
  14. #elif (!CSHARP && PYTHON)
  15. Console.WriteLine("PYTHON is defined, CSHARP is undefined");
  16. #else
  17. Console.WriteLine("CSHARP and PYTHON are undefined");
  18. #endif
  19. }
  20. }
  21. }

当我们运行程序时,输出将是:

  1. CSHARP is defined, PYTHON is undefined

在此示例中,我们可以看到#elif#else指令的使用。 当有多个条件要测试时,将使用这些指令。 同样,可以使用逻辑运算符组合符号以形成预处理器表达式。


#warning指令

  • #warning指令允许我们从代码中生成用户定义的一级警告。

  • 语法

    1. #warning warning-message
  • 例如
    1. #warning This is a warning message

示例 3:如何使用#warning指令?

  1. using System;
  2. namespace Directives
  3. {
  4. class WarningDirective
  5. {
  6. public static void Main(string[] args)
  7. {
  8. #if (!CSHARP)
  9. #warning CSHARP is undefined
  10. #endif
  11. Console.WriteLine("#warning directive example");
  12. }
  13. }
  14. }

当我们运行程序时,输出将是:

  1. Program.cs(10,26): warning CS1030: #warning: 'CSHARP is undefined' [/home/myuser/csharp/directives-project/directives-project.csproj]
  2. #warning directive example

运行上面的程序后,我们将看到上面的输出。 文本表示警告消息。 在这里,我们正在使用#warning指令生成用户定义的警告消息。

请注意,也会执行#warning指令之后的语句。 这意味着#warning指令不会终止程序,只会发出警告。


#error指令

  • #error指令允许我们从代码中生成用户定义的错误。

  • 语法

    1. #error error-message
  • 例如
    1. #error This is an error message

示例 4:如何使用#error指令?

  1. using System;
  2. namespace Directive
  3. {
  4. class Error
  5. {
  6. public static void Main(string[] args)
  7. {
  8. #if (!CSHARP)
  9. #error CSHARP is undefined
  10. #endif
  11. Console.WriteLine("#error directive example");
  12. }
  13. }
  14. }

当我们运行程序时,输出将是:

  1. Program.cs(10,24): error CS1029: #error: 'CSHARP is undefined' [/home/myuser/csharp/directives-project/directives-project.csproj]
  2. The build failed. Please fix the build errors and run again.

我们将看到一些错误,可能与上面类似。 在这里,我们正在生成用户定义的错误。

这里要注意的另一件事是程序将终止并且不会像在#warning指令中那样打印#error directive example行。


#line指令

  • #line指令允许我们修改行号和文件名以获取错误和警告。

  • 语法

    1. #line line-number file-name
  • 例如
    1. #line 50 "fakeprogram.cs"

示例 5:如何使用#line指令?

  1. using System;
  2. namespace Directive
  3. {
  4. class Error
  5. {
  6. public static void Main(string[] args)
  7. {
  8. #line 200 "AnotherProgram.cs"
  9. #warning Actual Warning generated by Program.cs on line 10
  10. }
  11. }
  12. }

当我们运行程序时,输出将是:

  1. AnotherProgram.cs(200,22): warning CS1030: #warning: 'Actual Warning generated by Program.cs on line 10' [/home/myuser/csh
  2. arp/directive-project/directive-project.csproj]

我们将上面的示例保存为Program.cs。 该警告实际上是由Program.csline 10生成的。 使用#line指令,我们将行号更改为200,并将文件名更改为AnotherProgram.cs,从而产生了错误。


#region#endregion指令

  • #region指令允许我们创建一个使用 Visual Studio 代码编辑器时可以扩展或折叠的区域。

  • 该指令仅用于组织代码。

  • #region块不能与#if块重叠。 但是,#region块可以包含在#if块内,并且#if块可以与#region块重叠。

  • #endregion指令指示#region块的结尾。

  • 语法

    1. #region region-description
    2. codes
    3. #endregion

示例 6:如何使用#region指令?

  1. using System;
  2. namespace Directive
  3. {
  4. class Region
  5. {
  6. public static void Main(string[] args)
  7. {
  8. #region Hello
  9. Console.WriteLine("Hello");
  10. Console.WriteLine("Hello");
  11. Console.WriteLine("Hello");
  12. Console.WriteLine("Hello");
  13. Console.WriteLine("Hello");
  14. #endregion
  15. }
  16. }
  17. }

当我们运行程序时,输出将是:

  1. Hello
  2. Hello
  3. Hello
  4. Hello
  5. Hello

#pragma指令

  • #pragma指令用于为编译器提供一些特殊的指令,用于编译该文件所在的文件。

  • 该指令可以包括禁用或启用某些警告。

  • C# 支持两条#pragma指令:

    • #pragma warning:用于禁用或启用警告
    • #pragma checksum:它生成用于调试的源文件的校验和。
  • 语法
    1. #pragma pragma-name pragma-arguments
  • 例如
    1. #pragma warning disable

示例 7:如何使用#pragma指令?

  1. using System;
  2. namespace Directive
  3. {
  4. class Error
  5. {
  6. public static void Main(string[] args)
  7. {
  8. #pragma warning disable
  9. #warning This is a warning 1
  10. #pragma warning restore
  11. #warning This is a warning 2
  12. }
  13. }
  14. }

当我们运行程序时,输出将是:

  1. Program.cs(12,22): warning CS1030: #warning: 'This is a warning 2' [/home/myuser/csharp/directive-project/directive-project.csproj]

我们可以看到在输出屏幕上仅显示第二个警告

这是因为,我们最初禁用了第一个警告之前的所有警告,而仅在第二个警告之前将它们还原。 这就是隐藏第一个警告的原因。

我们还可以禁用特定警告而不是所有警告。

要了解有关#pragma的更多信息,请访问#pragma(C# 参考)