C#学习12——预处理

发布于:2025-06-04 ⋅ 阅读:(26) ⋅ 点赞:(0)
一、预处理指令:

解释:是在编译前由预处理器执行的命令,用于控制编译过程。这些命令以 # 开头,每行只能有一个预处理指令,且不能包含在方法或类中。

个人理解:就是游戏里面的备战阶段(不同对局,不同选英雄。。。)

1.#define 定义字符和 #undef取消定义字符
#define TEST
#undef TEST  // 取消定义(删掉则输出"TEST 已定义")

#if TEST
    Console.WriteLine("TEST 已定义");
#else
    Console.WriteLine("TEST 未定义");  // 输出此行"TEST 未定义"
#endif

#define 宏常量与内置的 const 常量区别:
特性            #define 宏常量                                    const 常量
定义方式    定义条件符号,在编译前替换文本       语言关键字,声明为不可修改的变量
作用域       无作用域限制                                        遵循变量作用域(块、类作用域等)
类型安全    无类型检查,可能导致意外行为          有类型声明,编译器会进行类型检查
内存占用    无独立内存,直接替换为文本              可能占用内存(取决于编译器优化)
调试支持    调试时不可见(已替换为文本)          调试时可见(有独立符号)
灵活性       可定义复杂表达式或代码片段               仅能定义简单值

2.条件编译指令#if#else#elif#endif
#define DEBUG  // 定义一个符号(通常在项目属性中设置)

#if !DEBUG
    Console.WriteLine("不是DEBUG模式");//输出这一行
#elif DEBUG
    Console.WriteLine("DEBUG模式");
#else
    Console.WriteLine("其他模式");
#endif

配套使用规则

这些指令必须成对出现,形成一个完整的条件编译块:

  • #if:开始条件编译块,检查符号是否定义。
  • #elif(可选):提供额外的条件分支。
  • #else(可选):定义默认分支(当所有条件都不满足时)。
  • #endif:结束条件编译块。
3.#error错误和警告指令(可嵌套)
#if OLD_VERSION
        #error 此代码需要更新到新版本
#else
        Console.WriteLine("代码正常运行");
#endif
4.#warning    生成编译器警告信息
#warning 此方法已过时,需要重构
5.#region:标记一个可折叠代码块的开始。#endregion:标记一个可折叠代码块的结束。
#region Properties
    Console.WriteLine("这一段是代码块1");
    Console.WriteLine("这一段是代码块1");
    Console.WriteLine("这一段是代码块1");
#endregion

#region Methods
    Console.WriteLine("这一段是代码块2");
    Console.WriteLine("这一段是代码块2");
    Console.WriteLine("这一段是代码块2");
#endregion
6.#line显式指定编译器在生成错误或警告时报告的行号和文件名

#line 数字 "文件名"

#line default恢复编译器使用实际的行号和文件名。

#line hidden隐藏代码行(通常用于编译器内部实现,如生成的状态机代码)。

#line 10 "Template.tt"
    public void GeneratedMethod() {
        Console.WriteLine("Hello from generated code!");
    }
#line default
7.#pragma    用于给编译器发送特殊指令,例如禁用或恢复特定的警告。
#pragma warning disable CS0168  // 禁用“变量未使用”的警告
int unusedVariable;    // 不会触发CS0168警告
#pragma warning restore CS0168  // 恢复警告
int unusedVariable1;    // 会触发CS0168警告

拓展:

#pragma checksum  :校验

#pragma optimize:控制代码优化(如 #pragma optimize "g", 启用尾调用优化)。

#pragma pack:控制结构体的内存对齐(在C/C++中更常见,C#中较少使用)。

8.nullable    控制可空性上下文和注释,允许启用或禁用对可空引用类型的编译器检查。

string? nullableString = null; // 不会发出警告,默认启用可空注释
#nullable disable annotations
string? nullableString1 = null;//警告,因为可空注释已禁用
Console.WriteLine(nullableString.Length);//警告,出现空引用
#nullable disable
// 潜在的运行时错误
Console.WriteLine(nullableString1.Length);//不会发出警告,因为可空注释和警告都已禁用

#nullable enable
string anotherString = null; // 警告,空文本
Console.WriteLine(anotherString.Length); // 警告,因为可空注释和警告都启用

二、为什么要用预处理命令?

1.为什么要用这个?
1)不同环境编译不同代码(调试发布模式Debug,跨平台代码Windows,Linux,IOS)
2)快速定位:
        a.标记暂时跳过的功能。
        b.提醒团队成员完成关键代码
3)功能开关
#define NEW_UI
class Program {
    static void Main() {
        #if NEW_UI
            ShowNewUI();
        #else
            ShowOldUI();
        #endif
    }
}
以 # 开始,不是语句,不以分号 ; 结束
4)提高可读性(用 #region 和 #endregion 折叠代码块,提升可读性。)

5) 灵活调试(#warning 和 #error 在编译时生成提示或错误)


网站公告

今日签到

点亮在社区的每一天
去签到