【从零开始入门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 Studio
、vscode
等等编辑器 中,调试模式(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
一位在小公司默默奋斗的开发者,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!如果你遇到任何问题,也欢迎你评论私信或者加群找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~