I recently came across null-coalescing operators in C#. In case you are not familiar with them, here is how they work.
?? returns the left hand side if it is not null and otherwise the right hand side. Take an example:
This line will set
processList to a new list if
myList is null.
??= is simply the assignment variant of
This line will set
myList to a new List only if it is null.
The null coalescing operators are great for initializing classes. Read Microsoft’s docs if you want to learn more about them.
In Unity, it is a common pattern to perform null checks and do assignments based on them. A perfect pattern to be replaced by null-coalescing operators!
I started using the null-coalescing operators instead of the null checks and very soon I got some very nasty bugs in my code. Sometimes the
?? operator would return the left hand side even though a null check would return true!!! The two lines above would have different outcomes!
So what is going on here?
It turns out that Unity overloads the
== operator for `Unity.Object` types (anything that derives from UnityEngine.Object). That is how a variables becomes null when game objects are destroyed. Assigning the variables to null would be almost impossible in C#. So Unity Engineers decided to overload the null checks instead.
Null-coalescing operators always check for reference equality and hence the discrepancy in their outcomes. For a destroyed GameObject, the reference equals null even though its actual value is not null.
An easy solution would be to overload the
??= operators for Unity objects. Unfortunately C# doesn’t allow overloading those operators. So there is no easy way to fix this.
How Did We Get Here? Whose Fault Is It?
Unity Engineers have known about this for a long time. A Unity blog post from 2014 shows how they were considering to get rid of the equality check override. But apparently they decided not to break all the Unity projects up to that point for a brighter future.
Overloading the equality operator is a bit iffy to say the least, but if it weren’t for the new null-coalescing operators introduced later on, it would have remained a fine decision.
C# Engineers at Microsoft should take at least partial credit (read blame) for this situation for letting developers overload equality operators and not the null-coalescing operators.
I don’t know why C# doesn’t allow this. I suspect it is keeping C# clean and predictable.
OK, But What Do I Do About It?
As shiny as the new null-coalescing operators are, they are just some syntactic sugar like the
? : ternary operator. Just avoid using them, stick to plain
== checks and you will be fine. Sorry for hyping you up on these operators and telling you not to use them right after. Life isn’t perfect.
I am a software engineer turned game developer. I regularly post about the challenges I face in Unity and share my experiences here. Follow my social media to learn about game development with Unity, C# and also hear my stories.