在 nullsafety.dartpad.dev如果我编写以下代码:
void main() {
String? name = 'Bob';
print(name.length);
}
我收到以下编译时错误:An expression whose value can be 'null' must be null-checked before it can be dereferenced
以及以下运行时错误:
Property 'length' cannot be accessed on 'String?' because it is potentially null.
Type promotion on null checks文档说:
The language is also smarter about what kinds of expressions cause promotion. An explicit
== null
or!= null
of course works. But explicit casts usingas
, or assignments, or the postfix!
operator we’ll get to soon also cause promotion. The general goal is that if the code is dynamically correct and it’s reasonable to figure that out statically, the analysis should be clever enough to do so.
题
没有办法
name
在上面的代码中可能为空。该文档还说分配应该导致类型提升。我误解了类型提升还是 DartPad 中的错误?澄清
由于几个答案为错误消息提供了解决方法,我应该澄清我不是在尝试解决上面的编码问题。相反,我是说我认为代码应该按原样工作。但事实并非如此。为什么不?
最佳答案
此答案是对添加到原始问题的赏金的回应。赏金内容如下:
Please explain how
String?
is different fromString
and how type promotion works in Dart.
字符串? VS 字符串
型号
String?
可以包含字符串或 null
.这里有些例子:String? string1 = 'Hello world';
String? string2 = 'I ❤️ Dart';
String? string3 = '';
String? string4 = null;
另一方面,String 类型只能包含字符串(一旦空安全是 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
.类型提升的工作原理
如果编译器可以从逻辑上确定可空类型(如
String?
)永远不会是 null
,然后它将类型转换(或提升)为其不可为空的对应物(如 String
)。这是一个正确的例子:
void printNameLength(String? name) {
if (name == null) {
return;
}
print(name.length);
}
虽然参数name
可以为空,如果它实际上是 null
然后函数提前返回。当您到达 name.length
时,编译器肯定知道 name
不能是 null
.所以编译器从 String?
提升 name至 String
.表达式 name.length
永远不会导致崩溃。一个类似的例子在这里:
String? name;
name = 'Bob';
print(name.length);
虽然 name
这里也可以为空,字符串文字 'Bob'
显然是非空的。这也会导致 name
被提升为不可为空的 String
.最初的问题是关于以下内容:
String? name = 'Bob';
print(name.length);
似乎这也应该将 name 提升为不可为空的 String
,但它没有。正如@lrn(Google 工程师)在 comments 中指出的那样,但是,这是一个错误,当空安全出现时,这也将像前面的示例一样工作。即,name
将被提升为不可为空的 String
.进一步阅读
关于dart - 分配非空值文字时的空安全类型提升,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63531488/