跳到主要内容

C# 预处理器指令

提示
  1. 预处理器指令基础:C#预处理器指令在编译开始之前处理,以 # 开始,用于指定编译代码的部分或处理特定错误和警告。
  2. 常用预处理器指令:包括 #define#undef 用于定义和取消定义符号,#if, #elif, #else, #endif 用于条件编译,以及 #warning#error 用于生成警告和错误。
  3. 特殊预处理器指令#line 用于修改错误和警告的行号和文件名,#region#endregion 用于创建可折叠的代码区域,而 #pragma 提供特殊编译指令。

正如名称所暗示的那样,预处理器指令是在实际编译开始之前处理的一组语句。C# 预处理器指令是对编译器的命令,影响编译过程。

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

C# 预处理器指令以 #(井号) 符号开始,所有预处理器指令只持续一行。预处理器指令是由 换行符 而不是 分号 终止的。

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

C# 预处理器指令

预处理器指令描述语法
#if检查预处理器表达式是否为真
#if 预处理器表达式
编译的代码
#endif

| | #elif | 与 #if 一起使用,用于检查多个预处理器表达式 |

#if 预处理器表达式-1
编译的代码
#elif 预处理器表达式-2
编译的代码
#endif

| | #else | 与 #if 一起使用,创建复合条件指令。|

#if 预处理器表达式
编译的代码
#elif
编译的代码
#endif

| | #endif | 与 #if 一起使用,指示条件指令的结束|

#if 预处理器表达式
编译的代码
#endif

| | #define | 用于定义一个符号 |

#define 符号

| | #undef | 用于取消定义一个符号 |

#undef 符号

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

#warning 警告信息

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

#error 错误信息

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

#line 行号 文件名

| | #region | 允许我们创建一个区域,可以在使用 Visual Studio 代码编辑器时展开或折叠 |

#region 区域描述
代码
#endregion

| | #endregion | 指示区域的结束 |

#region 区域描述
代码
#endregion

| | #pragma | 为出现的文件给编译器特殊编译指令 |

#pragma 指令名称 指令参数

|

#define 指令

  • #define 指令允许我们定义一个符号。
  • 当与 #if 指令一起使用时,定义的符号将被评估为真。
  • 这些符号可以用于指定编译条件。
  • 语法:
#define 符号
  • 例如:
#define TESTING

这里,TESTING 是一个符号。

#undef 指令

  • #undef 指令允许我们取消定义一个符号。
  • 当与 #if 指令一起使用时,未定义的符号将被评估为假。
  • 语法:
#undef SYMBOL
  • 例如:
#undef TESTING

这里,TESTING 是一个符号。

#if 指令

  • #if 指令用于测试预处理器表达式。
  • 预处理器表达式可能仅包含一个符号,或者符号与操作符(如 &&(与)、||(或)、!(非))的组合。
  • #if 指令后跟着一个 #endif 指令。
  • 只有 #if 测试的表达式计算为真时,#if 指令内的代码才会被编译。
  • 语法:
#if preprocessor-expression
code to compile<
#endif
  • 例如:
#if TESTING
Console.WriteLine("Currently Testing");
#endif

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

#define CSHARP

using System;

namespace Directive
{
class ConditionalDirective
{
public static void Main(string[] args)
{
#if (CSHARP)
Console.WriteLine("CSHARP is defined");
#endif
}
}
}

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

CSHARP is defined

在上面的程序中,使用 #define 指令在程序开始时定义了 CSHARP 符号。在 Main() 方法中,使用 #if 指令测试 CSHARP 是否为真。只有当 CSHARP 被定义时,#if 指令内的代码块才会被编译。

#elif 指令

  • #elif 指令与 #if 指令一起使用,让我们创建复合条件指令。
  • 它在测试多个预处理器表达式时使用。
  • 只有 #elif 测试的表达式计算为真时,#elif 指令内的代码才会被编译。
  • 语法:
#if preprocessor-expression-1
code to compile
#elif preprocessor-expression-2
code-to-compile
#endif
  • 例如:
#if TESTING
Console.WriteLine("Currently Testing");
#elif TRAINING
Console.WriteLine("Currently Training");
#endif

#else 指令

  • #else 指令与 #if 指令一起使用。
  • 如果前面的 #if#elif(如果存在)指令中的所有表达式都不为真,则 #else 指令内的代码将被编译。
  • 语法:
#if preprocessor-expression-1
code to compile
#elif preprocessor-expression-2
code-to-compile
#else
code-to-compile
#endif
  • 例如:
#if TESTING
Console.WriteLine("Currently Testing");
#elif TRAINING
Console.WriteLine("Currently Training");
#else
Console.WriteLine("Neither Testing nor Training");
#endif

#endif 指令

  • #endif 指令与 #if 指令一起使用,以表示 #if 指令的结束。
  • 语法:
#if preprocessor-expression-1
code to compile
#endif
  • 例如:
#if TESTING
Console.WriteLine("Currently Testing");
#endif

示例 2:如何使用条件指令(if, elif, else, endif)?

#define CSHARP
#undef PYTHON

using System;

namespace Directive
{
class ConditionalDirective
{
static void Main(string[] args)
{
#if (CSHARP && PYTHON)
Console.WriteLine("CSHARP 和 PYTHON 都已定义");
#elif (CSHARP && !PYTHON)
Console.WriteLine("CSHARP 已定义,PYTHON 未定义");
#elif (!CSHARP && PYTHON)
Console.WriteLine("PYTHON 已定义,CSHARP 未定义");
#else
Console.WriteLine("CSHARP 和 PYTHON 都未定义");
#endif
}
}
}

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

CSHARP 已定义,PYTHON 未定义

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

#warning 指令

  • #warning 指令允许我们从代码中生成用户定义的一级警告。
  • 语法:
#warning 警告信息
  • 例如:
#warning 这是一个警告信息

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

using System;

namespace Directives
{
class WarningDirective
{
public static void Main(string[] args)
{
#if (!CSHARP)
#warning CSHARP 未定义
#endif
Console.WriteLine("#warning 指令示例");
}
}
}

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

Program.cs(10,26): warning CS1030: #warning: 'CSHARP 未定义' [/home/myuser/csharp/directives-project/directives-project.csproj]
#warning 指令示例

运行上述程序后,我们将看到上述输出。文本代表一个警告信息。这里,我们使用 #warning 指令生成了一个用户定义的警告信息。

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

#error 指令

  • #error 指令允许我们从代码中生成用户定义的错误。
  • 语法:
#error 错误信息
  • 例如:
#error 这是一个错误信息

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

using System;

namespace Directive
{
class Error
{
public static void Main(string[] args)
{
#if (!CSHARP)
#error CSHARP 未定义
#endif
Console.WriteLine("#error 指令示例");
}
}
}

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

Program.cs(10,24): error CS1029: #error: 'CSHARP 未定义' [/home/myuser/csharp/directives-project/directives-project.csproj]
构建失败。请修复构建错误并再次运行。

我们将看到一些错误,可能像上面那样。这里我们生成了一个用户定义的错误。

另一个需要注意的地方是,程序将被终止,#error 指令示例 这一行将不会被打印,与 #warning 指令不同。

#line 指令

  • #line 指令允许我们修改错误和警告的行号和文件名。
  • 语法:
#line 行号 文件名
  • 例如:

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

using System;

namespace Directive
{
class Error
{
public static void Main(string[] args)
{
#line 200 "AnotherProgram.cs"
#warning 实际警告由 Program.cs 在第 10 行生成
}
}
}

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

AnotherProgram.cs(200,22): warning CS1030: #warning: '实际警告由 Program.cs 在第 10 行生成' [/home/myuser/csharp/directive-project/directive-project.csproj]

我们将上述示例保存为 Program.cs。警告实际上是在 Program.cs第 10 行 生成的。使用 #line 指令,我们将行号更改为 200,并将生成错误的文件名更改为 AnotherProgram.cs

#region#endregion 指令

  • #region 指令允许我们创建一个区域,该区域可以在使用 Visual Studio Code 编辑器时展开或折叠。
  • 这个指令主要用于组织代码。
  • #region 块不可以与 #if 块重叠。然而,一个 #region 块可以包含在一个 #if 块中,而一个 #if 块可以与一个 #region 块重叠。
  • #endregion 指令表示 #region 块的结束。
  • 语法:
#region 区域描述
代码
#endregion

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

using System;

namespace Directive
{
class Region
{
public static void Main(string[] args)
{
#region Hello
Console.WriteLine("Hello");
Console.WriteLine("Hello");
Console.WriteLine("Hello");
Console.WriteLine("Hello");
Console.WriteLine("Hello");
#endregion
}
}
}

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

Hello
Hello
Hello
Hello
Hello

#pragma 指令

  • #pragma 指令用于为编译器提供一些特殊指令,用于编译其中出现的文件。
  • 这些指令可能包括禁用或启用一些警告。
  • C# 支持两个 #pragma 指令:
    • #pragma warning:用于禁用或启用警告
    • #pragma checksum:生成源文件的校验和,用于调试。

语法:

#pragma 指令名称 指令参数

例如:

#pragma warning disable

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

using System;

namespace Directive
{
class Error
{
public static void Main(string[] args)
{
#pragma warning disable
#warning 这是一个警告 1
#pragma warning restore
#warning 这是一个警告 2
}
}
}

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

Program.cs(12,22): warning CS1030: #warning: '这是一个警告 2' [/home/myuser/csharp/directive-project/directive-project.csproj]

我们可以看到,屏幕上只显示了第二个警告

这是因为,我们最初在第一个警告前禁用了所有警告,并且只在第二个警告前恢复了它们。这就是为什么第一个警告被隐藏的原因。

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

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