- Home /
Is it possible to perform a TRUE null-check?
I'm aware of how ==null behaves in classes derived from UnityEngine.Object - no need to explain that. However it really stands in my way, because it seems I'm unable to perform true null-check. Like: I have no way to differentiate destroyed object from real null. Is there any way to find out, if a reference is really a null, not a destroyed object? Or do I have to do some workarounds?
Since nobody is answering or even commenting, I'm still looking for the solution. I found out that ?? operator DOES in fact detect true null. However it can be pretty difficult to use it because it gives a statement... But I'm working on it. As soon as I figure something solid out, I'm gonna post an answer (for future generations).
I'm not really sure what you mean.... the reference to a destroyed object is null. What is your definition of a "true" null? How exactly is this really standing in your way, and what is the problem you're actually trying to solve?
It is not. If it was true null reference in a C# meaning, then using dot access operator on it would automatically throw System.NullReferenceException. Ins$$anonymous$$d accessing destroyed GameObject's properties, such as transform, causes $$anonymous$$issingReferenceException, which is introduced by Unity libraries. However, if you have a script class derived from $$anonymous$$onoBehaviour, you can define your own properties. Those properties can be accessed very well after you call Destroy() for a GameObject holding this script. But if you compare the instance of this script with null, like this: instance == null
it will give you true. Here's the inconsistency.
The main problem is, with overriding Equals and == operator this way, Unity changed quite the fundamental way the C# language behaves. I knew C# long time before Unity and I know it pretty well. Having practice with it it seems really counterintuitive for null comparison to return true in cases, when there is no real null in a variable/field.
$$anonymous$$ake sure you read this blog post, especially the reason "no2" to understand why they did this in the first place.
I read this post even before posting this question, and I understand it, but the main feeling I got from it is the doubt of the very creators of such a mechanism, wether the caveats of it are worth the gain. Which in my opinion are not. I never needed such a mechanism. Bah, in C++ when you use delete on a pointer that points to something created by new, it doesn't put address 0 (C++ equivalent of null) to every other pointer pointing to the same memory space, right?
So, simple IsDestroyed property would be sufficient & clean. This is just a one of many weird ideas of Unity creators, such as na$$anonymous$$g the most general class "Object", which is in conflict with System.Object, or na$$anonymous$$g all properties with lowerCamelCase, as opposed to standard C# na$$anonymous$$g convention, or using yield keyword in a way it was never intended to use by C# developers (i.e. coroutines), or making extensive use of reflection (Start, Update methods) ins$$anonymous$$d of simply using polymorphism (making these methods virtual).
Seriously? We have to find hacky workarounds for something so straight forward? null
means null
, it doesn't mean inaccessible, to be destroyed or something else.
This ghetto hack of highjacking a fundamental language identifier only brings trouble (read bugs, even subtle bugs) with checking for null when it's not, or checking for not null when it is, debugging in vs and first of all it just doesn't make sense.
Answer by Sushi271 · Aug 03, 2016 at 06:40 AM
Found it!
Apparently there is much, much simpler way to compare with true null. One property of == operator saved the day: it is not polymorphic. It means, that though every descendant of UnityEngine.Object gets this nasty surprise as a gift, there is one ancestor of UnityEngine.Object, which remembers good old ways: System.Object.
In other words:
bool a = destroyedObject == null;
bool b = (System.Object)destroyedObject == null;
bool c = (object)destroyedObject == null;
Variable a will be true, whereas b and c will be false, since destroyedObject is not a null reference. In fact c is just a simpler way to write b.
Unsurprisingly, calling Equals method even when object is cast to System.Object does not work - since Equals is polymorphic.
Actually I wrote myself an extension method just so I wouldn't need to use cast all the time:
public static bool IsTrueNull(this UnityEngine.Object obj)
{
return (object)obj == null;
}
Of course you can call extension method even on null references (so it works), since it isn't a true member, just a syntactic sugar.
Uhm, isn't that pretty much exactly what i wrote as an answer 10 hours ago? You said
I'm aware of how ==null behaves in classes derived from UnityEngine.Object - no need to explain that
But in your own answer you seems to be suprised and you actually explain it.
Somehow this answer says it's been posted 4 hours ago, but in fact I posted it merely 2 hours after posting a question... So your answer 10 hours ago appeared for me much later than my own answer.
And yes, I was aware, that ==null with Unity objects returns true with both nulls and destroyed objects. I was also aware that == operator in C# isn't polymorphic. But it just took me a while to connect the dots, that I can use == operator from System.Object, by casting on it. And I always explain solution to my own problems on any StackExchange, as a habit, so other people with the same problem can get the solution. It's a nice gesture, compared to answers like "Never $$anonymous$$d, I found the solution."
Yes, you're right ^^. I usually check the revision history
As a matter of fact, I'm kinda amazed how similar our answers are, even though none of us have seen the other one before writing his own... :) Even the idea of an extension method.
I must agree with Bunny83 here. Why did you make your own answer as a copy of his/hers? That's in pretty poor taste.
Because I didn't. $$anonymous$$y answer was posted long before Bunny83's, but it was awaiting moderation, that's why it arrived later. Check revision history.
Answer by Gread72 · Aug 03, 2016 at 01:11 PM
Here is another way to check for null : Object.ReferenceEquals
public GameObject myGameObj;
if( Object.ReferenceEquals( myGameObj, null ) )
{
Debug.Log("myGameObj is null");
}
It is slightly faster depending on the implementation.
This seems to work IF the class in question is either set as private or not serialized in the inspector. Looks like it gets constructed as soon as it is visible in the inspector.
Debug.Log("Is Null?:" + lastDetected==null); False
Debug.Log("CAST Is Null?:" + (object)lastDetected == null); False
Debug.Log("REF Is Null?:" + object.ReferenceEquals(lastDetected,null)); True if set as private
I guess I will have to check for null and if initialized..
Answer by Bunny83 · Aug 02, 2016 at 11:28 PM
Yes you can test if a reference is really null by simply casting it to "object".
Example:
Transform someObjectReference;
if (someObjectReference == null)
{
if ((object)someObjectReference == null)
{
// Really null
}
else
{
// Unity fake null
}
}
I think an extension method like this should work as well:
public static class UnityObjectExtension
{
public static bool IsRealNull(this UnityEngine.Object aObj)
{
return (object)aObj == null;
}
}
With that you should be able to do this:
if (someObjectReference.IsRealNull())
{
}
Thanks, that's pretty much the same that I came up with. However, what I said in other comment, because my own answer was awaiting moderation, and your didn't, it appeared after your, even though I posted it long before. +1 Anyway.
Answer by initram · Aug 03, 2016 at 01:44 AM
you can Either cast to System.Object, and then compare with == null, or you can use System.Object.ReferenceEquals(mythingie, null);
The cast to object is marginally faster.
Your answer
![](https://koobas.hobune.stream/wayback/20220612090031im_/https://answers.unity.com/themes/thub/images/avi.jpg)