“操作符不能被无条件调用,因为接收者可以为空";迁移到 Dart 空安全后出错 [英] "The operator can’t be unconditionally invoked because the receiver can be null" error after migrating to Dart null-safety

查看:65
本文介绍了“操作符不能被无条件调用,因为接收者可以为空";迁移到 Dart 空安全后出错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在升级一个基于 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆