I have a problem understanding, and living with, the excessive use of bang operators in dart/flutter.
Consider this example:
if(model != null && model!.someValue != null) {
print(model!.someValue!);
}
The first condition check is verifying that the model is not null. In the second condition I have to put in a bang operator after model, else the compiler gives me an The property 'someValue' can't be unconditionally accessed because the receiver can be 'null'
error. But why is this necessary? I´ve just checked the variable! And same goes for the print(model!.someValue!);
line.
Another example where I have these classes:
class GeoPosition {
double lat = 0;
}
class Wrapper {
GeoPosition? position;
}
...
Wrapper wrapper = Wrapper();
wrapper.position = GeoPosition();
wrapper.position!.lat = 1;
Now why do I need to put this bang operator (or ? operator) after position
? I´ve just created a new instance of GeoPosition in the Wrapper instance – position cannot be null.
My best guess is that the compiler cannot see or understand the current context of the class. But in Typescript the linter is smart enough to know when these operators are not necessary.
I know that I can create local variables from the properties that I am trying to access, but this would be just as ugly 😉
So why are !
and ?
necessary in these (and many other) situations? And is there anything I can do about it?
2
Answers
This is what happens with nullable properties (hence the message you get). It is explained here: Understanding null safety: Working with nullable fields.
You should be able to work around this issue by declaring the field as
late
, as inThis will remove the need to add a bang to every access to
position
The compiler will add a non-null check at appropriate places. Of course, the program will fail if you don’t assign a non-null value before accessing the field.If explained in Late variables
Nullable properties of a class can still be null between two access.
For your first example you can extract the variable then check it:
For your second example an elegant way will be the .. operator :
If you want the GeoPosition to be not null you have to make it not nullable:
You can set the position field
final
to be immutable.Be careful with the
late
keyword, if you forget to init the field you’ve got a crash like the ! operator.