-
Notifications
You must be signed in to change notification settings - Fork 208
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Null safety feedback: initialization check for late variables #1028
Comments
Note that this was discussed in #324. |
But then I think it should be possible to see that this variable is late. When I will use it and hover over it in my editor. (That is, something like a signature) Therefore, I will understand that an exception may occur when using it. |
I'd generally discourage using Exposing such a variable to clients of a class means delegating the responsibility of using the variable correctly to the users. If nothing else, I'd prefer to use a |
Some tips I came up with from advice of different dart maintainers, and my self-analysis:
|
For
there are situations where it's perfectly reasonable to have an instance variable with a lazily-initialized default value. So, basically agree if you add a "with no initializer expression". Those are the dangerous ones. Late variables with initializers are just lazy, but safe. Not sure what exiting and emerging constructors are. The exception to the rule above is that you can have uninitialized late instance fields with no initializer if you initialize them in the constructor bodies instead. Generally, that only makes sense when you need to create cyclic references between newly created immutable objects. Otherwise I'd do my darnedest to avoid late variables that are always initialized in the constructor anyway. Seems like it should be unnecessary, A late variable which is only initialized on some code paths is meaningful, but dangerous. If your logic is consistent, and you only read the variable in cases where you also know it's written, then you're fine, but you can't let users see that. I guess the short version is: Never let a client of your class see an "uninitialized late" error. If such an error can happen when accessing or writing a late variable (no initializer expression), make the variable private and ensure you only use it correctly, or ensure that it's definitely initialized in the constructor, before any user code sees the object. Late variables with initializer expressions are always safe. (If you need to check for initialization, you can use bool _fooInitialized = false;
final late Foo? foo = (_fooInitialized = true) ? _createFoo() : ("throw "unreachable"); That's fairly inefficient, because you are effectively duplicating the "initialization state" of the variable, but shorter to write than bool _fooInitialized = false;
Foo? _foo;
Foo? get foo => _fooInitialized || !(_fooInitialized = true) ? _foo : (_foo = _createFoo()); ) |
@lrhn Thanks for the valuable explanation! Updated my comment accordingly here, in the other thread, and on SO. Linked your comment as well. |
it would be nice to have compile time check for uninitialized late variables |
If we could know it at compile time we wouldn't even need it... |
There should be a way to check if the late variable is initialized or not.
Otherwise, the farther from the place of declaration the initialization occurs, the higher the probability of getting an exception!
As a bonus, thanks to this check, we will be able to use late final fields to cache values in immutable classes.
Instead of this
We can use this (The isInitialized function is just an example)
Also, the analyzer should report at compile time, that we are trying to reinitialize the late final field.
The text was updated successfully, but these errors were encountered: