I just discovered that I still had not properly learned everything I needed about Unity’s null references.
What I found is that when writing collection code, generic fields might still report == null as false, even when object has no value, and its ToString() is “null”.
So my question is… how do you properly check a generic argument for equality between null and “null” (the other null).
If the type is explicitly Unity type (Unity.Object and derived → Component Monobehavior etc) than it will return null when an object was destroyed even when reference is not null. ex: void Foo(Component cmp)
But when your object type is hidden for example void Foo(object obj) than it will not return null when it was destroyed.
To check for real null on Unity type you can use System.object.ReferenceEquals or cast Unity type to System.object and than compare.
Well, this is the general issue when you have a System.Object reference that holds a UnityEngine.Object instance. That reference could be real null, or could reference a dead / fake null UnityEngine.Object instance which should be treated as if it’s null. This is usually handled by the overloaded == operator, however operators are not polymorphic. The simplest ad hoc solution is to use
if (obj == null || obj.Equals(null))
instead of
if (obj == null)
Of course when you need the opposite condition, apply the usual boolean logic. So you use
if (obj != null && !obj.Equals(null))
instead of
if (obj != null)
This will work for all objects since UnityEngine.Object does override the Equals method which is polymorphic. Though it can only be used when you actually have an instance. That’s why you need the first condition as well so that Equals is only called when you actually have an instance.