Search Unity

Unity's magic null check not properly documented

Discussion in 'Documentation' started by Baste, May 31, 2016.

  1. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    Unity has overriden the == operator such that "x == null" means "is x null or destroyed". While there has been plenty discussion about it on the forums, and on the blog, the documentation for == doesn't capture the whole picture:

    That quote is correct, but doesn't actually explain what's going on, and is not enough to explain to the user what's happening.

    What we need to know is something along the lines of:
    "Unity has overridden the == operator for UnityEngine.Object. When you compare and object with null, the check will return true either if the object is null, or if it has been Destroyed.". A link to an explanation of how objects live both on the c++ side and the C# side, and how this weirdness falls out of the disconnect between those two would also be helpful.

    This == null thing isn't just a minor feature - this is a huge, fundamental change to how the language works. It will surprise any programmer that has written in an object oriented language before they start using Unity. This method needs a clear and long-form explanation of exactly what == does differently from every other C# framework.

    As for the example given, the real caveat that people will run into is not mistakenly comparing a new UnityEngine.Object with null, as the documentation example proposes. I doubt that will ever happen - why would anyone ever try to make a blank Object? What will happen is that you'll get inconsistent == null checks when handling references of an interface type, which experienced programmers will do a bunch. Here's a quick example of something where code hidden behind a null-check will throw a nullReferenceException:

    Code (csharp):
    1. public interface SomeInterface {
    2.     Vector3 GetPosition();
    3. }
    4.  
    5. public class SomeBehaviour : MonoBehaviour, SomeInterface {
    6.  
    7.     public Vector3 GetPosition() {
    8.         return transform.position;
    9.     }
    10.    
    11. }
    12.  
    13. //Example where this goes wrong:
    14. public static void PrintPosition(SomeInterface behaviour) {
    15.     /*
    16.      * Since behaviour is sent in as a SomeInterface, this == resolves to the default C# ==, not the
    17.      * one defined in UnityEngine.Object.
    18.      */
    19.     if (behaviour == null) {
    20.         Debug.Log("It is null!");
    21.     }
    22.     else {
    23.         /* If behaviour is a SomeBehaviour that has been destroyed, this will throw a NullReferenceException
    24.          * when SomeBehaviour.GetPosition tries to access the transform component
    25.          */
    26.         Debug.Log(behaviour.GetPosition());
    27.     }
    28. }
    That's an example of an actual problem users will run in to.
     
    Zenix likes this.
  2. Alex_May

    Alex_May

    Joined:
    Dec 29, 2013
    Posts:
    198
    OK, I see what you are saying. Thanks for the report! I've added it to our buglist.
     
  3. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    1,123
    Wow, this is nasty. I had no idea something like this could be floating around waiting to cause problems in our code base! @Alex_May just to clarify when your said you reported it, do you mean you filed a report to update the documentation, or to "fix" this issue?
     
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    Since the fix would break every_single_project written in Unity, it probably won't happen unless there's a major version change (5->6).

    It would also require the introduction of an IsDestroyed method, and a retraining of all Unity devs to use it. While I'd prefer that, I don't see this as a huge problem. The problem is that Unity's underestimating how huge of a caveat this is, and that it's not documented properly.

    All of Unity's tutorial resources is geared towards people who's got very little, if any, programming experience. There's no "here's what somebody who knows how to program need to know" introduction, so all of the important details gets hidden away in the docs for specific parts of the API.
     
    Zenix likes this.
  5. Alex_May

    Alex_May

    Joined:
    Dec 29, 2013
    Posts:
    198
    The former.
     
  6. WereVarg

    WereVarg

    Joined:
    Apr 9, 2012
    Posts:
    20
    We've faced some situations (2 at least) when Unity silently hits into null ref and doesn't throw anything into Console.