【问题标题】:Why does C# null-conditional operator not work with Unity serializable variables?为什么 C# 空条件运算符不适用于 Unity 可序列化变量?
【发布时间】:2023-03-25 15:19:01
【问题描述】:

我注意到,如果我有一些变量暴露给 Unity 检查器,例如:

[SerializeField] GameObject _tickIcon;

如果我不分配它们并尝试使用 null 条件运算符并在该对象上调用一个方法,我会收到一个异常,指出该变量未分配。所以基本上不是这样做:

_tickIcon?.SetActive(false);

这迫使我这样做:

if(_tickIcon != null)
{
   _tickIcon.SetActive(false)
}

所以我猜这一定是 Unity 运行时特有的东西,它并不是真的为 null,但我可以检查 null 并且它可以工作。这个我不太明白。

【问题讨论】:

    标签: c# unity3d serialization


    【解决方案1】:

    它通常不适用于从 UnityEngine.Object 继承的任何东西!

    由于他们在内部实现==/!= 方法的方式不同,因此绕过了它。见Custom == operator, should we keep it?

    ReSharper 在 Possible unintended bypass of lifetime check of underlying Unity engine object 中解释得很好

    如果派生自 UnityEngine.Object 的类型使用空合并 (??) 或空传播或条件 (?.) 运算符,则会显示此警告。这些运算符不使用在 UnityEngine.Object 上声明的自定义相等运算符,因此绕过检查底层原生 Unity 引擎对象是否已被破坏。为了明确意图,首选明确的 null 或布尔比较,或调用 System.Object.ReferenceEquals()

    UnityEngine.Object 在某些情况下不是 null 但仍保留一些元数据。所以底层的object( = System.Object) 不是nullUnityEngine.Object 的覆盖== 运算符只是为== null 返回true

    因此_tickIcon?.gameObjct 之类的东西抛出NullReferenceException 的主要原因是?. 运算符仅直接作用于底层object,而UnityEngine.Object 在不同级别上与它们的自定义实现一起工作。

    例如之后

    Destroy(_tickIcon);
    _tickIcon.SetActive(false);
    

    你会注意到你没有得到一个正常的NullReferenceException,如果它实际上是null,而是得到一个统一的习惯MissingReferenceException,告诉你抛出异常的可能原因。


    长话短说:作为解决方案UnityEngine.Object 具有隐含的bool operator

    对象是否存在?

    那里给出的例子实际上并不是真的 - 见上文

    您应该始终检查是否存在源自UnityEngine.Object 的任何内容,如下所示:

    if(_tickIcon)
    {
        _tickIcon.SetActive(false);
    }
    

    【讨论】:

    • 这正是我正在寻找的信息。我怀疑他们有某种特定于运营商的实现,但我不确定。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-16
    • 1970-01-01
    • 2022-07-06
    • 1970-01-01
    • 2010-09-18
    • 1970-01-01
    相关资源
    最近更新 更多