Rider 检查空对象的新方法

问题描述

假设我们正在 Unity 中构建一个游戏,并且每一帧我们都想检查玩家是否为空。

我知道这不是最佳的,但我只想举一个例子来说明我的问题。

// Update is called once per frame
private void Update()
{
    if (player != null)
    {
        player.Move();
    }
}

According to Jetbrains,we should avoid null comparisons against UnityEngine.Object subclasses,因为这是一件非常昂贵的事情。特别是如果我们每帧都这样做(可能是每秒 100 次)。

所以我决定让 Rider 以尽可能便宜的方式检查 Player 是否为 null。 Rider 决定将我的代码重构为:

// Update is called once per frame
private void Update()
{
    if (player is { } && player)
    {
        player.Move();
    }
}

我对 C# 有点陌生,我真的不明白为什么它不够用:

// Update is called once per frame
private void Update()
{
    if (player)
    {
        player.Move();
    }
}

为什么 Rider 也将 Player 与一对空括号进行比较?

解决方法

Rider 抱怨性能惩罚的原因是“UnityEngine.Object”有自己的 operator== 实现,这意味着它比简单的空检查更昂贵。它不会做更多的事情(因为这通常在相等运算中进行了显式测试),但它通常至少涉及一个虚函数调用(到 Equals(object))。

你的最后一个例子

// Update is called once per frame
private void Update()
{
    if (player)
    {
        player.Move();
    }
}

只是不能在 C# 中编译。 C# 不提供从引用到 bool 的隐式转换。

您实际寻找的是Object.ReferenceEquals()。这种方法确保,即使运算符重载等等,也只进行引用比较。

所以这变成了:

// Update is called once per frame
private void Update()
{
    if (!ReferenceEquals(player,null))
    {
        player.Move();
    }
}

这是一个非常快的操作,不应给出任何警告的理由。