当前位置:

首页 > 编程开发 > C#预处理器指令语言

C#预处理器指令语言

C#的预处理器指令由编译器直接处理,没有独立的预处理器。主要用于条件编译、可为空上下文控制、代码折叠等场景。支持定义符号、条件判断、可为空上下文、区域折叠、错误提示、编译指示等指令。条件编译仅判断符号是否定义,不包含宏替换功能。

本文目录

    C# 预处理器指令——听起来像是个冷门话题,但实际在条件编译、代码折叠、可为空上下文控制这些日常场景里,几乎每个 C# 开发者都会碰到。这次我们不讲教程,直接上语法规范和细节,方便你随时查。

    C#预处理器指令语言

    先说核心前提,也是很多新手容易踩的坑: C# 的预处理器指令没有独立的预处理器,由编译器直接处理。指令必须独占一行。别指望像 C/C++ 那样玩宏,条件编译只判断符号有没有定义——说白了就是个布尔逻辑。

    指令类别涵盖指令
    Nullable 上下文#nullable enable/disable/restore 及 annotations/warnings 子集
    条件编译#if、#elif、#else、#endif
    符号定义#define、#undef
    代码区域#region、#endregion
    诊断信息#error、#warning、#line
    编译器指令#pragma warning、#pragma checksum
    文件应用#!(shebang)、#:

    一、#nullable——可为空上下文

    这个指令用来控制可为 null 引用类型的注释和警告。它的优先级高于项目设置,一旦设定,效果会持续到遇到下一条指令,或者文件结束。实际迁移旧项目时,经常靠它局部开启或关闭 nullable 检查。

    1.1 基本形式

    指令效果
    #nullable disable禁用可为空上下文(注释 + 警告)
    #nullable enable启用可为空上下文
    #nullable restore恢复为项目级别的设置

    1.2 细粒度控制

    有时候你只想控制注释(也就是 ? 标记),或者只想控制警告,那就用下面这些子指令:

    指令效果
    #nullable disable annotations禁用 ? 标记(不检查 nullability 注释)
    #nullable enable annotations启用 ? 标记
    #nullable restore annotations恢复注释设置为项目级别
    #nullable disable warnings禁用可为 null 警告
    #nullable enable warnings启用可为 null 警告
    #nullable restore warnings恢复警告设置为项目级别

    典型场景: 当项目逐步迁移到 nullable aware 时,可以在特定文件或代码区域临时禁用或启用,避免一次改动整个项目。

     // 整个文件默认启用 nullable
     #nullable enable
     
     public string? GetOptional() => null;   // string? 有效,返回 null 不报警告
     
     #nullable disable warnings
     public string GetRequired() => null;     // 返回 null 不报警告(warnings 已禁用)
     
     #nullable restore warnings
     // 后面的代码恢复警告
    

    二、条件编译——#if / #elif / #else / #endif

    2.1 基本语法

     #if SYMBOL
         // 当 SYMBOL 已定义时编译
     #elif OTHER_SYMBOL
         // 当 OTHER_SYMBOL 已定义且前面条件不满足时编译
     #else
         // 前面所有条件都不满足时编译
     #endif
    

    这应该是用得最多的预处理器指令了——调试代码、多框架支持,全靠它。

    2.2 支持的运算符

    运算符含义示例
    !逻辑非#if !DEBUG
    ==相等#if NET8_0 == true
    !=不等#if NET8_0 != true
    &&逻辑与#if DEBUG && NET10_0
    ||逻辑或#if DEBUG || TRACE
    ()分组#if (DEBUG || TRACE) && !PRODUCTION

    2.3 预定义符号

    SDK 风格的项目会根据目标框架自动定义一组符号,这个设计非常省心,你只要选对目标框架,符号自动就配好了。

    桌面 / 框架相关:

    目标框架精确版本符号范围符号
    .NET Framework 4.7.2NET472NET472_OR_GREATER
    .NET Framework 4.8NET48NET48_OR_GREATER
    .NET Standard 2.1NETSTANDARD2_1NETSTANDARD2_1_OR_GREATER

    现代 .NET(.NET 5+):

    目标框架精确版本符号范围符号
    .NET 8NET8_0NET8_0_OR_GREATER
    .NET 9NET9_0NET9_0_OR_GREATER
    .NET 10NET10_0NET10_0_OR_GREATER

    平台符号:

    平台符号带版本号
    AndroidANDROIDANDROID35_0_OR_GREATER
    iOSIOSIOS15_1_OR_GREATER
    WindowsWINDOWSWINDOWS10_0_17763_0_OR_GREATER

    通用符号:

    符号来源
    DEBUGDebug 生成配置自动定义
    TRACETrace 常量,默认开启

    2.4 多框架适配示例

     public static string DownloadContent(string url)
     {
     #if NET40
         WebClient _client = new WebClient();
         return _client.DownloadString(url);
     #else
         HttpClient _client = new HttpClient();
         return _client.GetStringAsync(url).Result;
     #endif
     }
    

    三、符号定义——#define / #undef

    3.1 语法

     #define MYTEST         // 定义符号
     #undef MYTEST         // 取消定义
    

    3.2 关键规则

    规则说明
    位置必须在文件最开头,在所有非预处理器代码之前
    作用域从定义位置到文件末尾
    不能赋值#define MYTEST 1 是非法的,只能声明符号名
    常量应用需要常量值用 const,不要用 #define
    编译器选项也可通过 DefineConstants 属性全局定义
     // 正确 ✅
     #define FEATURE_EXPERIMENTAL
     
     // 错误 ❌
     #define FEATURE_EXPERIMENTAL true   // 编译错误
    

    这一点和 C/C++ 完全不同,千万别弄混。

    四、#region / #endregion——代码折叠

    4.1 语法

     #region 区域名称
     // ... 可折叠的代码 ...
     #endregion
    

    4.2 规则

    规则说明
    配对#region 必须由 #endregion 终止
    嵌套#region 内可以嵌套另一个 #region
    与 #if 的关系不能重叠,但可互相嵌套:#region 内含 #if 块,或 #if 内含 #region
    编译影响不影响编译,纯 IDE 大纲视图特性

    4.3 正确 vs 错误的嵌套

     // ✅ 正确 — #if 完整包含在 #region 内
     #region 多框架适配
     #if NET8_0_OR_GREATER
         Console.WriteLine(".NET 8+");
     #endif
     #endregion
     
     // ✅ 正确 — #region 完整包含在 #if 内
     #if DEBUG
     #region 调试工具
         Console.WriteLine("Debug tools active");
     #endregion
     #endif
     
     // ❌ 错误 — 重叠(编译失败)
     #region 开始
     #if DEBUG
     #endregion       // ❌ 在 #if 没有 #endif 之前关闭 #region
     #endif
    

    4.4 示例

     #region MyClass definition
     public class MyClass
     {
         static void Main()
         {
         }
     }
     #endregion
    

    常见坑: #region 不能拆分 #if/#endif 块。如果你在一个 #region 内打开了 #if,必须在同一个 #region 内用 #endif 关闭。跨区域交叉是不允许的。

    五、诊断指令——#error、#warning、#line

    5.1 #error——主动生成编译错误

     #error Deprecated code in this method.
     // 编译错误 CS1029: #error: 'Deprecated code in this method.'
    

    常用场景: 在不支持的条件下直接阻止编译,比如让旧框架的调用直接报错。

     #if !NET8_0_OR_GREATER
         #error This library requires .NET 8 or later.
     #endif
    

    5.2 #warning——主动生成编译警告

     #warning Deprecated code in this method.
     // 编译警告 CS1030: #warning: 'Deprecated code in this method.'
    

    5.3 #line——修改编译输出行号/文件名

    指令效果
    #line 200 "Special.cs"强制编译器以第 200 行、"Special.cs" 文件名报告后续代码
    #line default恢复默认行号
    #line hidden对调试器隐藏后续行(逐步执行时跳过)

    C# 高级语法(适用于 DSL / 代码生成器):

     #line (起始行, 起始列) - (结束行, 结束列) 列偏移 "原始源文件名"
    

    这个高级语法常见于 Razor 页面,编译器把生成的 .cs 文件中的错误映射回原始的 .cshtml 文件,方便开发者定位。

    六、#pragma 指令

    6.1 #pragma warning——警告控制

     #pragma warning disable 414, CS3021   // 从下一行起禁用指定警告
     // ... 受抑制的代码 ...
     #pragma warning restore CS3021        // 恢复指定警告
    

    格式控制:

     #pragma warning disable format   // 禁用代码格式化(如 Ctrl+K,D)
     // ... 你想保留手动格式的代码 ...
     #pragma warning restore format   // 恢复格式化
    

    6.2 #pragma checksum——调试校验和

    这主要服务于 ASP.NET 页面,用于确保调试器能找到正确的源文件:

     #pragma checksum "file.cs" "{3673e4ca-6098-4ec1-890f-8fceb2a794a2}" "hex-bytes..."
    

    参数:

    1. 文件名 ——源文件路径
    2. GUID ——文件的唯一标识
    3. 校验和字节 ——十六进制字符串

    这个指令日常开发很少手动去写,但了解它对理解 ASP.NET 的调试机制有帮助。

    七、#! 和 #:——基于文件的应用

    7.1 #!——Shebang

     #!/usr/bin/env dotnet
     Console.WriteLine("Hello");
    

    在 Unix 系统下,配合 chmod +x 可以直接把 .cs 文件当脚本执行。有点类似 Python 脚本的 shebang 行。

    7.2 #:——文件级配置

    C# 编译器会忽略 #: 开头的行,但 .NET SDK 等工具会按约定解析它们:

     #:package Spectre.Console@*
     #:sdk Microsoft.NET.Sdk.Web
     #:property PublishAot=false
    

    这算是一种轻量的文件级元数据声明,不是标准语法,但实际项目中偶尔能看到。

    八、指令不重叠关系速查

    结构 A结构 B可以嵌套?条件
    #region#region✅完整嵌套
    #if#if✅完整嵌套
    #region#if✅一个完整包含另一个
    #region#if❌不能重叠/交错

    最后

    这份参考覆盖了 C# 预处理器指令的全部语法规范。日常开发中最常用的就三类:#if DEBUG、#nullable enable、#region。其余的(比如 #line 高级映射、#pragma checksum)主要在代码生成器和 ASP.NET 底层框架中使用。记住最核心的一条:C# 预处理指令没有宏,条件编译只判断符号有没有定义,别把它当 C/C++ 的宏来用。

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发
    相关文章 更多
    llama.cpp 后端更新:Adreno 分解注意力、CUDA 空分块修复与 SYCL 缓存
    llama.cpp 后端更新:Adreno 分解注意力、CUDA 空分块修复与 SYCL 缓存

    llama.cpp b12314为Adreno OpenCL加入分解Flash Attention,b12316修复CUDA MoE空分块路径读取,b12319源码标签改用SYCL线程本地设备ID缓存。三个后端、两种发布阶段需分别核对,不能合并成统一性能提升或全平台安全结论。

    LangChain JS 适配包更新:MCP与OpenAI提高Zod下限,连接器同步依赖
    LangChain JS 适配包更新:MCP与OpenAI提高Zod下限,连接器同步依赖

    LangChain JS的MCP、IBM、OpenAI及Tavily适配包要求安装Zod 4.6.6及以上,OpenRouter、Together AI、xAI和Neo4j同步相关依赖。本文区分直接安全约束与传递依赖更新,给出锁文件和schema兼容性核对方法。

    LangChain Core 1.8.0:最低 Python 升至3.11,加入决策模型能力
    LangChain Core 1.8.0:最低 Python 升至3.11,加入决策模型能力

    langchain-core 1.8.0结束Python 3.10支持,最低要求变为Python 3.11,并加入decision models。Python 3.10仍会解析到1.7.x;升级前应同时核对解释器、锁文件、CI镜像与部署运行时,不把TypeSafe包的迁移要求混同于全部LangChain包。

    GitHub Copilot CLI 1.0.110-2:压缩遵守会话额度,修复插件设置覆盖
    GitHub Copilot CLI 1.0.110-2:压缩遵守会话额度,修复插件设置覆盖

    GitHub Copilot CLI 1.0.110-2预发布补丁让/compact遵守会话AI credit限制,改进失败回复标记,并修复无效配置时插件操作覆盖其他设置的问题。会话清理会跳过其他进程正在使用的会话,适合核对多终端与插件工作流。

    Ducter 0.0.42:消息定向回复上线,串联密钥卡片与 Mac 手机操作
    Ducter 0.0.42:消息定向回复上线,串联密钥卡片与 Mac 手机操作

    Ducter 0.0.42加入对单条消息及选中文字回复;本轮0.0.39—0.0.41还调整主动提醒、密钥请求卡片及Mac上的手机和应用操作。更新涉及本地权限与远端执行边界,应按版本逐项确认,而非默认所有设备都能使用全部功能。

    Qwen Code 1.0.0-preview.1:修复订阅模型登录,支持 Qoder 并行工具调用
    Qwen Code 1.0.0-preview.1:修复订阅模型登录,支持 Qoder 并行工具调用

    Qwen Code 1.0.0-preview.1修复订阅账号登录后无法使用订阅模型的问题,模型目录随登录状态更新,并同步0.27.x模型目录与思考预算映射。Qoder模型支持并行工具调用;这是预览版补丁,需要单独验证配置兼容。

    OpenCode PTY 0.5.2:发布 protocol 8 终端服务组件
    OpenCode PTY 0.5.2:发布 protocol 8 终端服务组件

    OpenCode发布opencode-pty 0.5.2终端服务组件,使用protocol 8并以@opencode/pty@0.5.2发布到npm。它面向集成终端子进程的开发者,采用MIT许可,仍被项目说明为实验性服务核心,不是OpenCode整款应用的版本号。

    vLLM 0.34.0rc2 源码标签:调整可扩展 KV Cache 测试内存参数
    vLLM 0.34.0rc2 源码标签:调整可扩展 KV Cache 测试内存参数

    vLLM出现0.34.0rc2候选源码标签,关联提交移除多处可扩展KV Cache测试和基准中的固定gpu_memory_utilization设置,并调整相关文档。当前核验的是标签与代码提交,不能将其当作正式版安装包或全局显存默认值变更。

    llama.cpp b12318:新增 CUDA 调试缓冲池与 Sanitizer 说明
    llama.cpp b12318:新增 CUDA 调试缓冲池与 Sanitizer 说明

    llama.cpp b12318新增CUDA调试缓冲池,并补充与compute-sanitizer相关的代码说明。它是面向CUDA开发调试路径的预发布构建,不能据此推断普通推理速度、显存占用或所有后端发生同等变化。

    llama.cpp b12307:修复 Metal SOLVE_TRI 内核越界读取
    llama.cpp b12307:修复 Metal SOLVE_TRI 内核越界读取

    llama.cpp b12307修复Metal后端SOLVE_TRI内核的越界读取,属于预发布构建中的特定计算路径补丁。使用Metal后端的开发者应核对是否涉及该算子,并验证模型加载与推理;公告未给出CVE、确认利用或统一性能结论。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。