While trying Dart's Sound Null Safety i came up with a problem:
Creating a new Flutter project i found the following (and very familiar) piece code
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
Now, i changed the variable _counter
to be nullable and took off the initialization:
int? _counter;
void _incrementCounter() {
setState(() {
_counter++;
});
}
And as expected, i got the following error in the editor:
The operator ‘+’ can’t be unconditionally invoked because the receiver can be 'null'
Following the documentation i added the required checking:
if (_counter!=null)
_counter++;
but to my astonishment, the error kept on showing and suggesting
Try making the call conditional (using '?' or adding a null check to the target ('!'))
even though i explicitly am making the call conditionally... so what is wrong?
Null-aware operators are used in almost every programming language to check whether the given variable value is Null. The keyword for Null in the programming language Dart is null. Null means a variable which has no values assign ever and the variable is initialized with nothing like.
When you opt into null safety, types in your code are non-nullable by default, meaning that variables can't contain null unless you say they can. With null safety, your runtime null-dereference errors turn into edit-time analysis errors.
As suggested in another SO thread, in a further thread in Github Erik Ernst says:
Type promotion is only applicable to local variables... Promotion of an instance variable is not sound, because it could be overridden by a getter that runs a computation and returns a different object each time it is invoked. Cf. dart-lang/language#1188 for discussions about a mechanism which is similar to type promotion but based on dynamic checks, with some links to related discussions.
So, with that explanation, now i see that only local variables can (so far?) be promoted, and thus my problem could be fixed by writing
int? _counter;
void _incrementCounter() {
setState(() {
if (_counter!=null)
_counter = _counter! + 1;
});
}
For an alternative fix, see my original answer below.
I finally fixed the problem by capturing the value of the instance variable inside the method as follows:
int? _counter;
void _incrementCounter() {
setState(() {
var c = _counter;
if (c!=null)
c++;
_counter = c;
});
}
Well, the whole problem is that
Type promotion is only applicable to local variables... Promotion of an instance variable is not sound, because it could be overridden by a getter that runs a computation and returns a different object each time it is invoked
so in my approach we
I am new to Dart and thus i am not 100% sure, but to me it seems that in general, when working with nullable instace variables, my approach is better that that of using the bang operator to cast away nullity:
By casting away nullity you are overlooking the main problem of promoting instance variables, namely that
it could be overridden by a getter that runs a computation and returns a different object each time it is invoked ...
That exact problem is what is avoided by capturing the value of the instance variable and working with that locally captured value...
If i am wrong kindly let me know...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With