I’m using Unity’s interface feature. I created a GameObject that implements interfaceA
, then added it to a List<interfaceA>
. After that, I destroyed the GameObject. When I iterate over this list, I observe the following in the debug logs:
csharp
复制代码
interfaceA obj = list[i];
if (obj == null)
{
Debug.Log(1);
}
else
{
Debug.Log(2);
}
In the debug output, obj
appears as “null” but is not actually null. Although obj == null
evaluates to true, the code ends up printing 2
, which is really crazy. If I use obj.Equals(null)
, it correctly prints 1
. Can anyone explain why this happens?
Unity objects have the concept of ‘fake-nulls’. Because we can’t directly destroy C# objects - but all Unity objects are backed by a C++ (which can be destroyed on demand) - Unity has a custom ==
operator between two Unity objects. Part of the check is to see if one of the objects’ backing C++ object has been destroyed (a fake null).
However this will fail if doing the default object == object
operator.
This is covered in the documentation on null references: Unity - Manual: Null references
Needless to say, if you’re destroying these objects, you should be removing them from the list at the same time.
Or you can test if the object is a Unity object before testing for null to use the correct operator:
var obj = list[i];
if (obj is UnityEngine.Object uObject)
{
Debug.Log(uObject == null); // using overloaded equality operator
}
else if (obj == null) // default System.Object equality operator
{
}
In other words, in Unity this statement is true: null != null

The main issue is that the ‘null’==null in compiler displays’ true ‘, but goes towards’ else’, which confuses me
Do you mean in the debugger? Wouldn’t be surprised if the Unity integration allows the debugger to understand fake nulls.
But still when executing, if you use the default System.Object==
operator, fakeNull == null
will be false.
2 Likes