UnityEngine.Object类的隐式bool转换,何时为null问题。

Posted 不明觉厉的( 乛◡乛)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UnityEngine.Object类的隐式bool转换,何时为null问题。相关的知识,希望对你有一定的参考价值。

最近在学unity时,群友们有人发布的Unity的题目,如下:

 

当时以为这题再考DestroyImmediate()方法和Destroy()方法,结果发现太小瞧它了。

不难看出,这题主要考察的是4个 if 语句的条件判断.

我也是才了解UnityEngine.Object可以隐式转换为bool,上源码:

 343行定义了Object隐式转换bool的方法,那么转换规则是怎样的呢?

我这里分三种情况进行测试:

    private void Start()
    
        UnityEngine.GameObject obj = new UnityEngine.GameObject();
        Destroy(obj);
        if (obj)
            Debug.Log("obj==true");
        else
            Debug.Log("obj==false");

        UnityEngine.GameObject obj0 = new UnityEngine.GameObject();
        DestroyImmediate(obj0);
        if (obj0)
            Debug.Log("obj0==true");
        else
            Debug.Log("obj0==false");

        UnityEngine.GameObject obj1 = null;
        if (obj1)
            Debug.Log("obj1==true");
        else
            Debug.Log("obj1==false");
    

结果如下:

这里也体现出DestroyImmediate()方法和Destroy()方法的不同

Destroy后Object实例短时间还存在,而DestroyImmediate后Object会立刻销毁(这里涉及到假 null 我稍后会提到)。

所以隐式转换bool的值即为Object实例是否存在。

第一个 if 答案则为true

 第340,341行定义了Object ==,!= 运算的重载,我这里依然分三种情况进行测试:

    private void Start()
    
        UnityEngine.GameObject obj = new UnityEngine.GameObject();
        Destroy(obj);
        Debug.Log(obj is null);
        Debug.Log(obj == null);
        Debug.Log("-------------------------------------------");
        UnityEngine.GameObject obj0 = new UnityEngine.GameObject();
        DestroyImmediate(obj0);
        Debug.Log(obj0 is null);
        Debug.Log(obj0 == null);
        Debug.Log("-------------------------------------------");
        UnityEngine.GameObject obj1 = null;
        Debug.Log(obj1 is null);
        Debug.Log(obj1 == null);
    

结果如下:

很神奇的现象,为什么三种情况每种和每种都不一样呢?

第一种情况好理解,毕竟Object对象暂时没有销毁。。。后两种情况就有的研究了。 

后来我通过查资料发现UnityEngine.Object有“假null”的状态:

UnityEngine.Object类通过 ==,!= 重载运算,使 (obj0 is null) 为 false 的状态下让 (obj0 == null) 为 true。

因此可推测DestroyImmediate后obj0还不是真正的 null ,而什么时候obj0真正为 null 我还存有疑问,望大佬们指教。

因此第二,三个 if 条件为false,true。

另外提一下,在C#中抛去重载运算符之外 a == null 与 a is null 是完全等价的。

最后一个: System.Object 就是 object 类,因此UnityEngine.Object也是继承自System.Object的。

既然System.Object没有 ==,!= 重载,那么 (System.Object)go == null 就可以等价为 go is null。

因此第四个 if 条件为false。

最终测试:

    private void Start()
    
        string s = string.Empty;
        var go = new UnityEngine.GameObject();
        UnityEngine.Object.DestroyImmediate(go);
        if (!go) s += "A";
        if (go is null) s += "B";
        if (go == null) s += "C";
        if ((System.Object)go == null) s += "D";
        UnityEngine.Debug.Log(s);
    

测试结果:

结果正确。 

第一次写文章,经验不足,哪里有不足的地方欢迎大家来指正。

以上是关于UnityEngine.Object类的隐式bool转换,何时为null问题。的主要内容,如果未能解决你的问题,请参考以下文章

带有可变参数的案例类的隐式 jsonFormat

C++ 类的隐式转换

Scala中的隐式转换|理解

Scala 中的隐式类

Scala的隐式转换

如何防止特定模板的隐式模板实例化?