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:
public interface SomeInterface {
Vector3 GetPosition();
}
public class SomeBehaviour : MonoBehaviour, SomeInterface {
public Vector3 GetPosition() {
return transform.position;
}
}
//Example where this goes wrong:
public static void PrintPosition(SomeInterface behaviour) {
/*
* Since behaviour is sent in as a SomeInterface, this == resolves to the default C# ==, not the
* one defined in UnityEngine.Object.
*/
if (behaviour == null) {
Debug.Log("It is null!");
}
else {
/* If behaviour is a SomeBehaviour that has been destroyed, this will throw a NullReferenceException
* when SomeBehaviour.GetPosition tries to access the transform component
*/
Debug.Log(behaviour.GetPosition());
}
}
That’s an example of an actual problem users will run in to.