[Unity] 为什么空合并运算符 (??, ??=) 在 Unity 中是邪恶的?

61 篇文章 4 订阅
本文讨论了在Unity中使用C#的空合并运算符时遇到的问题,特别是它们如何在游戏对象被销毁时产生意外行为。作者指出,Unity重载了相等运算符导致了问题,建议开发者避免使用空合并运算符,保持简单的null检查。
摘要由CSDN通过智能技术生成

英文原文:https://nosuchstudio.medium.com/why-are-null-coalescing-operators-evil-in-unity-16f5a88d6071

在这里插入图片描述

我最近在 C# 中遇到了空合并运算符。 如果您不熟悉它们,以下是它们的工作原理。

?? 如果不为空,则返回左侧,否则返回右侧。 举个例子:

public void ProcessFunc(List<int> myList) {
  var processList = myList ?? new List<int>();
}

如果 myList 为 null,此行会将 processList 设置为新列表。

??= 只是 ?? 的赋值变体 。

List<int> myList;

void Awake() {
  myList ??= new List<int>();
}

仅当 myList 为空时,此行才会将其设置为新列表。

空合并运算符非常适合初始化类。 如果您想了解更多信息,请阅读 Microsoft 的文档

在 Unity 中,执行 null 检查并基于它们进行分配是一种常见模式。 一个被空合并运算符取代的完美模式!

SpriteRenderer sr;
if (sr == null) sr = GetComponent<SpriteRenderer>();
// 我们应该用下面的一行替换上面的一行吗?
sr ??= GetComponent<SpriteRenderer>();

我开始使用空合并运算符而不是空检查,很快我的代码中出现了一些非常讨厌的错误。 有时?? 即使空检查将返回 true,运算符也会返回左侧! 上面两行会产生不同的结果!

那么这是怎么回事呢?

事实证明,Unity 重载了“Unity.Object”类型(任何派生自 UnityEngine.Object 的类型)的 == 运算符。 这就是当游戏对象被销毁时变量变成 null 的原因。 在 C# 中将变量分配为 null 几乎是不可能的。 因此,Unity 工程师决定重载空检查。

空合并运算符始终检查引用是否相等,从而检查结果的差异。 对于被销毁的 GameObject,即使其实际值不为 null,引用也等于 null。

一个简单的解决方案是超载 ?? 和 ??= Unity 对象的运算符。 不幸的是,C# 不允许重载这些运算符。 所以没有简单的方法来解决这个问题。

我们是怎么来到这里的? 是谁的错?

Unity 工程师很早就知道这一点。 2014 年的一篇 Unity 博客文章展示了他们如何考虑摆脱相等性检查覆盖。 但显然他们决定不中断所有 Unity 项目,以实现更光明的未来。

至少可以说,重载相等运算符有点不确定,但如果不是后来引入的新空合并运算符,这仍然是一个不错的决定。

对于这种情况,Microsoft 的 C# 工程师至少应该承担部分责任(读作责备),因为他们让开发人员重载了相等运算符而不是空合并运算符。

我不知道为什么 C# 不允许这样做。 我怀疑它使 C# 保持干净和可预测。

好吧,但是我该怎么办呢?

尽管新的空合并运算符很闪亮,但它们只是一些语法糖,例如 ? : 三元运算符。 只要避免使用它们,坚持简单的 == 检查就可以了。 很抱歉向您宣传这些运算符并告诉您不要立即使用它们。 生活并不完美。

尾注

我是一名软件工程师转为游戏开发人员。 我定期发布有关我在 Unity 中面临的挑战的文章,并在这里分享我的经验。 关注我的社交媒体,了解使用 Unity、C# 进行游戏开发并聆听我的故事。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值