- Home /
"Operator `??' cannot be applied to operands of type `bool' and `bool'" Error with C# 6's "??" operator
This is my code:
bool didBottomCenterHit = bottomCenterHit.transform.CompareTag ("Ground") ?? false;
"bottomCenterHit" is a RaycastHit2D. From what I've read, it seems like "??" is used to test if something is null, and if it is, set a different value. So, I use it to check if bottomCenterHit is null, and if it is, just set didBottomCenterHit to false.
Yet I get the error mentioned in the title. Can someone help me figure out what I'm doing wrong? Thanks.
Answer by IgorAherne · Oct 05, 2017 at 02:33 AM
null is not false in c#, and it's not 0 either
?? is best used to, say, initialize a List of objects, but only if there is at least one entity to be added. This allows to avoid unnecessary memory allocations, and is useful when list would be generated every frame. This makes it easier on the Garbage Collector
void Update(){
List<MyObject> objectsToBeRemoved = null;
foreach(MyObject obj in objectsToBeRemoved){
if(obj.isGood()){
continue; //skip to next object
}
//list becomes equal to self, or if it's null, we initialize it:
objectsToBeRemoved = objectsToBeRemoved ?? new List<MyObject>();
ojbectsToBeRemoved.add(go);
}
}
Of course we could have used
if(objectsToBeRemoved == null){
objectsToBeRemoved = new List<MyObject>();
}
but, the ?? makes it fit into one line instead of 3 which is nice
In your example, CompareTag() returns a true of false, so you can compare it to what's on the right.
Just as a reminder
a = boolA == BoolB //set a to true only if BoolA is equal to BoolB
a = boolA != BoolB//set a to true oly if BoolA is not euqal to BoolB
a = !a; //set a to false if it was true, or set a to true if it was false (allow to toggle back and fourth)
Thanks for the quick response. I've got a very similar question for you if you'd like to take a quick look:
Doing this:
bool didBottomCenterHit = bottomCenterHit.transform?.CompareTag ("Ground");
Gets me this error:
Cannot implicitly convert type
bool?' > to
bool'. An explicit conversion exists (are you missing a cast?)
After reading the docs on the $$anonymous$$icrosoft website, it would seem like "?" before a "." means don't continue if null. Like a null check. So uhm, I must be wrong on that too then? Sorry, I know you're probably thinking I should just google this, and I have, and read docs, it just doesn't make sense to me. Thanks.
It's not just about "not continuing if null". You have to think about the return type too: what are you trying to assign into bool didBottomCenterHit
.
The value of bottomCenterHit.transform?
is null if the transform is null. The return type of CompareTag() is a boolean. So you are taking an expression that can have the value null, true or false and trying to assign it to a bool. A bool can't be null. In C# there is a way to make value types like bool nullable: you declare the type with a ?
after it. That's what the error is saying. You could do
bool? didBottomCenterHit = bottomCenterHit.transform?.CompareTag ("Ground");
now didBottomCenterHit
can be null as well as true or false.
But that's probably not what you want. You just want to get a false when the object is null? If you want to do that in one line, you could do for example
bool b = bottomCenterHit.transform?.CompareTag("moi") ?? false;
So if you never get to execute CompareTag and bottomCenterHit.transform? has the value null, the ?? makes the value of the whole expression "false", otherwise you do the CompareTag and return its value.
Other remarks: If bottomCenterHit
can be null too, you should write bottomCenterHit?.transform?
or you might still get a null ref error.
$$anonymous$$OST OF ALL
Be very aware when using the null coalescing or conditional operators with UnityEngine.Objects.
unityObject?.something
// or
unityObject ?? something
When you for example Destroy()
a GameObject or do a GetComponent<SomeComponent>()
when there is none attached, you are left with an object that's see$$anonymous$$gly null: yourObject == null
is true.
But because of the way Unity works, the object is actually just a C# wrapper object that still causes object.Equals(yourObject, null) to return false: it is not really null. (You can see this also from the fact that referencing it doesn't cause a real Null Reference Exception, but a Unity $$anonymous$$issing Reference Exception or such)
The null coalescing and conditional operaors usually end up comparing your object with object.Equals()
which causes them to behave unexpectedly with UnityEngine.Objects.
For example this never works:
var renderer = gameObject.GetComponent<Renderer>() ?? gameObject.AddComponent<Renderer>;
As I explained before, GetComponent never returns a "real null" so the ?? evaluates the left side as always being non null. You never add the component even if there was none previously attached.