我如何滥用null运算符?这是否正确评估为“ null”?

pri*_*ope 4 c# null-coalescing-operator unity-game-engine

我试图在Unity中的C#脚本中使用null-coalescing运算符,我的项目Scripting Runtime设置为.NET 4.x,因此它应该可以正常工作。

问题是,即使LEFT操作数的计算结果为null,也不会正确返回RIGHT操作数。

这是一个示例语句,当左侧Operand返回null时,该语句不起作用

m_meshFilter = ( GetMeshFilter() ?? AddMeshFilter() );
Run Code Online (Sandbox Code Playgroud)

这是SAME确切的语句,除了它显式地将null传递给null-coalescing运算符(运行时可正常运行

m_meshFilter = ( GetMeshFilter() == null ? null : GetMeshFilter() ) ?? AddMeshFilter();
Run Code Online (Sandbox Code Playgroud)

这是一个简短的脚本,可以直接在Unity中轻松测试问题。

using UnityEngine;

public class DoubleQuestionTest : MonoBehaviour
{
    public GameObject myGo;

    public MeshFilter m_meshFilter = null;

    [ContextMenu( "Test1 Null Coalescing Operator" )]
    void Test1()
    {
        m_meshFilter = ( GetMeshFilter() ?? AddMeshFilter() );

        if ( m_meshFilter == null )
        {
            Debug.Log( "m_meshFilter was null, trying Alternate" );
            m_meshFilter = ( GetMeshFilter() == null ? null : GetMeshFilter() ) ?? AddMeshFilter();
        }
    }

    MeshFilter GetMeshFilter()
    {
        MeshFilter temp = myGo.GetComponent<MeshFilter>();

        if ( temp == null )
            Debug.Log( "    > Get Mesh Filter RETURNING NULL" );

        return temp;
    }

    MeshFilter AddMeshFilter()
    {
        Debug.Log( "    > Add Mesh Filter Called" );
        return myGo.AddComponent<MeshFilter>();
    }
}

Run Code Online (Sandbox Code Playgroud)

您可以通过在Unity(2018.3.12f1)中的检查器中单击组件的右上角来运行测试功能

使用测试脚本时,第一次使用Null Coalescing运算符将失败,但是当我显式检查null,然后冗余地传递null(使用三元运算符)时,第二次成功

Unity编辑器控制台中的输出:

影像输出

这是错误吗?还是我做错了什么?

_______________________________

编辑:

在寻找解决方法时,为了找到null运算符,我找到了一种不错的方法使REAL返回null:

    public static T GetComponentRealNull<T>( this GameObject self ) where T : Component
    {
        T component = self.GetComponent<T>();

        if ( component == null )
            return null;

        return component;
    }
Run Code Online (Sandbox Code Playgroud)

或者,对于添加/获取组件的更具体的情况:

    public static T GetComponentOrAddIfMissing<T>(this GameObject self) where T : Component
    {
        T component = self.GetComponent<T>();
        if(component == null)
            component = self.AddComponent<T>();

        return component;
    }
Run Code Online (Sandbox Code Playgroud)

Dra*_*18s 6

这是Unity随身携带的。

如果您这样做:

MeshFilter GetMeshFilter()
{
    MeshFilter temp = myGo.GetComponent<MeshFilter>();

    if ( temp == null ) {
        Debug.Log( "    > Get Mesh Filter RETURNING NULL" );
        return null;
    }
    return temp;
}
Run Code Online (Sandbox Code Playgroud)

有用。

为什么?

因为Unity 在所有Unity对象上都覆盖了Equals(和==操作符),所以销毁的游戏对象和从不存在的对象都“等于”为null(这样做是为了简化开发人员的生活)。但被破坏的(或“缺失”)的对象不是字面上空:其在发动机指向的C#一部分的包装对象在底层C ++代码空对象。空合并运算符检查字面是否为空。

例如,尝试以下操作:

Start() {
    GameObject gg = new GameObject(); //create a GO
    DestroyImmediate(gg); //destroy it immediately
    Debug.Log(gg == null); //prints true: it is definitely null!
    GameObject go = gg ?? this.gameObject; //get a non-null object
    Debug.Log(go); //prints null
}
Run Code Online (Sandbox Code Playgroud)

这也是为什么你一个MissingReferenceException当您尝试是空的,而不是一个NullReferenceException访问统一性对象:这些对象不是从字面上空,但只有有效空。