如何修复“运算符'{0}"不能无条件调用,因为接收者可以为"null". [英] How to fix "The operator ‘{0}’ can’t be unconditionally invoked because the receiver can be ‘null’"

查看:168
本文介绍了如何修复“运算符'{0}"不能无条件调用,因为接收者可以为"null".的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试 Dart 无声安全时,我遇到了一个问题:

While trying Dart's Sound Null Safety i came up with a problem:

创建一个新的 Flutter 项目,我发现了以下(非常熟悉的)片段代码

Creating a new Flutter project i found the following (and very familiar) piece code

int _counter = 0;

void _incrementCounter() {
  setState(() {
    // This call to setState tells the Flutter framework that something has
    // changed in this State, which causes it to rerun the build method below
    // so that the display can reflect the updated values. If we changed
    // _counter without calling setState(), then the build method would not be
    // called again, and so nothing would appear to happen.
    _counter++;
  });
}

现在,我将变量 _counter 更改为 nullable 并开始初始化:

Now, i changed the variable _counter to be nullable and took off the initialization:

int? _counter;

void _incrementCounter() {
  setState(() {
    _counter++;
  });
}

和预期的一样,我在编辑器中遇到以下错误:

And as expected, i got the following error in the editor:

不能无条件地调用运算符"+",因为接收者可以为"null"

The operator ‘+’ can’t be unconditionally invoked because the receiver can be 'null'

问题

文档之后,我添加了必需的检查:

The Problem

Following the documentation i added the required checking:

if (_counter!=null)
        _counter++;

但令我惊讶的是,错误不断出现并提示

but to my astonishment, the error kept on showing and suggesting

尝试使呼叫成为条件呼叫(使用'?'或向目标('!')添加空检查)

Try making the call conditional (using '?' or adding a null check to the target ('!'))

即使我明确地有条件地拨打电话 ...所以怎么了?

even though i explicitly am making the call conditionally... so what is wrong?

推荐答案

UPDATE

@suragch友善地告诉我,这个问题已经答案在SO 中.在其他SO线程中,在Github中引用了另一个线程,埃里克·恩斯特(Erik Ernst)说:

UPDATE

@suragch kindly let me know that this question had already an answer in SO. In that other SO thread a further thread in Github is referenced, where Erik Ernst says:

类型提升仅适用于局部变量...实例变量的提升不是合理的,因为它可能被运行计算的getter覆盖,并在每次调用它时返回一个不同的对象.cf. dart-lang/language#1188 讨论类似于以下内容的机制类型升级,但基于动态检查,并带有相关讨论的一些链接.

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, with that explanation, now i see that only local variables can (so far?) be promoted, and thus my problem could be fixed by writing

int? _counter;

void _incrementCounter() {
  setState(() {
    if (_counter!=null)
        _counter = _counter! + 1;
  });
}

有关其他解决方法,请参见下面的原始答案.

For an alternative fix, see my original answer below.

我最终通过如下方法捕获实例变量的值来解决该问题:

I finally fixed the problem by capturing the value of the instance variable inside the method as follows:

int? _counter;

void _incrementCounter() {
  setState(() {
    var c = _counter;

    if (c!=null)
      c++;

    _counter = c;
      
  });
}

为什么需要捕获变量?

嗯,整个问题是

类型提升仅适用于局部变量...实例变量的提升并不合理,因为它可能被运行计算的getter覆盖,并在每次调用它时返回一个不同的对象

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

所以在我的方法中,我们

so in my approach we

  • 捕获实例变量的值
  • 然后我们检查那个 是否不为空.
  • 如果该值不为null,则我们对局部变量进行操作,该局部变量现在可以通过null检查正确地推广.
  • 最后,我们将新值应用于实例变量.
  • capture the value of the instance variable
  • then we check for that value to not be null.
  • if that value turned out not to be null then we operate on the local variable which through the null check is now correctly promoted.
  • finally we apply the new value to the instance variable.

我是 Dart 的新手,所以我不确定我要写什么,但是在我看来,一般在使用可为空的instace时变量,我的方法比使用bang运算符消除无效性更好:

I am new to Dart, so i am not sure about what i am about to write, but to me it seems that in general, when working with nullable instace variables, my approach is better that that of using the bang operator to cast away nullity:

通过消除无效性,您可以忽略推广实例变量的主要问题,即

By casting away nullity you are overlooking the main problem of promoting instance variables, namely that

它可能被运行计算的getter覆盖,并在每次调用它时返回一个不同的对象...

it could be overridden by a getter that runs a computation and returns a different object each time it is invoked ...

确切的问题是通过捕获实例变量的值并使用那个本地捕获的值来避免的...

That exact problem is what is avoided by capturing the value of the instance variable and working with that locally captured value...

如果我错了,请告诉我...

If i am wrong kindly let me know...

这篇关于如何修复“运算符'{0}"不能无条件调用,因为接收者可以为"null".的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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