代码之家  ›  专栏  ›  技术社区  ›  Suragch Shmidt

赋值非空值文字时的空安全类型提升

  •  0
  • Suragch Shmidt  · 技术社区  · 5 年前

    nullsafety.dartpad.dev

    void main() {
      String? name = 'Bob';
      print(name.length);
    }
    

    以及以下运行时错误:

    无法对“String?”访问属性“length”,因为它可能为空。

    这个 Type promotion on null checks

    对于什么样的表达方式能引起升职,这种语言也更聪明。明确的 == null != null 当然有用。但是使用 as , 或任务 ! 运营商很快也会得到提升。一般目标是,如果代码在动态上是正确的,并且在静态上是合理的,那么分析应该足够聪明。

    问题

    没有可能的办法 name 在上面的代码中可以为null。文件还说,作业应该引起类型提升。我是误解了类型升级还是这是达特帕德的一个错误?

    澄清

    0 回复  |  直到 5 年前
        1
  •  2
  •   Suragch Shmidt    5 年前

    这个答案是对原问题中增加的悬赏的回应。赏金上写着:

    请解释一下怎么做 String? 不同于 String 在达特推广工作。

    字符串?vs字符串

    类型 null . 以下是一些示例:

    String? string1 = 'Hello world';
    String? string2 = 'I ❤️ Dart';
    String? string3 = '';
    String? string4 = null;
    

    无效的

    String string1 = 'Hello world';
    String string2 = 'I ❤️ Dart';
    String string3 = '';
    

    如果您尝试执行以下操作:

    String string4 = null;
    

    您将得到编译时错误:

    A value of type 'Null' can't be assigned to a variable of type 'String'.
    

    这个 字符串 类型不能是 无效的 任何可能是 int 喜欢 3 bool 喜欢 true ,保证变量永远不会 无效的 .

    类型推广工作原理

    如果编译器可以逻辑地确定一个可为null的类型(如 字符串? ,然后将类型转换(或提升)为其不可为null的对应类型(如 字符串 ).

    下面是一个这样的例子:

    void printNameLength(String? name) {
      if (name == null) {
        return;
      }
      print(name.length);
    }
    

    name 是可空的,如果它真的是 然后函数提前返回。当你到达的时候 name.length 名称 不能是 字符串? 字符串 名称.长度 不会引起车祸的。

    String? name;
    name = 'Bob';
    print(name.length);
    

    尽管 这里也可以为null,字符串文本 'Bob' 显然是非空的。这也会导致 名称 字符串 .

    String? name = 'Bob';
    print(name.length);
    

    字符串 ,但事实并非如此。正如@lrn(谷歌工程师)在 comments ,不过,这是一个bug,当出现null safety时,它也会像前面的示例一样工作。也就是说, 名称 将升级为不可为空的

    进一步阅读

        2
  •  0
  •   Calleb Developer    5 年前

    既然你已经声明了变量 name 作为一个在代码的某个点可以为null的字符串,当您使用它时,您必须检查它是否为null并安全地调用它。 可以使用变量 名称 通过以下两种方式安全:

    1追加(?)到变量

    当您确定变量不为null时,您可以使用/调用它,只需附加一个 ? 在上面。

    void main() {
          String? name = 'Bob';
          print(name?.length);
        }
    

    2追加(!)到变量

    ! 到变量 名称

    void main() {
      String? name = 'Bob';
      print(name!.length);
    }
    

    为了避免变量 名称 如果为空,则必须先验证它的可空性,然后才能安全地使用它。

    void main() {
      String? name = 'Bob';
     
      if (name != null) {
         print(name!.length);
      }
    }
    
        3
  •  0
  •   Suragch Shmidt    5 年前

    enter image description here

    为了使类型升级工作,您必须首先确认该值不是如文档所述的null。

    但是如果在if语句之外使用它而不事先检查它是否为null,dart知道它随时都可以被赋值为null。这就是为什么它总是鼓励检查它是否为空。因为任何设定的变量(赋值的变量)都可以赋值 无效的