对象方法中的 Flutter 空安全条件

Flutter null-safety conditionals in object methods

我正在使用我的 Flutter 项目完成整个空安全模式,不确定 ?! 在调用对象方法时有什么区别。

例如,提示是添加 ! 条件。这是我现在的一个例子,我不确定这应该是 ? 还是 !findNbr!.replaceAll().

Future checkItem({String? findNbr}) async {
  int? x = int.tryParse(findNbr!.replaceAll('-', ''));

  ...

这是否意味着如果 findNbr 为空,replaceAll() 将不会 运行?

或者应该是 ?? findNbr?.replaceAll() 编辑:我刚刚注意到我不能使用 findNbr?,它告诉 String?无法分配参数字符串。

或者这是否意味着我说它不为空并且 运行 无论如何?

请注意,我还没有接近 运行 我的应用程序,所以我不知道它是否有效。但我认为在完成更多工作之前我最好知道它在做什么。我仍在转换所有内容,并且有 75-100 个 dart 文件。老实说,我不确定我明白这一切的意义,因为我只是将 ? 添加到所有内容中,所以它无论如何都可以为空。

建议大家尽量少用!运算符,也就是called bang运算符。你应该只在 dart 分析器出错并且你 100% 知道该值 never 为 null 时才使用此运算符。

下面是 dart 分析器错误的示例,您应该使用 bang 运算符。

// 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!;
}

? 运算符只是告诉 Dart 值 can 为空。所以每次你想放置一个 ? 运算符时,问问你自己,这个值可以为 null 吗?

Dart 中的空安全特性主要是为了帮助开发人员记住值 can 何时为空。 Dart 现在会简单地告诉您何时将变量设置为可空,以便强制进行空检查或默认值等。

Future checkItem({String? findNbr}) async {
  int? x = int.tryParse(findNbr!.replaceAll('-', ''));

  ...

Does this mean replaceAll() will not run if findNbr is null?

正确。如果 findNbrnull,那么 findNbr! 将抛出运行时异常。那会很糟糕,特别是因为 checkItem's function signature advertises that findNbr is allowed to be null, and therefore it would violate callers' 期望。

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.

您不能使用 findNbr?.replaceAll(...),因为如果 findNbrnull,那么它将调用 int.tryParse(null),但不允许 int.tryParse接受一个 null 的论点。

您需要做的是 个:

  • 使findNbr不再可选:

    Future checkItem({required String findNbr}) async {
      int? x = int.tryParse(findNbr.replaceAll('-', ''));
      ...
    
  • 允许 findNbr 是可选的但具有非空默认值:

    Future checkItem({String findNbr = ''}) async {
      int? x = int.tryParse(findNbr.replaceAll('-', ''));
      ...
    
  • 允许 findNbr 是可选的,但明确决定如果它为 null 时要做什么。例如:

    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.

如果您盲目地将 ? 添加到所有类型并将 ! 添加到所有变量,那么是的,null-safety 将毫无意义:这样做会给您带来与 Dart before null 相同的行为-安全。

空安全的要点是防止 不应该 成为 null 的事物成为 null。您以前可能已经编写过这样的代码,但是 没有空安全,这意味着执行 runtime null 检查 (例如 assert(x != null);if (x != null) { ... },或者如果 null 在不希望的地方使用,则依靠空指针异常使程序崩溃)。 空安全意味着现在可以通过静态分析构建时完成此类检查,这意味着可以更早更彻底地发现错误.此外,虽然以前的函数需要明确记录参数和 return 值是否被允许为 null(并且不充分或不正确的文档可能是错误的来源),但现在它们是自我记录的看待。就像使用 int foo(String s)dynamic foo(dynamic s) 一样;使用强类型可以更早地捕获错误并更好地描述函数的契约。

如果您还没有读过,我建议您阅读 Understanding Null Safety