Bang 运算符与断言语句

Bang operator vs assert statements

在下面的代码中,我使用 bang 运算符放弃了可空性。

void main() {
  String? foo;
  foo!.toLowerCase();
}

但是当我在调用函数之前使用 assert 时,出现错误。

void main() {
  String? foo;
  assert(foo != null);
  foo.toLowerCase(); // Error
}

bang算子不也是在幕后做同样的事情吗?

注意:我不是在寻找如何让它工作的解决方案,有很多方法,甚至是流程语句,if (foo == null) return;

(添加这个答案而不是评论。)

asserts 的要点是它们可以被禁用并且不会产生任何运行时惩罚。 It's been some matter of debate,但目前的理念是,这意味着 asserts 不会执行类型提升,所以即使你这样做:

bool foo(Object object) {
  assert(object is String);

  // error: The getter 'isEmpty' isn't defined for the type 'Object' 
  return object.isEmpty;
}

出于同样的原因,assert(someLocalVariable != null) 不会将 someLocalVariable 提升为不可空类型:

bool bar(String? string) {
  assert(string != null);

  // error: The property 'isEmpty' can't be unconditionally accessed
  //        because the receiver can be null.
  return string.isEmpty;
}

从启用了空安全的 Dart 2.12 开始,您可以通过直接执行转换来获得所需的效果。如果转换失败,这将提升类型并抛出运行时异常:

bool foo(Object object) {
  object as String;
  return object.isEmpty;
}

bool bar(String? string) {
  string!;
  return string.isEmpty;
}