问题描述
假设我们正在 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();
}
}
这是一个非常快的操作,不应给出任何警告的理由。