GetComponent returns null however comparison to null returns false

Look the result of the following function

        public static T FindComponent<T>(this GameObject obj) where T : class
        {
            T a = obj.GetComponent<T>(); // Shows as "null"
            T b = obj.GetComponentInChildren<T>(); // Some correct object

            T c = a ?? b; // c is set to a
            bool d = a == null; // false
            bool g = a != null; // true
            bool f = a.ToString() == "null"; // true

            return obj.GetComponent<T>() 
                ?? obj.GetComponentInChildren<T>() 
                ?? obj.GetComponentInParent<T>();
        }

a is essentially null but a == null returns false. Nevertheless debugger shows a to be null. If a code uses this function and attempts do use that component this exception is thrown:

MissingComponentException: There is no ‘T’ attached to the “[ObjectName]” game object, but a script is trying to access it. T being the component type passed to the function. I am clueless as to how this is even happening. Interesting thing is a.ToString() == "null" is true

The fact alone that you get a MissingComponentException and not a NullReferenceException gives away a lot. In C#, if an object truly is null and you reference its members, you will get a genuine NullReferenceException. There’s no way around it.

Unity does funky things when destroying or e.g GameObjectFind()ing non-existent UnityEngine.Object instances and that causes certain means of checking for null to return unexpected results. “??” is one of them.

Here’s a blog post about it
And here a forum post

As NoseKills said the problem is that Unity has implemented a custom “==” operator for UnityEngine.Object. For all types which are derived from UnityEngine.Object the compiler will use that overloaded operator. However the operator selection is not dynamic. So the right operator is choosen at compile time.

Since you use a generic method here the actual type of “T” is not known at compile time. Your only constraint is “class” which restricts T to by a reference type. So the == operator used is the normal System.Object == operator and not Unity’s == operator.

Try this:

bool d = (UnityEngine.Object)a == null; 

It should return true for fake null objects.

You can’t use the “null coalescing operator” ( ?? ) since it always uses the System.Object “==” operator.

So to get to a solution you should get rid of the “??” operators.

So one solution would be to change your generic constraint to “Component” instead of “class”. This will make all “T” variables of type Component and ensures that “==” works.

However if you want to be able to pass interfaces as types, you either have to cast the result to UnityEngine.Object (or Component) and then do the check, or use “Equals”

btw: “GetComponentInChildren” will also do a GetComponent. The name is misleading but GetComponentInChildren will first look on the gameobject itself and then inside children.

public static T FindComponent<T>(this GameObject obj) where T : class
{
    T res = obj.GetComponentInChildren<T>();
    if (res != null && !res.Equals(null))
        return res;
    return obj.GetComponentInParent<T>();
}

This should do what you want. The Equals check will tell you about “fake null” objects. Though you can only use Equals when you know the reference isn’t actually null ^^. Equals is a virtual instance method, so it is dynamically dispatched.