“操作符不能被无条件调用,因为接收者可以为空";迁移到 Dart 空安全后出错 [英] "The operator can’t be unconditionally invoked because the receiver can be null" error after migrating to Dart null-safety
问题描述
我正在升级一个基于 Flutter 框架的个人包.我注意到这里在 Flutter Text 小部件源代码中,有一个空检查:
if (textSpan != null) {properties.add(textSpan!.toDiagnosticsNode(name: 'textSpan', style: DiagnosticsTreeStyle.transition));}
然而,textSpan!
仍在使用 !
运算符.不应该将 textSpan
提升为不可为 null 的类型而不必使用 !
运算符吗?但是,尝试删除运算符会出现以下错误:
值可以为空"的表达式必须先进行空检查,然后才能取消引用.尝试在取消引用之前检查该值是否为空".
这是一个独立的例子:
class MyClass {细绳?_myString;字符串获取 myString {如果(_myString == null){返回 '';}返回_myString;//<-- 此处出错}}
我收到一个编译时错误:
<块引用>错误:'String?' 类型的值无法从函数myString"返回,因为它的返回类型为String".
或者,如果我尝试获取 _mySting.length
,我会收到以下错误:
无法无条件访问属性length",因为接收者可以为null".
我认为进行 null 检查会将 _myString
提升为不可为 null 的类型.为什么不呢?
我的问题已在 GitHub 上解决,因此我将在下面发布答案.
Dart 工程师 Erik Ernst 在 GitHub 上说:
<块引用>类型提升只适用于局部变量.... 实例变量的提升是不合理的,因为它可能被 getter 覆盖,该 getter 运行计算并在每次调用时返回不同的对象.参见dart-lang/language#1188 讨论类似于类型的机制推广但基于动态检查,并提供一些相关讨论的链接.
所以本地类型推广有效:
String myMethod(String? myString) {如果(myString == null){返回 '';}返回我的字符串;}
但是实例变量不提升.为此,您需要使用 !
运算符手动告诉 Dart 在这种情况下您确定实例变量不为空:
class MyClass {细绳?_myString;字符串 myMethod() {如果(_myString == null){返回 '';}返回 _myString!;}}
I'm upgrading a personal package that is based on the Flutter framework. I noticed here in the Flutter Text widget source code that there is a null check:
if (textSpan != null) {
properties.add(textSpan!.toDiagnosticsNode(name: 'textSpan', style: DiagnosticsTreeStyle.transition));
}
However, textSpan!
is still using the !
operator. Shouldn't textSpan
be promoted to a non-nullable type without having to use the !
operator? However, trying to remove the operator gives the following error:
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.
Here is a self-contained example:
class MyClass {
String? _myString;
String get myString {
if (_myString == null) {
return '';
}
return _myString; // <-- error here
}
}
I get a compile-time error:
Error: A value of type 'String?' can't be returned from function 'myString' because it has a return type of 'String'.
Or if I try to get _mySting.length
I get the following error:
The property 'length' can't be unconditionally accessed because the receiver can be 'null'.
I thought doing the null check would promote _myString
to a non-nullable type. Why doesn't it?
My question was solved on GitHub so I'm posting an answer below.
Dart engineer Erik Ernst says on GitHub:
Type promotion is only applicable to local variables. ... Promotion of an instance variable is not sound, because it could be overridden by a getter that runs a computation and returns a different object each time it is invoked. Cf. dart-lang/language#1188 for discussions about a mechanism which is similar to type promotion but based on dynamic checks, with some links to related discussions.
So local type promotion works:
String myMethod(String? myString) {
if (myString == null) {
return '';
}
return myString;
}
But instance variables don't promote. For that you need to manually tell Dart that you are sure that the instance variable isn't null in this case by using the !
operator:
class MyClass {
String? _myString;
String myMethod() {
if (_myString == null) {
return '';
}
return _myString!;
}
}
这篇关于“操作符不能被无条件调用,因为接收者可以为空";迁移到 Dart 空安全后出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!