如果我在nullsafety.dartpad.dev中编写以下代码:

void main() {
  String? name = 'Bob';
  print(name.length);
}
我收到以下编译时错误:

以及以下运行时错误:

Type promotion on null checks文档说:


上面的代码中name不可能为null。该文档还说,分配应该引起类型提升。我是误解类型提升还是DartPad中的错误?
澄清度
由于有两个答案为错误消息提供了解决方法,因此我应该澄清,我并不是要解决上面的编码问题。相反,我是说我认为代码应该可以正常工作。但事实并非如此。为什么不?

最佳答案

该答案是对原始问题中添加的赏金的回应。赏金如下:

串? vs StringString?类型可以包含字符串或null。这里有些例子:

String? string1 = 'Hello world';
String? string2 = 'I ❤️ Dart';
String? string3 = '';
String? string4 = null;
另一方面,String类型只能包含字符串(即,一旦null安全是Dart的一部分)。它不能包含null。这里有些例子:
String string1 = 'Hello world';
String string2 = 'I ❤️ Dart';
String string3 = '';
如果您尝试执行以下操作:
String string4 = null;
您将得到编译时错误:
A value of type 'Null' can't be assigned to a variable of type 'String'.
String类型不能是null,不能像int这样的3还是bool这样的true。这就是零安全性的全部含义。如果您有一个类型为String的变量,则可以确保该变量永远不会是null
类型推广的工作原理
如果编译器可以从逻辑上确定可为null的类型(如String?)将永远不是null,则它将编译(或提升)该类型为其不可为null的对应类型(如String)。
这是真实的一个示例:
void printNameLength(String? name) {
  if (name == null) {
    return;
  }
  print(name.length);
}
尽管参数name可为空,但如果实际上是null,则该函数会提前返回。到name.length时,编译器肯定会知道name不能是null。因此,编译器将名称从String?提升为String。表达式name.length将永远不会导致崩溃。
一个类似的例子在这里:
String? name;
name = 'Bob';
print(name.length);
尽管name在此处也是可为空的,但是字符串文字'Bob'显然非空。这也将name提升为不可空的String
最初的问题涉及以下方面:
String? name = 'Bob';
print(name.length);
似乎这也应该将名称提升为不可空的String,但事实并非如此。正如@lrn(一位Google工程师)在comments中指出的那样,这是一个错误,当出现null安全性时,它也将像前面的示例一样工作。也就是说,name将被提升为不可空的String
进一步阅读
  • Sound null safety
  • Type promotion on null checks
  • 关于dart - 分配非空值文字时的空安全类型提升,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/63531488/

    10-11 22:21
    查看更多