为什么我能够在null引用中使用变量?

时间:2017-04-06 21:48:07

标签: c# inheritance singleton unity5 inner-classes

我不确定如何描述它,所以让我告诉你发生了什么。

我有一个PlayerControls脚本看起来像这样(注意:除了必需品之外我剥掉了所有东西)。

namespace Player.Controls {
    internal class PlayerControls: MonoBehaviour {
        public bool IsClimbing { get; private set; } = false;
        public bool IsGrounded { get; private set; } = false;
    }
}

这些变量在此课程中设置,具体取决于玩家是否正在攀爬/接触地面。此脚本位于场景中的“播放器”GameObject上。


我有另一个名为PlayerController的脚本,看起来像这样

using Player.Controls;
public class PlayerController: Singleton<PlayerController> {
    internal PlayerStats stats = new PlayerStats();
    //PlayerStats nested class (see below)
}

Singleton类仅检查泛型类型是否为null,如果是,则它将使用FindObjectOfType来获取实例。此脚本也位于“播放器”GameObject


PlayerController类中,我有一个名为PlayerStats的嵌套类。看起来像这样

internal class PlayerStats : PlayerControls {
    public new bool IsClimbing { get { return base.IsClimbing; } }
    public new bool IsGrounded { get { return base.IsGrounded; } }
}

请注意继承自PlayerControls的此嵌套类。


这个想法是除PlayerControls之外的所有其他类都无法访问的PlayerController类,以及我想获得的关于玩家的任何信息都可以通过获取玩家的实例(通过单例)和访问来获得PlayerStats变量。

例如,假设保存实例的Singleton内的变量称为Instance,可以PlayerController.Instance.stats.IsClimbing;除了一件事之外,所有内容都按预期工作。

Awake课程的PlayerController方法中,我这样做

private void Awake() {
    Debug.LogFormat("In PlayerController Awake(). Is PlayerController.stats null? {0}",
    (stats.Equals(null) ? "Yes" : "No"));

    Debug.LogFormat("IsClimbing : {0}", stats.IsClimbing);
}

在输出窗口中,打印
In PlayerController Awake(). Is PlayerController.stats null? Yes
IsClimbing : False

如果我也在IsClimbing方法中进行相同的Update()调试,那么当我开始攀爬时,该值是正确的。

最后,我的问题是,如果PlayerStatsstats,如何使用stats变量访问null类的变量?我以为它可能以某种方式直接调用PlayerControls属性,因此我更改了它们的名称,删除了new内的PlayerStats,甚至将调试语句放在其中一个属性中PlayerStats,它肯定会被调用。例如,
public bool IsClimbing { get { Debug.Log("Called IsClimbing inside PlayerStats."); return base.Climbing; } }

如果它被调用并正常工作,它怎么可能是null?我问我的教授,他似乎也不知道为什么。这里到底发生了什么?




修改

根据要求,Singleton类:

public abstract class Singleton<T>: MonoBehaviour where T : MonoBehaviour {
    private static T instance;

    public static T Instance {
        get {
            if(instance == null) {
                instance = FindObjectOfType<T>();
            }
            return instance;
        }
    }
}

Here is an image of the console output.

1 个答案:

答案 0 :(得分:2)

在Unity论坛it appears that the Equals method has been overriddenObject {{{}}最终衍生出来)上挖掘这就是为什么将MonoBehaviournull进行比较并不给予你可能会期待什么。我链接的答案表明这样的代码更合适:

stats == null || stats.Equals(null)