为什么 C# 空条件运算符不适用于 Unity 可序列化变量? [英] Why does C# null-conditional operator not work with Unity serializable variables?
问题描述
我注意到,如果我有一些变量暴露给 Unity 检查器,例如:
I've noticed that if I have some variables exposed to the Unity inspector such as:
[SerializeField] GameObject _tickIcon;
如果我让它们未分配并尝试使用空条件运算符并调用该对象上的方法,我会收到一个异常,说明未分配变量.所以基本上不是这样做:
If I leave them unassigned and try to use the null conditional operator and call a method on that object I get an exception saying the variable is not assigned. So basically instead of doing this:
_tickIcon?.SetActive(false);
这迫使我这样做:
if(_tickIcon != null)
{
_tickIcon.SetActive(false)
}
所以我猜这一定是特定于 unity 的运行时的东西,它不是真正的 null,但我可以检查 null 并且它可以工作.我真的不明白这个.
So I'm guessing this must be something specific to unity's runtime, it's not really null, but I can check for null and it work. I don't really understand this.
推荐答案
它通常不适用于从 UnityEngine.Object
!
由于他们在内部实现了 ==
/!=
方法的不同,它被绕过了.参见 自定义 == 操作符,我们是否应该保留它?
It is bypassed due to how they internally implemented the ==
/!=
method differently. See Custom == operator, should we keep it?
ReSharper 在 可能意外绕过底层 Unity 引擎对象的生命周期检查
ReSharper explained it pretty well in Possible unintended bypass of lifetime check of underlying Unity engine object
如果从 UnityEngine.Object
派生的类型使用空值合并 (??
) 或空值传播或条件 (?.
) 运算符.这些运算符不使用在 UnityEngine.Object
上声明的自定义相等运算符,因此绕过检查以查看底层原生 Unity 引擎对象是否已被破坏.为了阐明意图,最好使用显式的 null
或布尔比较,或者调用 System.Object.ReferenceEquals()
.
This warning is shown if a type deriving from
UnityEngine.Object
uses either the null coalescing (??
) or null propagation or conditional (?.
) operators. These operators do not use the custom equality operators declared onUnityEngine.Object
, and so bypass a check to see if the underlying native Unity engine object has been destroyed. An explicitnull
or boolean comparison, or a call toSystem.Object.ReferenceEquals()
is preferred in order to clarify intent.
UnityEngine.Object
在某些情况下 不是真的 null
但仍然保留一些元数据.所以底层的object
( = System.Object
) 是not null
,UnityEngine.Object
被覆盖的 ==
操作符只为 == null
返回 true
.
UnityEngine.Object
is in some occasions not really null
but still keeps some meta data. So the underlying object
( = System.Object
) is not null
, UnityEngine.Object
's overwritten ==
operator just returns true
for == null
.
因此诸如 _tickIcon?.gameObjct
之类的东西抛出 NullReferenceException
的主要原因是 ?.
运算符仅直接作用于底层object
而 UnityEngine.Object
在不同级别上与他们的自定义实现一起工作.
The main reason why therefore things like _tickIcon?.gameObjct
throw a NullReferenceException
is that the ?.
operator only directly works on the underlying object
while the UnityEngine.Object
works with their custom implementation on a different level.
例如之后
Destroy(_tickIcon);
_tickIcon.SetActive(false);
你会注意到你没有得到一个正常的 NullReferenceException
,如果它实际上是 null
就会出现这种情况,而是得到一个 Unity 海关 MissingReferenceException
告诉您引发异常的可能原因.
you will note that you don't get a normal NullReferenceException
which would be the case if it were actually null
but rather get a Unity customs MissingReferenceException
telling you a probable reason for why the exception was thrown.
长话短说:作为解决方案 UnityEngine.Object
具有隐含的 bool
运算符
Long story short: As solution UnityEngine.Object
has the implicit bool
operator
对象是否存在?
给出的例子实际上并不是真的 - 见上文
您应该始终检查是否存在从 UnityEngine.Object
派生的任何内容,如下所示:
You should always check the existence of anything derived from UnityEngine.Object
like this:
if(_tickIcon)
{
_tickIcon.SetActive(false);
}
这篇关于为什么 C# 空条件运算符不适用于 Unity 可序列化变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!