1. 什么是编译器编译器是一种将高级编程语言代码如 C#、Java、Python翻译成计算机可执行代码如机器码或中间语言的程序。它的核心作用包括语法检查验证代码是否符合语言规范。优化提高代码的运行效率如减少冗余计算。生成目标代码输出可执行文件如.exe或.dll。在 C# 中编译器如csc.exe将源代码转换为中间语言IL再由 .NET 运行时CLR通过 JIT 编译器转换为机器码执行。2. 什么是预处理器指令预处理器指令是在编译前由编译器处理的特殊指令用于在编译阶段控制代码的包含、排除或条件编译。它们不参与程序运行仅在编译时生效。以 # 符号开头如 #if、#define。不改变代码逻辑而是控制哪些代码被编译。与 C/C 不同C# 的预处理器不支持宏定义如#define PI 3.14功能较为简化。3. C# 中常见的预处理器指令(1)#define和#undef作用定义或取消定义一个符号Symbol用于条件编译。#define在代码文件中定义一个符号Symbol仅用于条件编译判断不是变量。#undef取消之前定义的符号。示例123456789101112#define DEBUG // 定义 DEBUG 符号从这行开始生效#undef DEBUG // 取消 DEBUG 符号从这行开始失效usingSystem;classProgram {staticvoidMain() {#if DEBUGConsole.WriteLine(调试模式);// 这行代码不会编译#endif}}实际使用所以其实他的作用就是使得某些代码不被执行1234567891011121314#define WINDOWS // 定义 WINDOWS 符号//#define LINUX // 注释掉 LINUX 符号publicclassProgram {publicstaticvoidMain() {#if WINDOWSConsole.WriteLine(运行 Windows 专用逻辑);#elif LINUXConsole.WriteLine(运行 Linux 专用逻辑);#elseConsole.WriteLine(未知平台);#endif}}若想切换平台只需注释 #define WINDOWS取消注释 #define LINUX。注意必须在文件顶部使用#define 和 #undef 必须放在所有代码之前比如 using 语句之前。符号无具体值符号只是“存在”或“不存在”不能赋值如 #define VERSION 1 是错误语法。作用域为当前文件每个文件的符号定义是独立的除非通过项目全局定义。(2) 条件编译指令#if,#elif,#else,#endif作用根据符号是否被定义控制哪些代码会被编译器包含。完全不同于运行时的 if-else条件编译的代码在编译时就被决定是否保留。示例1234567891011121314#define DEBUG#define LOGGINGpublicclassProgram {publicstaticvoidMain() {#if DEBUG LOGGINGConsole.WriteLine(调试模式 日志开启);#elif DEBUGConsole.WriteLine(仅调试模式);#elseConsole.WriteLine(发布模式);#endif}}运算符支持与、||或、!非例如 #if !RELEASE注意哈:C# 的预处理器没有#elseif正确写法是#elif注意是#elif不是#elseif。这些玩意一定是配套出现的例如出现了#if就一定会有#endif注意条件编译 vs. 运行时if条件编译的代码在编译后不存在而if是运行时判断12345678#if DEBUGConsole.WriteLine(调试模式);// 编译后可能被移除#endifif(isDebug){Console.WriteLine(调试模式);// 始终存在于编译结果中}(3)#warning和#error作用#warning在编译时生成自定义警告用于提示开发者注意某些问题但不会阻止编译。#error在编译时生成自定义错误强制编译失败用于阻止不符合条件的代码编译。示例1234567publicclassPaymentService {publicvoidProcessPayment() {#warning TODO: 需要实现支付逻辑// 临时占位代码Console.WriteLine(支付功能待实现);}}123456789#if !NET6_0#error 此代码必须使用 .NET 6.0 或更高版本编译#endifpublicclassProgram {publicstaticvoidMain() {// ...}}如果项目目标框架不是 .NET 6.0编译会直接失败并显示错误信息。(4)#line(不太重要)作用修改编译器报告的行号和文件名常用于代码生成工具如 Razor 模板、T4 模板将错误定位到原始文件而非生成的中间文件。隐藏代码块结合 #line hidden 和 #line default 控制调试器的可见性。示例 1修改行号和文件名12345678#line 200 SpecialFile.cspublicclassFakeClass {// 故意写一个错误publicvoidMethod() {intx error;// 这里会报错}}#line default // 恢复原始行号和文件名SpecialFile.cs(200,13): error CS0029: 无法将类型“string”隐式转换为“int”调试时错误会显示在SpecialFile.cs的第 200 行实际文件可能不存在。示例 2隐藏生成的代码1234567// 生成的代码开始#line hiddenpublicclassGeneratedClass {publicvoidAutoGeneratedMethod() {/*...*/}}#line default// 生成的代码结束调试时GeneratedClass的代码在 IDE 中会被折叠或隐藏直接跳过。(5)#pragma作用禁用/恢复警告临时屏蔽不需要的编译器警告。优化代码指示编译器对代码块进行优化如 #pragma optimize。示例112345678910publicclassExample {publicvoidDemo() {#pragma warning disable CS0168 // 禁用 变量未使用 的警告intunusedVariable;#pragma warning restore CS0168 // 恢复警告intusedVariable 10;Console.WriteLine(usedVariable);}}示例2123456789#pragma warning disable CS0219, CS8602 // 禁用 变量已赋值但未使用 和 可能为 null 的引用 警告publicclassTest {publicvoidMethod() {intx 5;// 不会触发 CS0219strings null;Console.WriteLine(s.Length);// 不会触发 CS8602}}#pragma warning restore CS0219, CS8602示例312345#pragma optimize off // 关闭优化publicvoidCriticalMethod() {// 此方法内的代码不会被编译器优化}#pragma optimize on用于调试时保持代码结构不被优化器破坏。(6)#region和#endregion作用标记代码块对编译器无影响仅用于 IDE 代码折叠。这个你在IDE里面写的时候左边会出现一个号你就可以折叠起来了。示例12345#region 初始化逻辑voidInitialize() {// ...}#endregion4、总结指令作用示例#define SYMBOL定义符号用于条件编译#define DEBUG#undef SYMBOL取消定义的符号#undef DEBUG#if #elif #else #endif根据符号条件编译代码块#if DEBUGConsole.WriteLine(调试模式);#endif#warning MESSAGE在编译时生成警告提示开发者注意问题#warning TODO: 需要优化此方法#error MESSAGE在编译时生成错误强制编译失败#error 此代码需要 .NET 6.0#line N FILE修改编译器输出的行号和文件名#line 100 Generated.cs#pragma控制编译器行为如禁用警告、代码优化#pragma warning disable CS0168#region #endregion标记代码块仅用于 IDE 折叠显示无编译影响#region 初始化逻辑void Init() {}#endregion完整一个版本代码示例1234567891011121314151617181920212223242526272829303132333435363738394041424344#define DEBUG // 定义 DEBUG 符号//#define NET6_0 // 取消注释模拟 .NET 6.0 环境#undef RELEASE // 取消 RELEASE 符号如果存在usingSystem;#pragma warning disable CS0168 // 禁用未使用变量警告#region 主程序publicclassProgram{publicstaticvoidMain(){// 条件编译示例#if DEBUGConsole.WriteLine( 调试模式 );#warning 注意调试模式下日志会输出敏感信息#elif RELEASEConsole.WriteLine( 发布模式 );#else#error 未定义编译模式DEBUG 或 RELEASE#endif// 平台逻辑示例#if WINDOWSConsole.WriteLine(运行 Windows 专用代码);#elif LINUXConsole.WriteLine(运行 Linux 专用代码);#elseConsole.WriteLine(未知平台);#endif// #pragma 示例intunusedVar;// 不会触发 CS0168 警告Console.WriteLine(Hello World);// #line 示例模拟代码生成工具#line 200 MagicFile.cs// 故意写一个错误编译时会显示在 MagicFile.cs 第 200 行// string s 123; // 取消注释会报错#line default}}#pragma warning restore CS0168#endregion到此这篇关于C#中预处理器指令的实现示例的文章就介绍到这了