唯一的区别(除了语法之外)是,编译器保证当使用 is not null 而不是 != null(或者 is null 而不是 == null)时不会调用用户重载的运算符。
根据这些解释,两者应该没有区别
但是当我使用Unity引擎和Json数据时 我看到一个功能差异,Is Not null 不会将 Jason 识别为空,但当我使用 !=
检查时,它会将相同的数据识别为空这是什么原因?
可能有问题,抱歉(使用翻译器)
我希望在这两种情况下都能检测到空值
我希望在这两种情况下都能检测到空值
是的,两个运算符都检测到真正的空值。然而Unity有一点特殊。 Unity 是一个 C++ 引擎,在内存管理方面存在一些重大问题。在 C# 中,您不能手动销毁任何对象,因为这完全由垃圾收集器控制。在 C# 中,对对象的引用不会突然变为 null。
由于 Unity 中的本机 (C++) 对象可以随时销毁,因此这会导致 C# 脚本层出现问题。 GameObject 或其他组件引用不会神奇地变为 null。所以Unity使用了一个技巧。它们重载了 == 运算符和 Equals 方法,当将死对象与 null 进行比较时,它们将返回 true。这称为假空对象。它仍然是一个有效的 C# 对象,但无法再使用,因为实际的本机对象已被破坏。 Unity 中的大多数内置组件和类只是 C# 包装类,它们在幕后有一个本机对象。 (每个类都派生自UnityEngine.Object)
这意味着您不能对派生自 UnityEngine.Object 类型的变量使用
is null
或任何空合并运算符。当这些引用确实为空时,它就会起作用。然而,在大多数情况下,您会遇到一个假空对象,并且 is null
检查不会将其视为空,因为它仍然是一个实例。
大约 10 年前有一篇关于 == 运算符重载的博客文章。这里是 Unity 的参考源和自定义 == 运算符。正如你所看到的,它实际上调用了
CompareBaseObjects
并且当对象死亡时,它会“假装”它为空。
许多人说这是一个错误的决定,但是这个决定是在唯一进行直接空检查的运算符是
??
时做出的。近年来,C# 有了许多运算符,这些运算符也绕过了运算符重载,因此它成为一个日益严重的问题。然而,摆脱过载意味着您总是必须手动进行额外的IsAlive
检查,因为您无法摆脱 C++ 和 C# 世界之间的根本冲突。