【问题标题】:How does the null check operator work in DartDart 中的 null 检查运算符如何工作
【发布时间】:2022-06-17 06:09:42
【问题描述】:

我正在使用 this 存储库来熟悉 Amazon 的 Cognito 用户系统。在文件 lib/screens/signup_screen.dart 中,从第 27 行开始有这段代码:

          TextFormField(
            keyboardType: TextInputType.emailAddress,
            decoration: InputDecoration(labelText: "Email"),
            controller: _emailController,
            validator: (value) =>
                !validateEmail(value) ? "Email is Invalid" : null,
          ),

但是,由于我们在 Dart 2.x 版本中具有空安全性,因此这段代码失败并显示错误消息:The argument type 'String?' can't be assigned to the parameter type 'String'

我从中得到的是 value 可能不等于 null 并且代码不能保证它是这样的。如果我错了,请纠正我,我也希望有人能向我解释为什么代码不能保证这里的空安全性。如果文本字段为空,value 应该等于 "" 而不是 null

无论如何,我决定使用三元运算符来解决这个问题:

!validateEmail(value == null ? "" : value) ? ...

IDE 建议我更正:

!validateEmail(value ?? "") ? ...

Dart 还建议插入一个空检查作为另一种选择:

!validateEmail(value!) ? ....

到目前为止,我只是将这些修复作为一种解决方法来快速生成代码,而无需尝试了解实际发生的情况。

那么这些方法有什么区别呢?第二种方法中的??是否集成了== null检查,和写value == null ? "" : value完全一样吗?

另外,nullcheck value! 有什么作用?是的,它会检查 value 是否等于 null,但是当 value 实际上等于 null 时,它对我有什么作用?

【问题讨论】:

    标签: dart null


    【解决方案1】:

    ?? 是一个可识别 null 的运算符,它返回左侧的表达式,除非该表达式的值为 null,在这种情况下,它会计算并返回右侧的表达式:

    print(1 ?? 3); // <-- Prints 1.
    print(null ?? 12); // <-- Prints 12.
    

    这与做三元运算符相同,但更具可读性。

    bang 运算符! 抛弃了变量的可空性,这意味着您明确地说该值不能是null

    当然,就像任何演员一样,使用 !伴随着静态安全的损失。 必须在运行时检查演员表以保持健全性,并且可能 失败并抛出异常。

    如需进一步阅读,请查看documentation

    【讨论】:

    • 您好,非常感谢您的超快速回复。关于??的部分我现在清楚了,谢谢。但假设我有一个变量 value 等于 null。当我写value! 时,我说它不能为空,但实际上它是。然后会发生什么?
    • 它将失败并出现异常,null aware operator used on null value
    【解决方案2】:

    您可以在此处开始了解有关 Dart 中声音 null 安全性的更多信息:Understanding Null Safety

    空断言value! 等于强制转换为不可为空的类型:value as String。如果value 为空,则会引发异常。

    条件 ?? 运算符的作用与您的预期一样:value ?? ""value != null ? value : "" 的简写形式

    【讨论】:

      【解决方案3】:

      我从中得到的是 value 可能不等于 null 并且代码不能保证原样。

      value 可能null,但validateEmail要求它的参数不是null

      可以向我解释为什么这里的代码不能保证空值安全。如果 textfield 为空,则值应等于 "" 而不是 null

      因为这是TextFormField's constructor 指定的。它的validator 参数被声明为FormFieldValidator&lt;String&gt;?FormFieldValidator&lt;T&gt; 被定义为String? Function(T? value)。换句话说,validator 回调被声明为一个必须接受null 作为参数的函数。编译器没有语义知识来知道TextFormField 在实践中是否会使用null 而不是空字符串来调用该回调。

      那么这些方法有什么区别呢?第二种方法中的??是否集成了== null检查,和写value == null ? "" : value完全一样吗?

      ?? 是 Dart 的 null-aware 运算符之一;它会自动为您检查nullAs stated in the Dart Language Tour:

      expr1 ?? expr2

      如果 expr1 不为空,则返回其值;否则,计算并返回 expr2 的值。

      所以是的,它相当于expr1 == null ? expr2 : expr1(除了?? 只会评估expr1 一次,如果评估有副作用,这很重要)。无论如何,您应该更喜欢??,因为它可以更好地传达意图。

      另外,nullcheck value! 有什么作用?是的,它检查 value 是否等于 null,但是当 value 实际上等于 null 时,它对我有什么作用?

      如果value 在运行时变成null

      value!抛出异常(特别是TypeError)。不要使用!,除非您可以在逻辑上保证value 不会是null

      【讨论】:

      • 啊,我明白了,所以在这里使用value ?? "" 是最安全的选择。
      猜你喜欢
      • 2015-01-20
      • 2022-01-11
      • 1970-01-01
      • 2021-06-03
      • 2014-08-10
      • 2021-12-12
      • 2021-04-13
      • 2022-08-02
      • 1970-01-01
      相关资源
      最近更新 更多