checking variable null-safety with ! and? [duplicate] - flutter

This question already has answers here:
What is Null Safety in Dart?
(2 answers)
Closed 11 months ago.
I trying to understand the basics of null-safety in dart
what is the best use for this:
// model
class MyModel {
String? name;
MyModel({this.name})
}
// view-controller
MyModel? response;
// do some async operations here, on success response get a value
if(response!.name == null){
}
if(response?.name == null){
}
// what is the best practice? and what should i use in this case?
// ! or ?

Go through this codelab excersie and you will get with basics of using '?' vs '!'.
For reference I am explaining both a bit:
suppose you want to have a string variable which could be, at any point null or can be used to store null value. For this case you can't use String to initialize your variable, instead you need to do it like this way :-
String? str
And now the '!' part which is called 'null assertion operator'. Sometimes flutter sdk thought that maybe any variable you have used might be null at runtime and so it throws you error that the object is nullabe. So for that case if you are sure that, the object could never be null at runtime so you need '!' operator to show flutter that it couldn't never be null.
If you have any confusion then do check that codelab exercise for sure.

Related

Dart initializer in constructor [duplicate]

This question already has an answer here:
Is there a difference in how member variables are initialized in Dart?
(1 answer)
Closed 9 months ago.
It looks easy, but not working. I have model in Dart like this:
class FormTab {
String caption;
FormTab(dynamic m) { // where m will be Map
this.caption = m['caption'] ?? "No caption";
}
}
But still I have error message: Non-nullable instance field 'caption' must be initialized. Try adding an initializer expression, or add a field initializer in this constructor, or mark it 'late'.
What is wrong? I set value caption, but still I have error. I tried caption
The body of a constructor in Dart is not part of the initializers. You need to put that into the initializer list:
class FormTab {
String caption;
FormTab(dynamic m) : caption = m['caption'] ?? "No caption";
}
Please note that if you know it's going to be a map, it might be better to make it a map. The earlier you switch from dynamic to actual types, the easier it is to catch errors.

dart null checking: why do i have to use a null check operator ('!') after checking already for null ( != null ) [duplicate]

This question already has answers here:
"The operator can’t be unconditionally invoked because the receiver can be null" error after migrating to Dart null-safety
(3 answers)
Closed 1 year ago.
I updated my flutter project to nullsafety and get errors saying:
The function can't be unconditionally invoked because it can be 'null'.
Try adding a null check ('!').
For a variable that I already checked for null. What is the correct way to do this now? I know I can just add ! because i know it can't be null. But I don't see why. If there was more code it could happen, that the null check is deleted and the ! operator stays.
Here is my code example:
final Function? suggestionsCallback;
if (widget.suggestionsCallback != null &&
widget.defaultSearchPattern.isNotEmpty &&
pattern.isEmpty) {
return await widget.suggestionsCallback(widget.defaultSearchPattern); // here is the error
} else {
return widget.suggestionsCallback != null
? await widget.suggestionsCallback(pattern) // here is the error
: [];
}
Take a quick look at my code:
class Hello{
final Function? hello;
Hello(this.hello);
}
class Say{
wow(){
var h1 = Hello(null);
if(h1.hello!=null) h1.hello();
}
}
https://dart.dev/tools/non-promotion-reasons#property-or-this
Note: "Promotion" here means "determine that a nullable is in fact not null at this line of code";
Dart compiler is not smart enough to infer that your function, after the if-statement, is NOTNULL at that position of your code. It can only tell a local variable is not null after certain condition statements.
You know the variable can’t be null because you just checked. The compiler doesn’t. So unfortunately you have to tell it again.
Actually your specific compiler might be clever enough, but not all compilers are. And whether you have compile time errors shouldn’t depend on how clever the compiler is. Therefore the language will require the ! test. It’s quite possible that the compiler produced no actual test for the !

How to take integer input in dart after the null safety update without using the if block for veriying weather the variable is null or not? [duplicate]

This question already has answers here:
"The argument type 'String?' can't be assigned to the parameter type 'String'" when using stdin.readLineSync()
(3 answers)
Closed 1 year ago.
Every time i need to input certain variable as integer i used to use this below code for that
import 'dart:io';
void main(List<String> arguments) {
int a = 0;
print("Enter a :");
String? x = stdin.readLineSync();
if (x != null) {
a = int.parse(x);
}
}
which is very hectic...very since the null safety was added from Dart 2.12 version.Before it the integer was inputted using this code int n = int.parse(stdin.readLineSync());
can anyone propose to make it smaller...since its hefty..
Since we are using Null Safety by default with Dart 2.12.2.
We also know that int.parse() take a String that cannot be null due to Null Safety.
however int.parse(readLineSync()) can return a int? which is a nullable value by simply adding the The null assertion operator (!) at the end of stdin.readLineSync() as show in code below
import 'dart:io';
void main(List<String> arguments) {
print("Enter a :");
int? a = int.parse(stdin.readLineSync()!);
}
The null assertion operator (!)
If you’re sure that an expression with a nullable type isn’t null, you can use a null assertion operator (!) to make Dart treat it as non-nullable. By adding ! just after the expression, you tell Dart that the value won’t be null, and that it’s safe to assign it to a non-nullable variable.
note:-If you’re wrong, Dart throws an exception at run-time. This makes the ! operator unsafe, so don’t use it unless you’re very sure that the expression isn’t null.
Hope you find this useful...(☞゚ヮ゚)☞

Flutter null-safety conditionals in object methods

I'm just working through this whole null-safety mode with my Flutter project and unsure what the difference is with ? and ! in calls to object methods.
For example, the hint was to add a ! conditional. Here's an example I have right now, and I'm unsure if this should be a ? or a ! at the findNbr!.replaceAll().
Future checkItem({String? findNbr}) async {
int? x = int.tryParse(findNbr!.replaceAll('-', ''));
...
Does this mean replaceAll() will not run if findNbr is null?
Or should it be a ? instead? findNbr?.replaceAll()
EDIT: I just noticed I cannot use findNbr?, it's telling String? can't be assigned parameter String.
Or does it mean I say it's not null and run it anyway?
For your information, I have not come close to running my app yet so I have no idea if it even works. But I figure I better know what it's doing before get too much more done. I'm still in the process of converting everything and there's 75-100 dart files. I'm not sure I get the point of it all to be honest, because I just add ? to everything, so its all nullable anyway.
Future checkItem({String? findNbr}) async {
int? x = int.tryParse(findNbr!.replaceAll('-', ''));
...
Does this mean replaceAll() will not run if findNbr is null?
Correct. If findNbr is null, then findNbr! will throw a runtime exception. That would be bad, especially since checkItem's function signature advertises that findNbr is allowed to be null, and therefore it would violate callers' expectations.
Or should it be a ? instead? findNbr?.replaceAll()
EDIT: I just noticed I cannot use findNbr?, it's telling String? can't be assigned parameter String.
You can't use findNbr?.replaceAll(...) because if findNbr is null, then it would be invoking int.tryParse(null), but int.tryParse is not allowed to take a null argument.
What you need to do is one of:
Make findNbr no longer optional:
Future checkItem({required String findNbr}) async {
int? x = int.tryParse(findNbr.replaceAll('-', ''));
...
Allow findNbr to be optional but have a non-null default value:
Future checkItem({String findNbr = ''}) async {
int? x = int.tryParse(findNbr.replaceAll('-', ''));
...
Allow findNbr to be optional but explicitly decide what to do if it is null. For example:
Future checkItem({String? findNbr}) async {
int? x = findNbr == null ? null : int.tryParse(findNbr.replaceAll('-', ''));
...
I'm not sure I get the point of it all to be honest, because I just add ? to everything, so its all nullable anyway.
If you blindly add ? to all types and add ! to all variables, then yes, null-safety would be pointless: doing that would give you the same behavior as Dart before null-safety.
The point of null-safety is to prevent things that shouldn't be null from ever being null. You could have written such code before, but without null-safety, that meant performing runtime null checks (e.g. assert(x != null);, if (x != null) { ... }, or relying on a null-pointer-exception to crash the program if null was used where it wasn't expected). Null-safety means that such checks now can be done at build-time by static analysis, which means that errors can be caught earlier and more completely. Furthermore, whereas previously functions needed to explicitly document whether arguments and return values were allowed to be null (and inadequate or incorrect documentation could be a source of errors), now they're self-documenting in that regard. It's just like using int foo(String s) versus dynamic foo(dynamic s); using strong types catches errors earlier and better describes the function's contract.
I recommend reading Understanding Null Safety if you haven't already done so.
I would like to advice you to use the ! operator, also the called bang operator, as little as possible. You should only use this operator when the dart analyser is wrong and you know for 100% that the value will never be null.
Below is an example of where the dart analyser would be wrong and you should use the bang operator.
// We have a class dog with a nullable name.
class Dog {
String? name;
Dog({this.name});
}
void main() {
// We create a dog without a name.
final dog = Dog();
// We assign the dog a name.
dog.name = 'George';
// The dart analyser will show an error because it can't know if the
// name of the object is not null.
//
// Will throw: `A value of type 'String?' can't be assigned to a
// variable of type 'String'`.
String myDogsName = dog.name;
// To avoid this, you should use the bang operator because you `know` it
// is not null.
String myDogsName = dog.name!;
}
The ? operator simply tells Dart that the value can be null. So every time you want to place a ? operator, ask yourself, can this value ever be null?
The null safety features in Dart are mainly created for helping the developer remember when a value can be null. Dart will now simply tell you when you made a variable nullable in order to force null checks or default values for example.

How to use optional in Dart for null safety

I found this package that implements Optional for Dart: https://pub.dev/packages/optional/example
On the examples, it does things like this:
void filterExample() {
final hello = Optional.of('hello');
final world = Optional.of('world');
final name = Optional.of('harry');
for (var o in [hello, world, name]) {
final filtered = o.filter((v) => v.startsWith('h'));
print(filtered.isPresent);
} // prints "true", "false", "true"
}
But how do I force a variable to be Optional of some type? I wanted to have Optional<String>, Optional<int>, etc, but I'm forced to give a value in the beginning.
The closest I can think is
final anEmpty = Optional.ofNullable(null);
which is already in the example, but what is a Nullable? If I do like this, I cannot constraint the value to be a String or int, it can be changed to anything. I want to stick to strong typing while using Optional.
If this is not possible with this library, then how can I make my own simple Optional type that supports templates so I can have Optional<String>, Optional<int>, etc?
The behavior you are looking for (doing something if null and something else otherwise) can be achieved using the ?? operator.
This is basically a null check which equals the left hand if not null and right hand if null. Example: doSomething(myString ?? "Default value of my string");
Does this answer your question? Sorry, I haven't used that package and don't see a need to.