您的位置:首页 > 游戏 > 手游 > 转行学python后悔了_中国域名拍卖网_seo咨询师_网络营销师资格证报名

转行学python后悔了_中国域名拍卖网_seo咨询师_网络营销师资格证报名

2025/4/27 6:53:50 来源:https://blog.csdn.net/m0_74212916/article/details/147497458  浏览:    关键词:转行学python后悔了_中国域名拍卖网_seo咨询师_网络营销师资格证报名
转行学python后悔了_中国域名拍卖网_seo咨询师_网络营销师资格证报名

目录

1. 什么是编译器?

2. 什么是预处理器指令?

3. C# 中常见的预处理器指令

(1) #define 和 #undef

(2) 条件编译指令(#if, #elif, #else, #endif)

注意哈:C# 的预处理器没有 #elseif,正确写法是 #elif(注意是 #elif 不是 #elseif!)。这些玩意一定是配套出现的,例如出现了#if,就一定会有#endif

(3) #warning 和 #error

(4) #line(不太重要)

示例 1:修改行号和文件名

示例 2:隐藏生成的代码

(5) #pragma

示例1:

 示例2:

示例3:

(6) #region 和 #endregion

4、总结


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:取消之前定义的符号。

  • 示例

#define DEBUG  // 定义 DEBUG 符号(从这行开始生效)
#undef DEBUG   // 取消 DEBUG 符号(从这行开始失效)using System;class Program {static void Main() {#if DEBUGConsole.WriteLine("调试模式");  // 这行代码不会编译#endif}
}

实际使用:所以其实他的作用就是使得某些代码不被执行

#define WINDOWS  // 定义 WINDOWS 符号
//#define LINUX  // 注释掉 LINUX 符号public class Program {public static void Main() {#if WINDOWSConsole.WriteLine("运行 Windows 专用逻辑");#elif LINUXConsole.WriteLine("运行 Linux 专用逻辑");#elseConsole.WriteLine("未知平台");#endif}
}

 若想切换平台,只需注释 #define WINDOWS,取消注释 #define LINUX

注意:

  1. 必须在文件顶部使用#define 和 #undef 必须放在所有代码之前(比如 using 语句之前)。

  2. 符号无具体值:符号只是“存在”或“不存在”,不能赋值(如 #define VERSION 1 是错误语法!)。

  3. 作用域为当前文件:每个文件的符号定义是独立的,除非通过项目全局定义。

 

(2) 条件编译指令(#if#elif#else#endif
  • 作用:根据符号是否被定义,控制哪些代码会被编译器包含
    完全不同于运行时的 if-else!条件编译的代码在编译时就被决定是否保留。

  • 示例

#define DEBUG
#define LOGGINGpublic class Program {public static void Main() {#if DEBUG && LOGGINGConsole.WriteLine("调试模式 + 日志开启");#elif DEBUGConsole.WriteLine("仅调试模式");#elseConsole.WriteLine("发布模式");#endif}
}
  • 运算符支持:&&(与)、||(或)、!(非),例如 #if !RELEASE

注意哈:C# 的预处理器没有 #elseif,正确写法是 #elif(注意是 #elif 不是 #elseif!)。这些玩意一定是配套出现的,例如出现了#if,就一定会有#endif

注意: 条件编译 vs. 运行时 if

条件编译的代码在编译后不存在,而 if 是运行时判断:

#if DEBUG
Console.WriteLine("调试模式");  // 编译后可能被移除
#endifif (isDebug) 
{Console.WriteLine("调试模式");  // 始终存在于编译结果中
}
(3) #warning 和 #error
  • 作用#warning:在编译时生成自定义警告,用于提示开发者注意某些问题(但不会阻止编译)。#error:在编译时生成自定义错误,强制编译失败(用于阻止不符合条件的代码编译)。

  • 示例

public class PaymentService {public void ProcessPayment() {#warning TODO: 需要实现支付逻辑// 临时占位代码Console.WriteLine("支付功能待实现");}
}
#if !NET6_0
#error 此代码必须使用 .NET 6.0 或更高版本编译
#endifpublic class Program {public static void Main() {// ...}
}

 如果项目目标框架不是 .NET 6.0,编译会直接失败,并显示错误信息。

(4) #line(不太重要)
  • 作用修改编译器报告的行号和文件名:常用于代码生成工具(如 Razor 模板、T4 模板),将错误定位到原始文件而非生成的中间文件。隐藏代码块:结合 #line hidden 和 #line default 控制调试器的可见性。

  • 示例 1:修改行号和文件名
#line 200 "SpecialFile.cs"
public class FakeClass {// 故意写一个错误public void Method() { int x = "error"; // 这里会报错}
}
#line default // 恢复原始行号和文件名

SpecialFile.cs(200,13): error CS0029: 无法将类型“string”隐式转换为“int” 

  • 调试时,错误会显示在 SpecialFile.cs 的第 200 行(实际文件可能不存在)。

  • 示例 2:隐藏生成的代码
// 生成的代码开始
#line hidden
public class GeneratedClass {public void AutoGeneratedMethod() { /*...*/ }
}
#line default
// 生成的代码结束
  • 调试时GeneratedClass 的代码在 IDE 中会被折叠或隐藏,直接跳过。

(5) #pragma
  • 作用禁用/恢复警告:临时屏蔽不需要的编译器警告。优化代码:指示编译器对代码块进行优化(如 #pragma optimize)。

  • 示例1
public class Example {public void Demo() {#pragma warning disable CS0168 // 禁用 "变量未使用" 的警告int unusedVariable;#pragma warning restore CS0168 // 恢复警告int usedVariable = 10;Console.WriteLine(usedVariable);}
}
  •  示例2:
#pragma warning disable CS0219, CS8602 // 禁用 "变量已赋值但未使用" 和 "可能为 null 的引用" 警告
public class Test {public void Method() {int x = 5; // 不会触发 CS0219string s = null; Console.WriteLine(s.Length); // 不会触发 CS8602}
}
#pragma warning restore CS0219, CS8602
  • 示例3:
#pragma optimize off // 关闭优化
public void CriticalMethod() {// 此方法内的代码不会被编译器优化
}
#pragma optimize on

 用于调试时保持代码结构不被优化器破坏。

(6) #region 和 #endregion
  • 作用:标记代码块(对编译器无影响,仅用于 IDE 代码折叠)。这个你在IDE里面写的时候,左边会出现一个+号你就可以折叠起来了。

  • 示例

#region 初始化逻辑
void Initialize() {// ...
}
#endregion

4、总结

指令作用示例
#define SYMBOL定义符号,用于条件编译#define DEBUG
#undef SYMBOL取消定义的符号#undef DEBUG
#if #elif #else #endif根据符号条件编译代码块#if DEBUG
Console.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

完整一个版本代码示例:

#define DEBUG        // 定义 DEBUG 符号
//#define NET6_0     // 取消注释模拟 .NET 6.0 环境
#undef RELEASE      // 取消 RELEASE 符号(如果存在)using System;#pragma warning disable CS0168 // 禁用未使用变量警告
#region 主程序
public class Program
{public static void Main(){// 条件编译示例#if DEBUGConsole.WriteLine("===== 调试模式 =====");#warning 注意:调试模式下日志会输出敏感信息!#elif RELEASEConsole.WriteLine("===== 发布模式 =====");#else#error 未定义编译模式(DEBUG 或 RELEASE)#endif// 平台逻辑示例#if WINDOWSConsole.WriteLine("运行 Windows 专用代码");#elif LINUXConsole.WriteLine("运行 Linux 专用代码");#elseConsole.WriteLine("未知平台");#endif// #pragma 示例int unusedVar; // 不会触发 CS0168 警告Console.WriteLine("Hello World");// #line 示例(模拟代码生成工具)#line 200 "MagicFile.cs"// 故意写一个错误(编译时会显示在 MagicFile.cs 第 200 行)// string s = 123; // 取消注释会报错#line default}
}
#pragma warning restore CS0168
#endregion

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com