Home > Enterprise >  Unnecessary usage of bang operator
Unnecessary usage of bang operator

Time:12-07

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?

CodePudding user response:

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 in

class Wrapper {
  late GeoPosition position;
}

Wrapper wrapper = Wrapper();
wrapper.position = GeoPosition();     
wrapper.position.lat = 1;

This 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

CodePudding user response:

Nullable properties of a class can still be null between two access.

For your first example you can extract the variable then check it:

    var someValue = model?.someValue;
    if(someValue != null) {
       print(someValue); // not null
    }

For your second example an elegant way will be the .. operator :

    Wrapper wrapper = Wrapper();
    wrapper. Position = GeoPosition()..lat = 1;

If you want the GeoPosition to be not null you have to make it not nullable:

    class Wrapper {
      GeoPosition position;
    
      Wrapper(this.position);
    }

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.

  • Related