理解 "!" dart 中的 Bang 运算符

Understanding " ! " Bang Operator in dart

我在有状态 class 中声明了一个回调方法,例如:

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

并在状态 class 内使用 widget.onselected 调用,例如:

widget.onSelected!(_selectedIndex);

但我无法理解 ! Bang 运算符的实际用法。我无法在构造函数中初始化 widget.onSelected 而不在声明期间给出 ?

我的主要问题是“! bang 运算符如何处理空值?它有什么用?

Bang 运算符只是告诉 Dart 即使我们将某个变量定义为 Nullable 类型,它也不会 definitely 为空。

Dart 的 Nullable safetyFlow Analysis 在这里通过避免运行时错误并在编译时本身捕获它们来使开发人员的生活变得轻松。

定义时,

final void Function(int index)? onSelected;

你告诉 dart 这个变量 may or may not 被赋予了一个值,因此它可能是也可能不是 null

现在,每当您尝试像这样使用它时,

widget.onSelected()

Dart 会警告你,这是一个 Nullable 类型的变量,因此要格外小心。

如果 Dart 没有事先告诉您这一点,那么您会在 运行 应用程序并在尝试调用该函数时崩溃后意识到这一点。

现在,由于 Dart 已警告您不能那样使用它,因此有两种方法可以解决它。

  1. 在使用前进行空检查。这样我们就避免了运行时错误。

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

    创建新的局部变量是必要的,因为 Dart 的流分析仅适用于局部变量空值检查,而不适用于 class 级变量空值检查。


  1. 使用bang运算符,

     widget.onSelected!(_selectedIndex)
    

    现在的问题是,您只是向 Dart 保证它永远不会为 null,但如果它实际上为 null,它仍然会导致运行时崩溃。

因此,Bang 运算符只是一种在您必须访问可空类型变量时绕过 Dart 的 flow analysis 的方法。

希望这至少能消除您的疑虑。

bang 运算符的工作方式类似于 assert 语句,但在生产模式下也是如此。

比方说,这是你的功能。

final void Function()? foo;

不能直接调用

foo(); // Error

来个bang运算符,其实是说Dart我全权负责这个函数不是null,让我继续调用。

foo!(); // No error

这基本上等于做:

(foo as Function())();

注:

如果 foonull,您将 运行 出错。一个好的方法是使用局部变量检查可空性并继续调用。

final f = foo;
if (f != null) {
  f();
}