当前位置: 首页 > article >正文

【从零开始入门unity游戏开发之——C#篇38】C#预处理器指令

文章目录

  • 前言
  • 一、什么是编译器
  • 二、什么是预处理器指令
  • 三、C# 中常用的预处理器指令
    • 1、**`#define` 和 `#undef`**
    • 2、**`#if`、`#elif`、`#else` 和 `#endif`**
      • `DEBUG` 宏的注意事项
    • 3、**`#warning` 和 `#error`**
    • 4、`#pragma warning` 指令
    • 5、`#nullable`
  • 四、预处理器指令加多条件判断
  • 五、预处理器指令的应用场景
  • 六、Unity 中的预处理器指令(预告)
    • 1、跨平台编译
      • 示例代码:
      • 解释:
    • 2、调试和日志记录
      • 示例代码:
      • 解释:
  • 专栏推荐
  • 完结

前言

在C#编程中,预处理器指令是指在编译前对源代码进行处理的一组指令。这些指令不属于C#的语法本身,它们是编译器在编译源代码之前解析的特殊命令。预处理器指令的主要作用是控制代码的编译过程,如条件编译、符号定义、文件包含等。

一、什么是编译器

编译器是一种程序,它的作用是将源代码翻译成目标代码。目标代码通常是机器语言或中间代码,具体表现为二进制格式的程序。

举个例子,如果你写了一个C#程序,编译器会将这个C#代码转化为.NET平台可以执行的中间语言(IL)代码。

二、什么是预处理器指令

预处理器指令用于指导编译器在实际编译开始之前,处理源代码中的特定信息。

预处理器指令以#符号开头,并且不需要分号(;)结尾。它们在代码编译前就已被编译器处理。

其实我们前面介绍的#region#endregion代码折叠就是预处理器指令。忘记的可以回头去看看:【从零开始入门unity游戏开发之——C#篇02】安装vscode、创建C#项目、注释、region代码折叠、打印

三、C# 中常用的预处理器指令

1、#define#undef

  • #define 用于定义符号(宏),这些符号可以在后续的代码中使用 #if#elif 等指令来控制编译。
  • #undef 用于取消之前定义的符号。

注意:它们只能在C#代码的最顶部定义,否则会报错
在这里插入图片描述
单单这么看你可能还不明白他有什么用,那是因为通常他都会和下面其他预处理器指令配合使用

2、#if#elif#else#endif

  • #if 用于检查一个符号是否已经定义,只有在符号已定义的情况下,紧随其后的代码才会被编译。
  • #elif 用于提供额外的条件检查。
  • #else 提供了 #if#elif 条件不成立时的代码。
  • #endif 结束条件编译的区域。

假设你写的程序需要同时在 Windows 和 Linux 系统上运行,而不同系统上的代码可能需要不同的处理方式。你可以使用预处理器指令来区分这些不同的操作系统。

#define WINDOWS  // 在Windows上编译时,定义WINDOWS符号
using System;

class Program
{
    static void Main()
    {
        #if WINDOWS
            Console.WriteLine("你正在Windows系统上运行程序");
        #elif LINUX
            Console.WriteLine("你正在Linux系统上运行程序");
        #else
            Console.WriteLine("你正在其他操作系统上运行程序");
        #endif

        // 这部分代码无论是什么系统都执行
        Console.WriteLine("程序开始运行...");
    }
}

结果
在这里插入图片描述
不同的系统你只需要修改前面定义的#define宏即可,Linux系统就修改#define LINUX,不是Windows又不是Linux注释或者删除前面的#define宏即可

DEBUG 宏的注意事项

Visual Studiovscode等等编辑器 中,调试模式(Debug 配置)默认会定义 DEBUG 宏,而发布模式(Release 配置)则不会定义该宏。所以即使你没有手动写 #define DEBUG,在调试模式下编译时,编译器仍会自动定义 DEBUG 宏。

比如下面代码
在这里插入图片描述
结果,DEBUG里的代码还是执行了
在这里插入图片描述
所以最好的办法,不是像我前面说的注释或者删除前面的#define宏,而是使用#undef 取消定义的符号。

比如改成如下
在这里插入图片描述
结果就正常了
在这里插入图片描述
如果你想定义 DEBUG 宏,这个问题得注意一下。

3、#warning#error

  • #warning 用来向开发者发出警告信息,但不停止编译过程。
  • #error 用来生成一个编译错误并停止编译过程。

语法

#warning 警告消息内容

#error 错误消息内容

示例
在这里插入图片描述
如果编译器遇到#error指令,它将停止编译并输出错误信息。

4、#pragma warning 指令

#pragma warning 指令是 C# 提供的一个编译指令,专门用于控制编译器的警告行为。它可以启用、禁用、或恢复特定的警告。

#pragma warning enable // 启用所有警告
#pragma warning disable // 禁用所有警告
#pragma warning restore // 恢复所有警告

#pragma warning disable CS0168 // 禁用未使用的变量警告
#pragma warning restore CS0168 // 恢复警告

比如我下面代码有很多警告
在这里插入图片描述
我在中间插入预编译指令禁用再回复警告效果
在这里插入图片描述

5、#nullable

#nullable:用于启用或禁用可空类型的上下文。可以在整个文件中启用或禁用对可空引用类型的支持。

#nullable enable  // 启用可空引用类型
#nullable disable  // 禁用可空引用类型

比如,前面的警告刚好都是空引用,我这里可以插入#nullable实现和前面一样的效果
在这里插入图片描述

四、预处理器指令加多条件判断

预处理器指令还可以和逻辑运算符&&(逻辑与)||(逻辑或)!(逻辑非)配置使用。

如果你忘记了什么是逻辑运算符,可以回头去看看:【从零开始入门unity游戏开发之——C#篇08】逻辑运算符、位运算符

示例

#define Unity2017
#define IOS
using System;

class Program
{
    static void Main()
    {
        #if Unity4 || Unity3 || Unity2 || Unity1 || Unity
            Console.WriteLine("低Unity版本");
        #elif Unity2017 && IOS
            Console.WriteLine("版本为Unity2017并且是iOS平台");           
        #else
            Console.WriteLine("其它版本");
        #endif

        #if !Unity6
            Console.WriteLine("不是最新的Unity6版本");
        #endif
    }
}

结果
在这里插入图片描述

五、预处理器指令的应用场景

  • 调试模式 vs 发布模式:假设你正在开发一个程序,在开发时你想输出一些调试信息,比如:打印变量的值、输出调试日志。但在最终发布给用户的时候,这些调试信息就不需要了,因为它们会影响性能,甚至会让程序显得“杂乱”。那么,你如何在开发时启用调试信息,在发布时关闭这些信息呢?这就可以通过预处理器指令来实现!

  • 跨平台开发:假设你写的程序需要同时在 Windows 和 Linux 系统上运行,而不同系统上的代码可能需要不同的处理方式。你可以使用预处理器指令来区分这些不同的操作系统。

六、Unity 中的预处理器指令(预告)

注意,为了防止你还是不理解预处理器指令的实际作用,我这里直接举例unity中预处理器指令的作用,这算是unity知识的内容预告,看不懂也没关系,后面我肯定会在《Unity 篇》中详细介绍的。

如果你接触unity了,就会发现unity已经帮我们定义了很多常用的预处理器指令。实际开发过程中,虽然你不一定需要自己定义预处理器指令,但了解这些预处理器指令的作用和背后的实现逻辑是非常重要的。

1、跨平台编译

在 Unity 中,你常常需要为不同的操作系统和平台(如 Windows、Mac、iOS、Android)编写不同的代码。预处理器指令使得你可以在编译时选择性地包含某些代码。

示例代码:

#if UNITY_EDITOR
    // 只在 Unity 编辑器中执行的代码
    Debug.Log("Running in Unity Editor");
#elif UNITY_ANDROID
    // 只在 Android 平台上执行的代码
    Debug.Log("Running on Android");
#elif UNITY_IOS
    // 只在 iOS 平台上执行的代码
    Debug.Log("Running on iOS");
#else
    // 其他平台
    Debug.Log("Running on an unknown platform");
#endif

解释:

  • #if UNITY_EDITOR:这部分代码只会在 Unity 编辑器中执行,通常用来编写编辑器相关的功能,比如在编辑器中显示调试信息、创建编辑器插件等。
  • #elif UNITY_ANDROID#elif UNITY_IOS:这些指令用于判断当前平台是 Android 还是 iOS,只有在特定平台编译时,这些代码才会被包含在内。
  • #else:这是一个默认情况,适用于你没有指定的其他平台。

2、调试和日志记录

开发中,经常需要在不同的环境下进行调试。通过预处理器指令,你可以轻松地在开发环境中输出大量的日志,而在发布版本中去掉这些调试信息,避免影响性能。

示例代码:

#if DEBUG
    Debug.Log("This is a debug build, logging detailed information.");
#endif

public class GameManager : MonoBehaviour
{
    void Start()
    {
        #if UNITY_EDITOR
            Debug.Log("Game started in the Unity Editor.");
        #endif
    }
}

解释:

  • #if DEBUG:这个指令用于检查是否定义了 DEBUG 符号。如果在编译时定义了 DEBUG,则会编译并执行 Debug.Log 语句,这对于开发时进行调试非常有用。
  • #if UNITY_EDITOR:这个指令用于检查当前代码是否运行在 Unity 编辑器中。你可以在编辑器中输出日志,或者执行某些编辑器特有的操作,而这些代码不会影响到发布的游戏版本。

专栏推荐

地址
【从零开始入门unity游戏开发之——C#篇】
【从零开始入门unity游戏开发之——unity篇】
【制作100个Unity游戏】
【推荐100个unity插件】
【实现100个unity特效】
【unity框架开发】

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!如果你遇到任何问题,也欢迎你评论私信或者加群找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述


http://www.kler.cn/a/463878.html

相关文章:

  • DuckDB:密钥管理器及其应用
  • node.js之---CommonJS 模块
  • Oracle ASM命令行工具asmcmd命令及其使用方法
  • scrapy 教程
  • 【51单片机零基础-chapter6:LCD1602调试工具】
  • 【图像处理】OpenCv + Python 实现 Photoshop 中的色彩平衡功能
  • locate() 在MySQL中的用法
  • 关于部署异常的处理问题
  • 网络渗透测试实验四:CTF实践
  • Spring Boot 嵌套事务详解及失效解决方案
  • leetcode hot 100 杨辉三角
  • python-leetcode-轮转数组
  • JVM实战—G1垃圾回收器的原理和调优
  • java下载文件流,不生成中间文件。
  • deepFM模型pytorch实现
  • Docker常用场景
  • ubuntu24.04配置IPV6
  • react中实现拖拽排序
  • CAD 精简多段线顶点——cad c# 二次开发
  • Pytorch_P1 Pytorch实现mnist手写数字识别
  • 自然语言处理:第八十三章 Prompt格式到底多重要?
  • IP5385为智能手机提供快充方案的30W到100W大功率电源管理芯片
  • 阿里云CDN与腾讯云CDN的全面对比
  • MySQL索引优化:提升查询性能的秘诀
  • 8086汇编(16位汇编)学习笔记08.函数
  • llama.cpp与PyTorch、TensorFlow