Understanding " ! " Bang Operator in dart
Asked Answered
T

2

13

I declared a callback method inside a Stateful class like:

final void Function(int index)? onSelected;
MyBottomNavigationBar({@required this.onSelected});

and called using widget.onselected inside state class like:

widget.onSelected!(_selectedIndex);

But I'am not able to understand the actual use of ! Bang operator. I can't initialize widget.onSelected in constructor without giving ? during declaration.

My main question is "How ! bang operator is handling the null values? What's the use of it ?

Tia answered 24/5, 2021 at 5:31 Comment(1)
Null-safety needs to use the new required keyword, not the old @required annotation. Using that will remove the need for onSelected to be nullable. The ! null-assertions operator simply performs a runtime assertion that the object is not null; if it turns out to actually be null, it will throw an exception at runtime.Surovy
P
39

The Bang operator does nothing more than tell Dart that even if we have defined some variable as a Nullable type, it will definitely not be null.

Dart's Nullable safety and Flow Analysis are here to make the developer's life easy by avoiding runtime error and catching them at compile-time itself.

When you define,

final void Function(int index)? onSelected;

You are telling dart that this variable may or may not be assigned a value and thus it may or may not be null.

Now, whenever you try to use it like this,

widget.onSelected()

Dart will warn you that, this is a Nullable typed variable hence take extra care.

If Dart didn't tell you this before hand, then you would've realized it after you ran the app and it crashed while trying to call the function.

Now, since Dart has warned you that you cannot use it like that, there are two ways to approach it.

  1. Put a null check before using it. This way we are avoiding runtime errors.

     var onSelected = widget.onSelected;
     if (onSelected != null) onSelected(_selectedIndex);
    

    This creation of a new local variable is necessary since Dart's flow analysis only works on local variable null checks and not class level variable null checks.


  1. Use the bang operator,

     widget.onSelected!(_selectedIndex)
    

    Now the issue with this is that, you are just assuring Dart that it will never be null, but if it were actually null, it will still result in a runtime crash.

So, the Bang operator is just a way to bypass Dart's flow analysis when you have to access a nullable typed variable.

Hope this clears at least a bit of your doubt.

Pair answered 24/5, 2021 at 5:49 Comment(1)
Great explainationGristle
H
3

The bang operator works like an assert statement but in production mode too.

Let's say, this is your function.

final void Function()? foo;

You can't call it directly

foo(); // Error

Here comes a bang operator, which actually says that Dart I take the full responsibility that this function isn't null, let me proceed with the call.

foo!(); // No error

This is essentially equal to doing:

(foo as Function())();

Note:

You will run into an error if foo was null. A good approach is to check for nullability using a local variable and proceed to the call.

final f = foo;
if (f != null) {
  f();
}
Heap answered 25/5, 2021 at 9:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.