0

Let's say we are building a game in Unity, and every single frame we want to check whether or not the player is null.

I know this is NOT optimal, but I just want to show an example to state my question.

// 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, since it's a very expensive thing to do. Especially if we do it EVERY frame (which could be 100 times per second).

So I decide to ask Rider to check Player against null in the less expensive way possible. Rider decides to refactor my code to this:

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

I'm kind of new to C#, and don't really understand why it doesn't suffice with:

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

Why is Rider comparing Player to a pair of empty brackets as well?

Jose Lopez Garcia
  • 972
  • 1
  • 9
  • 21
  • From the documentation youve linked it depends on what you want to check https://github.com/JetBrains/resharper-unity/wiki/Possible-unintended-bypass-of-lifetime-check-of-underlying-Unity-engine-object#null-conditional-operator – Drag and Drop Jan 18 '21 at 13:39
  • Thank you, but my questions is more related to that "player is { }" strange comparison? – Jose Lopez Garcia Jan 18 '21 at 13:40
  • 2
    related: [Curly Braces In C#](https://stackoverflow.com/questions/60103804/curly-braces-in-c-sharp) – Drag and Drop Jan 18 '21 at 13:46
  • Assuming `player` derives from `UnityEngine.Object` (the mother class of all Unity built-in reference types) you should be using none of these! See the duplicate links I added in addition to the original one from @DragandDrop 's comment for how to actually check for the existence of anything derived from `UnityEngine.Object` .. use the `bool` operator as in the last code snippet! Reason: In Units it is very often not enough to check for `null` since an object might be **not** `null` but still be *invalid* after e.g. `Destroy` – derHugo Jan 18 '21 at 16:01

1 Answers1

1

The reason Rider complains about a performance penality is that "UnityEngine.Object" has its own implementation of operator==, which means it is more expensive than just a simple null check. It won't do much more (since that's usually explicitly tested within an the equality operation), but it nevertheless usually involves at least a virtual function call (to Equals(object)).

Your last example

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

just doesn't compile in C#. C# does not provide an implicit conversion from a reference to bool.

What you are actually looking for is Object.ReferenceEquals(). This method ensures that, even with operators overloaded and whatever, just a reference comparison is done.

So this changes to:

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

This is a very fast operation and should not give any reasons for a warning.

PMF
  • 14,535
  • 3
  • 23
  • 49
  • Thank you for the answer. Can you please expand on the comparison Rider makes? ```if (player is { } && player) {...}``` – Jose Lopez Garcia Jan 18 '21 at 13:38
  • I'm sorry, but I haven't seen this construct yet (A few new syntactical possibilities involving the `is` operator have been added in the latest version of C#). I suppose it's the same as `if (player is object)` but that's very unlikely to be faster than ReferenceEquals, because it involves a typecast. – PMF Jan 18 '21 at 13:43
  • 3
    `just doesn't compile in C#. C# does not provide an implicit conversion from a reference to bool` this is wrong under the plausible assumption that OP's `player` at some point derives from [`UnityEngine.Object`](https://docs.unity3d.com/ScriptReference/Object.html) which implements explicitly for that reason the [`bool` operator](https://docs.unity3d.com/ScriptReference/Object-operator_Object.html) ;) – derHugo Jan 18 '21 at 15:50