GetComponent returning "null" instead of null - c#

I'm confused about the return value of GetComponent if the requested component is not attached to the object. According to the Unity documentation, GetComponent should return null. However, what appears to be happening is that GetComponent is returning a "null" object of the requested type, rather than the value null.
In this example, my game object does not have a CircleCollider2D attached to it. When I set a breakpoint on the line CircleCollider2D x = GetComponent<CircleCollider2D>();, I get this result
Why is the returned value not null?
EDIT:
Here's a full screenshot of the code and the values in the debugger.
ANOTHER EDIT:
Could it be that Unity has overloaded the == operator so that GetComponent always returns a object, but the object can have an internal "null" state which returns true when compared to null? I can see the following declarations in the UnityEngine namespace
public static bool operator ==(Object x, Object y);
public static bool operator !=(Object x, Object y);

It seems like GetComponent<T>() doesnt return TRUE null. Instead it returns new T with default values that fires MissingComponentException when using any null field. GetInstanceID() and GetHashCode() work because they only use int m_InstanceID which is set to default 0. Not sure how ToString() works but it probably returns "null" when m_InstanceID == 0.
Proof:
void Start()
{
CircleCollider2D getComponent = GetComponent<CircleCollider2D>();
CircleCollider2D empty = null;
CircleCollider2D newCC = new CircleCollider2D();
Debug.LogFormat("getComponent.GetInstanceID() {0}", getComponent.GetInstanceID());
Debug.LogFormat("newCC.GetInstanceID() {0}", newCC.GetInstanceID());
try
{
Debug.LogFormat("empty.GetInstanceID() {0}", empty.GetInstanceID());
}
catch (System.NullReferenceException e)
{
Debug.Log("empty.GetInstanceID() doesnt work, im true null");
}
try
{
string t = getComponent.name;
}
catch (System.Exception e)
{
Debug.Log(string.Format("getComponent fires {0} when any field is null",
e.ToString()));
}
try
{
string t = newCC.name;
}
catch (System.Exception e)
{
Debug.Log(string.Format("newCC fires {0} when any field is null",
e.ToString()));
}
}
Results:
getComponent.GetInstanceID() 0
newCC.GetInstanceID() 0
empty.GetInstanceID() doesnt work, im true null
getComponent fires UnityEngine.MissingComponentException
newCC fires System.NullReferenceException
Also:
getComponent.GetHashCode() = 0
getComponent.ToString() = "null"
Why getComponent == null is true? Usually it's just:
`getComponent.GetInstanceID() == otherComponent.GetInstanceID()`
In o == null case it's:
return !(
o.GetCachedPtr() != IntPtr.Zero || (!(o is MonoBehaviour) &&
!(o is ScriptableObject) &&
Object.DoesObjectWithInstanceIDExist(o.GetInstanceID())));
So i guess object with InstanceID = 0 never exists.
Search for decompiled UnityEngine/UnityEngine/Object.cs if u want to know more.

Could it be that Unity has overloaded the == operator
Tldr: Yes.
Why is the returned value not null?
According Custom == operator, should we keep it? :
When a MonoBehaviour has fields, in the editor only, we do not set
those fields to “real null”, but to a “fake null” object.
Why? According that article, basically for two reasons:
On Editor mode: get more contextual information on invocations, so if you have an exception you will be able to know which object was the cause.
Every that comes from UnityEngine.Object are wrapped in a C# object to keep the reference to the Unity C/C++ GameEngine Object. In the editor/code we work with the C# elements but those are just a reference to the 'real' c++ objects. Now, the lifetime of those 'real' c++ objects are handled explicitly (if you destroy something the C++ object it will be destroyed and the allocated memory it will be freed) but the C# object will be completely destroyed when the Garbage Collector decides to free that memory. So you will have a not null C# object pointing to a null C++ object. With this fake null trick you will know that this specific C# object is null because in the C++ side it was destroyed.
This is also important when if you have a singleton and if (sm_Instance == null) is not working as expected, you can use: if (EqualityComparer<T>.Default.Equals(sm_Instance, null)) instad.
Edit: Probably this can be caused if your singleton use generics and your type constrain is class
public class Singleton<T> where T : class {
This will cause to use the == operator of a class object, even when your Singleton is a GameEngine Object. One fix for that? Instead of class you can use UnityEngine.Object, like:
public class Singleton<T> where T : UnityEngine.Object {
Related Thread:
https://forum.unity3d.com/threads/null-check-inconsistency-c.220649/#post-1775701
Ps: If you go to UnityEngine.Object assembly, you will be able to see the overload:
Almost at the end...

if you are still looking for solution this worked for me`
var component = parent.GetChild(i).GetComponent<T>();
if(component != null)
{
if (component.ToString().Equals("null") == false)
{
list.Add(component);
}
}

GetComponent is expected to return object of type 'Component. Hence it is not expected to return "null" rather ~null is expected value. Perhaps this strange behavior should be reported to unity3d,

Related

Why does my if statement appear to be running twice on first run, even though it shouldn't?

I am currently making a game similar to Flappy Bird, and I have an if statement nested inside another if statement. When the first if statement becomes false, the other if statement still runs, but it only runs once. It should not be running when the first if statement returns false.
void Update()
{
if(!passed) {
if(Player.position.x >= gameObject.GetComponent<Transform>().position.x) {
Debug.Log("done");
passed = true;
}
}
}
As you can see when it first starts, the passed boolean becomes true which means it shouldn't run again after completion. However when I pass the obstacle for the first time in-game, it prints out "done" twice. This only occurs for the first obstacle.
In another script I have this:
private void OnTriggerEnter2D(Collider2D collision){
GameObject.Find("ObstacleTop").GetComponent<Obstacles>().passed = false;
}
And btw passed is set to false at the start:
public bool passed = false;
The script is probably attached to two game objects, so it shows the log output twice.
You can see which instance the log is for by calling GetInstanceID() in the Debug statement.
if (!passed) {
if (Player.position.x >= gameObject.GetComponent < Transform > ().position.x) {
Debug.Log(gameObject.GetInstanceID() + " done");
passed = true;
}
}
If you want to execute the code for the first object that ever executes Update and fulfills the condition, then make the passed variable static.
public static bool passed;
void Update()
{
if(!passed &&
Player.position.x >= gameObject.GetComponent<Transform>().position.x) {
Debug.Log("done");
passed = true;
}
}
If you make the variable static, it will exist once for this class instead of once per instance (i.e., per object).
You can also combine the two if-statements. Since C# uses short circuit evaluation, the second part of the condition (after the &&) will not be evaluated, if the first part evaluates to false.
Since the flag you use to indicate whether it passed or not is not in the same scope as its accompanying if statement, your logic will now depend on the second nested if statement instead.
If you want to only go through this once regardless of what happens in the body, you should do something like this instead:
void Update()
{
if(!passed) {
if(Player.position.x >= gameObject.GetComponent<Transform>().position.x) {
Debug.Log("done");
}
passed = true;
}
}
This marks the block as passed as long as it has entered there at least once.

Use event to execute method

I have a C# class which contains the following:
public event Action<int> UnsupportedMessage;
It also has a method containing
if (template != null)
{
...
}
else
{
if (UnsupportedMessage != null)
{
UnsupportedMessage(templateId);
}
}
Another C# class called HealthCheck contains public void MyMessage(int id).
What's supposed to happen is if template is null, an event should call HealthCheck.MyMessage().
So many things are wrong here. UnsupportedMessage is always null so UnsupportedMessage(templateId); never gets executed. Even is I remove if (UnsupportedMessage != null) UnsupportedMessage(templateId); will throw System.NullReferenceException: 'Object reference not set to an instance of an object.'. Even if it did work, there's no reference to HealthCheck.MyMessage() so I don;t know how it could ever be run.
How do I create an event to do what I need?
Update
I tried changing to UnsupportedMessage?.Invoke(templateId); as mentioned in the below answer and added this in the line above it:
UnsupportedMessage += _handlerClass.UnsupportedMessage;
_handlerClass is initialized by the constructor contains this method:
public void UnsupportedMessage(int value)
{
...
}
This initially seemed to work but it seems to be getting called many more times than I expected.
It sounds like you're simply missing the event subscription step; you'd presumably need:
objectThatIsGoingToRaiseTheEvent.UnsupportedMessage += healthCheckInstance.MyMessage;
which will make UnsupportedMessage become non-null, and make everything work. You should also change:
if (UnsupportedMessage != null)
{
UnsupportedMessage(templateId);
}
to either
UnsupportedMessage?.Invoke(templateId);
or (on older C# versions, noting that this is semantically identical)
var handler = UnsupportedMessage;
if (handler != null) { handler(templateId); }
to avoid a race condition that is possible if the last event-handler unsubscribes (-=) between the two reads of UnsupportedMessage in the original version.

ReSharper warning for Possible System.NullReferenceException despite implicit null check

I am getting a ReSharper (2018.1) warning for Possible 'System.NullReferenceException' when I check for null implicitly with if (obj) instead of if (obj ! = null).
For example:
using JetBrains.Annotations;
using UnityEngine.UI;
public class CanBeNullTest : MonoBehaviour
{
[CanBeNull] public Button Button { get; set; }
private void EnableButton_explicitCheck()
{
if (Button != null) Button.enabled = true;
}
private void EnableButton_implicitCheck()
{
if (Button) Button.enabled = true;
}
//private void EnableButton_cSharp6()
//{
// // null propagating operator is not available in C# 4
// Button?.enabled = true;
//}
}
Only the implicit null check shows the ReSharper warning:
I looked at the ReSharper page for "Why is ReSharper suggesting this" and the links there, but I couldn't find an explanation for this.
Is this a ReSharper limitation? Or is it incorrect or bad style to check for null implicitly?
Although it doesn't actually produce a NullReferenceException, because your Button can be null and the if statement triggers an implicit conversion to boolean that produces the NullReferenceException, it is still valid warning in general.
Something similar in Java,
Check if null Boolean is true results in exception
If you don't like extra null checks, you may be able to do the C# equivalent of the following Java code,
if (Boolean.TRUE.equals(value)) {...}
The if (Button) involves an implicit conversion to bool, which doesn't produce a NullReferenceException in this case, but it is a valid warning in general.

Where to use if(obj == null) When writing API?

I am always confused about when to use if (sth == null). Design of delegate in C# is like this:
//Declaration:
private delegate void OnSthHappened();
//In some place, do:
OnSthHappened += SthHappendCallback;
//When use delegate:
if(OnSthHappened != null)
OnSthHappened();
I really think of judging it is null everytime when use OnSthHappened is unnecessary. I know that in compiler, delegate will become a class to handle the callback. Then why the C# compiler doesn't do the other way like:
//Use the delegate directly:
OnSthHappened();
//In the created-by-compiler class, do the judgement:
//object: instance object, Intptr method: a method pointer
if(method != 0x00) //Null, hide the judgement here
{
Invoke(object, method);
}
I just gave a scene of where to judge null, this is giving me hard choices everytime when I try to write API, to do ==null in caller or called functions? Does anyone could give me some style about where to use ==null judgement?
I know that in compiler, delegate will become a class to handle the callback
Delegate (more precise, MulticastDelegate, because in fact we work with multicast delegates) is a class already. The delegate keyword is just a way to declare a MulticastDelegate-derived type.
Where to use if(obj == null) When writing API?
Shortly, check for null:
in public or protected contacts, if the particular method parameter or return value must not be null. If it is null, throw an exception;
in public, protected or private contracts, when value the value could be null, and you can handle that.
public void Method1(Action action)
{
Contact.Requires<ArgumentNullException>(action != null);
}
public object Method2()
{
Contract.Ensures(Contract.Result<object>() != null);
// code here
}
public void Method2(Action action == null)
{
if (action != null)
action();
}
Do not check for null:
in private contacts, when value must not be null.
private void Method3()
{
var result = Method2();
// In case of result == null, NRE is a best option here.
Console.WriteLine(result.ToString().Length);
}
UPD.
why use different strategies between private and public methods? What is the benefit?
Public or protected surface is unpredictable.
You can't guarantee, that user of your class will provide, for example, valid parameter values. That's why you must check them - this is the way to tell the user, that something is wrong in his code. By delivering understandable exception, you can tell, what is wrong exactly. Note, that user hasn't access to your code, and ArgumentNullException on your method call is much more cleaner, that NullReferenceException inside of your method.
On the other hand, your release code should be clean from extra checks.
If you'll return null from any private method, and then try to access a member of that null value, you'll get NRE during debugging or testing. Then you have to fix error in your code and forget it. If you have fixed the error, there's no reason to keep the null-checking alive. This all doesn't avoid Debug.Assert/Contract.Assert or similar. But: a) those thing should live in debug version of your code; b) they must not be after every line of code, because this reduces code readability; c) often it is enough to catch an exception in debugger/unit test result.

Thread-safe use of a singleton's members

I have a C# singleton class that multiple classes use. Is access through Instance to the Toggle() method thread-safe? If yes, by what assumptions, rules, etc. If no, why and how can I fix it?
public class MyClass
{
private static readonly MyClass instance = new MyClass();
public static MyClass Instance
{
get { return instance; }
}
private int value = 0;
public int Toggle()
{
if(value == 0)
{
value = 1;
}
else if(value == 1)
{
value = 0;
}
return value;
}
}
Is access through 'Instance' to the 'Toggle()' class threadsafe? If yes, by what assumptions, rules, etc. If no, why and how can I fix it?
No, it's not threadsafe.
Basically, both threads can run the Toggle function at the same time, so this could happen
// thread 1 is running this code
if(value == 0)
{
value = 1;
// RIGHT NOW, thread 2 steps in.
// It sees value as 1, so runs the other branch, and changes it to 0
// This causes your method to return 0 even though you actually want 1
}
else if(value == 1)
{
value = 0;
}
return value;
You need to operate with the following assumption.
If 2 threads are running, they can and will interleave and interact with eachother randomly at any point. You can be half way through writing or reading a 64 bit integer or float (on a 32 bit CPU) and another thread can jump in and change it out from underneath you.
If the 2 threads never access anything in common, it doesn't matter, but as soon as they do, you need to prevent them from stepping on each others toes. The way to do this in .NET is with locks.
You can decide what and where to lock by thinking about things like this:
For a given block of code, if the value of something got changed out from underneath me, would it matter? If it would, you need to lock that something for the duration of the code where it would matter.
Looking at your example again
// we read value here
if(value == 0)
{
value = 1;
}
else if(value == 1)
{
value = 0;
}
// and we return it here
return value;
In order for this to return what we expect it to, we assume that value won't get changed between the read and the return. In order for this assumption to actually be correct, you need to lock value for the duration of that code block.
So you'd do this:
lock( value )
{
if(value == 0)
... // all your code here
return value;
}
HOWEVER
In .NET you can only lock Reference Types. Int32 is a Value Type, so we can't lock it.
We solve this by introducing a 'dummy' object, and locking that wherever we'd want to lock 'value'.
This is what Ben Scheirman is referring to.
The original impplementation is not thread safe, as Ben points out
A simple way to make it thread safe is to introduce a lock statement. Eg. like this:
public class MyClass
{
private Object thisLock = new Object();
private static readonly MyClass instance = new MyClass();
public static MyClass Instance
{
get { return instance; }
}
private Int32 value = 0;
public Int32 Toggle()
{
lock(thisLock)
{
if(value == 0)
{
value = 1;
}
else if(value == 1)
{
value = 0;
}
return value;
}
}
}
I'd also add a protected constructor to MyClass to prevent the compiler from generating a public default constructor.
That is what I thought. But, I I'm
looking for the details... 'Toggle()'
is not a static method, but it is a
member of a static property (when
using 'Instance'). Is that what makes
it shared among threads?
If your application is multi-threaded and you can forsee that multiple thread will access that method, that makes it shared among threads. Because your class is a Singleton you know that the diferent thread will access the SAME object, so be cautioned about the thread-safety of your methods.
And how does this apply to singletons
in general. Would I have to address
this in every method on my class?
As I said above, because its a singleton you know diferent thread will acess the same object, possibly at the same time. This does not mean you have to make every method obtain a lock. If you notice that a simultaneos invocation can lead to corrupted state of the class, then you should apply the method mentioned by #Thomas
Can I assume that the singleton pattern exposes my otherwise lovely thread-safe class to all the thread problems of regular static members?
No. Your class is simply not threadsafe. The singleton has nothing to do with it.
(I'm getting my head around the fact that instance members called on a static object cause threading problems)
It's nothing to do with that either.
You have to think like this: Is it possible in my program for 2 (or more) threads to access this piece of data at the same time?
The fact that you obtain the data via a singleton, or static variable, or passing in an object as a method parameter doesn't matter. At the end of the day it's all just some bits and bytes in your PC's RAM, and all that matters is whether multiple threads can see the same bits.
Your thread could stop in the middle of that method and transfer control to a different thread. You need a critical section around that code...
private static object _lockDummy = new object();
...
lock(_lockDummy)
{
//do stuff
}
I was thinking that if I dump the singleton pattern and force everyone to get a new instance of the class it would ease some problems... but that doesn't stop anyone else from initializing a static object of that type and passing that around... or from spinning off multiple threads, all accessing 'Toggle()' from the same instance.
Bingo :-)
I get it now. It's a tough world. I wish I weren't refactoring legacy code :(
Unfortunately, multithreading is hard and you have to be very paranoid about things :-)
The simplest solution in this case is to stick with the singleton, and add a lock around the value, like in the examples.
Quote:
if(value == 0) { value = 1; }
if(value == 1) { value = 0; }
return value;
value will always be 0...
Well, I actually don't know C# that well... but I am ok at Java, so I will give the answer for that, and hopefully the two are similar enough that it will be useful. If not, I apologize.
The answer is, no, it's not safe. One thread could call Toggle() at the same time as the other, and it is possible, although unlikely with this code, that Thread1 could set value in between the times that Thread2 checks it and when it sets it.
To fix, simply make Toggle() synchronized. It doesn't block on anything or call anything that might spawn another thread which could call Toggle(), so that's all you have to do save it.

Categories