C# 预处理器指令完全指南:条件编译、符号定义与诊断控制
预处理器指令指示编译器在实际编译开始前预处理信息。所有指令以 # 开头,行首仅允许空白字符。预处理器指令不是语句,不以分号结尾。
C# 编译器无独立预处理器,但按有预处理器方式处理指令。C# 预处理器指令用于条件编译,不同于 C/C++ 不用于创建宏。每行只能有一条预处理器指令。
C# 预处理器指令列表
| 序号 | 指令及说明 |
|---|---|
| 1 | #define:定义符号(字符序列) |
| 2 | #undef:取消定义符号 |
| 3 | #if:测试符号是否为真 |
| 4 | #else:配合 #if 创建复合条件 |
| 5 | #elif:创建复合条件指令 |
| 6 | #endif:结束条件指令 |
| 7 | #line:修改编译器行号和文件名输出 |
| 8 | #error:从特定位置生成编译错误 |
| 9 | #warning:从特定位置生成一级警告 |
| 10 | #region:指定可展开/折叠代码块(VS 编辑器大纲功能) |
| 11 | #endregion:标记 #region 结束 |
#define 预处理器
创建符号常量。使用符号作为 #if 表达式时评估为 true。语法:#define symbol
示例
#define PI
using System;
namespace PreprocessorDAppl {
class Program {
static void Main(string[] args) {
#if (PI)
Console.WriteLine("PI is defined");
#else
Console.WriteLine("PI is not defined");
#endif
Console.ReadKey();
}
}
}
输出:PI is defined
条件指令
使用 #if 创建条件指令,测试符号是否为真。语法:#if symbol [operator symbol]...
操作符:== != && ||。可用括号分组。#if 必须以 #endif 显式结束。
复合条件示例
#define DEBUG
#define VC_V10
using System;
public class TestClass {
public static void Main() {
#if (DEBUG && !VC_V10)
Console.WriteLine("DEBUG is defined");
#elif (!DEBUG && VC_V10)
Console.WriteLine("VC_V10 is defined");
#elif (DEBUG && VC_V10)
Console.WriteLine("DEBUG and VC_V10 are defined");
#else
Console.WriteLine("DEBUG and VC_V10 are not defined");
#endif
Console.ReadKey();
}
}
输出:DEBUG and VC_V10 are defined
诊断指令
#error "message":编译时产生错误,阻止编译通过。用于强制配置检查。#warning "message":编译时产生警告,不阻止编译。用于提醒过时代码、待办事项。
示例
#if !DEBUG
#error "Release build requires optimization enabled"
#endif
#warning "This code path is deprecated, use NewMethod instead"
#line 指令
修改编译器报告的行号和文件名,常用于代码生成工具:
#line 100 "GeneratedCode.cs"
int x = 1; // 编译器报告此行在 GeneratedCode.cs 第 100 行
#line default // 恢复默认行号
#region / #endregion
Visual Studio 编辑器大纲功能支持折叠/展开代码块,提升大文件可读性:
#region 公共属性
public string Name { get; set; }
public int Age { get; set; }
#endregion
#region 私有字段
private string _name;
private int _age;
#endregion
项目级条件编译符号
除源码 #define,还可在项目属性 → Build → Conditional compilation symbols 定义(如 DEBUG;TRACE;MY_SYMBOL),或在 .csproj 中配置:
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<DefineConstants>DEBUG;TRACE</DefineConstants>
</PropertyGroup>
最佳实践
- 条件编译用于平台差异、调试代码、功能开关,避免滥用导致代码碎片化
- 优先用
ConditionalAttribute标记方法替代#if包裹调用点 - 公共库避免暴露内部条件编译符号
#region逻辑分组而非单纯折叠大块代码
C语言