条件编译指令#if、#else、#endif在C#中用于编译阶段控制代码包含,依据预定义符号如DEBUG、NET6_0或自定义符号决定;符号可通过项目属性、.csproj文件或命令行定义;支持逻辑组合与嵌套,常用于调试日志、多平台适配、功能开关和API兼容处理,提升代码灵活性与安全性。

#if、#else、#endif 是 C# 中用于条件编译的核心预处理指令,它们不改变运行时逻辑,而是在编译阶段决定哪些代码参与编译——这在多平台开发、调试控制、功能开关等场景中非常实用。
基本语法与工作原理
编译器根据预定义的符号(如 DEBUG、RELEASE 或自定义符号)是否被定义,来决定是否包含某段代码。未被选中的代码块不会被编译,也不会出现在最终程序集中,甚至不会进行语法检查(比如里面写了错别字也不会报错)。
常见写法:
- #if DEBUG —— 当项目配置为 Debug 模式时生效(VS 默认已定义)
- #if NET6_0 —— 针对 .NET 6.0 及以上版本启用特定代码(SDK 风格项目自动定义)
- #if MY_FEATURE —— 自定义符号,需在项目文件或编译选项中手动添加
在项目中定义自定义符号
想用 #if MY_LOGGING?得先让编译器“认识”它:
- Visual Studio:右键项目 → 属性 → 生成 → 常规 → “条件编译符号”框里输入 MY_LOGGING(多个用分号隔开)
- .csproj 文件中添加:
DEBUG;TRACE;MY_LOGGING - 命令行编译(dotnet build):加参数 /p:DefineConstants="MY_LOGGING"
嵌套与组合判断
支持 #elif 和逻辑运算符,让条件更灵活:
- #if DEBUG && !DISABLE_LOGGING —— 同时满足两个条件
- #if WINDOWS || LINUX —— 满足任一即可(注意:这些符号通常由 SDK 自动定义)
- 可嵌套:#if DEBUG → #if UNIT_TEST → 内层代码只在 Debug + 单元测试环境下编译
典型实用场景
不是炫技,而是解决真实问题:
- 调试专用日志:仅 Debug 下调用 Debug.WriteLine(),发布版完全剔除,零性能开销
- 平台差异化实现:Windows 调用 Registry,Linux 读取配置文件,用 #if WINDOWS / #elif LINUX 隔离
- 灰度功能开关:定义 FEATURE_PAY_V2,上线前编译两版程序,快速回滚
- 规避不兼容 API:旧版 .NET 不支持 HttpClient.DefaultProxy,用 #if NET6_0_OR_GREATER 包裹
基本上就这些。用好条件编译,能让同一份代码适配更多环境,也避免把调试逻辑误带到生产中。










