Sur*_*gch 18 dart type-promotion flutter dart-null-safety
我正在升级一个基于 Flutter 框架的个人包。我在 Flutter Text 小部件源代码中注意到这里有一个空检查:
if (textSpan != null) {
properties.add(textSpan!.toDiagnosticsNode(name: 'textSpan', style: DiagnosticsTreeStyle.transition));
}
Run Code Online (Sandbox Code Playgroud)
但是,textSpan!
仍然使用!
运算符。不textSpan
应该在不必使用!
运算符的情况下提升为不可为空的类型吗?但是,尝试删除运算符会出现以下错误:
Run Code Online (Sandbox Code Playgroud)An expression whose value can be 'null' must be null-checked before it can be dereferenced. Try checking that the value isn't 'null' before dereferencing it.
这是一个独立的示例:
An expression whose value can be 'null' must be null-checked before it can be dereferenced.
Try checking that the value isn't 'null' before dereferencing it.
Run Code Online (Sandbox Code Playgroud)
我收到一个编译时错误:
错误:“字符串?”类型的值 无法从函数“myString”返回,因为它的返回类型为“String”。
或者,如果我尝试获取,则会_mySting.length
出现以下错误:
不能无条件访问属性“length”,因为接收者可以为“null”。
我认为进行空检查会提升_myString
为不可空类型。为什么不呢?
我的问题在 GitHub 上得到了解决,所以我在下面发布了一个答案。
Sur*_*gch 27
Dart 工程师 Erik Ernst在 GitHub 上说:
类型提升只适用于局部变量。... 实例变量的提升是不合理的,因为它可能会被运行计算并在每次调用时返回不同对象的 getter 覆盖。参见 dart-lang/language#1188用于讨论类似于类型提升但基于动态检查的机制,以及一些相关讨论的链接。
所以本地类型推广有效:
String myMethod(String? myString) {
if (myString == null) {
return '';
}
return myString;
}
Run Code Online (Sandbox Code Playgroud)
但是实例变量不会提升。为此,您需要使用!
运算符手动告诉 Dart 在这种情况下您确定实例变量不为空:
class MyClass {
String? _myString;
String myMethod() {
if (_myString == null) {
return '';
}
return _myString!;
}
}
Run Code Online (Sandbox Code Playgroud)
Cop*_*oad 12
假设这是您的代码,您正在对实例变量进行空检查,但仍然看到错误:
class Foo {
int? i = 0;
double bar() {
if (i != null) return i.toDouble(); // <-- Error
return -1;
}
}
Run Code Online (Sandbox Code Playgroud)
方法 'toDouble' 不能无条件调用,因为接收者可以为 'null'。
您在这样的代码中看到的错误是因为Getter 没有被提升为它们的不可为空的对应物。让我们来谈谈原因。
比方说,有一个类Bar
扩展Foo
和覆盖i
变量并且不为其分配任何值(保留它null
):
class Bar extends Foo {
@override
int? i;
}
Run Code Online (Sandbox Code Playgroud)
所以,如果你能做到
print(Bar().d() * 2);
Run Code Online (Sandbox Code Playgroud)
您会遇到运行时 null 错误,这就是禁止 getter 类型提升的原因。
我们需要从int?
. 通常有3种方法可以做到这一点(更多的方法包括使用as
,is
等等)
使用局部变量(推荐)
double bar() {
var i = this.i; // <-- Use of local variable.
if (i != null) return i.toDouble();
return -1;
}
Run Code Online (Sandbox Code Playgroud)
用 ?。和 ??
double bar() {
return i?.toDouble() ?? -1; // Provide some default value.
}
Run Code Online (Sandbox Code Playgroud)
使用 Bang 运算符 (!)
只有在 100% 确定变量 ( i
) 永远不会是null
.
double bar() {
return i!.toDouble(); // <-- Bang operator in play.
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
10450 次 |
最近记录: |