【问题标题】:What's better, an initially empty non-nullable or an initially nullable and null container?更好的是,最初为空的不可为空或最初可为空且为空的容器?
【发布时间】:2021-10-05 21:20:31
【问题描述】:

假设您正在管理建筑物中居民拥有的自行车序列号列表,目标是提前规划以建立更多安全的自行车存放处。

有些人当然没有自行车。

在 Dart > 2.12 (with null safety) 你可以 使用不可为空的List<String> 并将其初始化为一个空列表

class Resident {
  String name;
  List<String> bicycles = [];
}

或者您可以使用可为空的 List&lt;String&gt; 并使用 null 作为标志来表示某人没有自行车。

class Resident {
  String name;
  List<String>? bicycles;
}

这两种设计当然是可行的,但结果是哪一种明显比另一种更好——例如,对于新的 Dart 来说更惯用吗?换句话说,最初为空的不可为空的容器或最初可为空且为空的容器哪个更好?

即使我计算所需的位数,也不是很清楚。在第一种情况下构造一个空列表会浪费存储空间,但在第二种情况下也会浪费存储空间——尽管它是未知的,并且可能取决于实现——数量。

【问题讨论】:

    标签: dart dart-null-safety


    【解决方案1】:

    如果你想表示什么都没有,那么更喜欢具有空状态的不可空容器类型而不是可空类型。

    • 对于可以为空的容器,您可能需要处理容器为空的问题,现在您必须做额外的工作来检查各处的null。 同时,处理空容器通常不需要任何额外的工作。对比:
      // Nullable case.
      final bicycles = resident.bicycles;
      if (bicycles != null) {
        for (var bicycle in bicycles) {
          doSomething(bicycle);
        }
      }
      
      /// Non-nullable case.
      for (var bicycle in resident.bicycles) {
        doSomething(bicycle);
      }
      
    • 您可以尝试在容器变空时重置对null 的引用,这样就没有两种情况需要处理,但是如上所述,空的情况通常是免费的,所以这会是更多的工作因为通常没有收获。此外,重置引用可能是很多的额外工作:
      var list = [1, 2, 3];
      mutateList(list);
      if (list.isEmpty) {
        list = null;
      }
      
      如果mutateList 可以从list 中删除元素,那么每个 调用者都需要做额外的工作来将空的Lists 替换为null
    • 即使您不想用null 替换空容器,但在转换到非空容器时仍然会有不同的行为。考虑:
      var sam = Resident();
      var samsBicycles = sam.bicycles;
      sam.addBicycle();
      
      你希望samsBicycles 是什么?如果 Resident.bicycles 最初是 null,那么 samsBicycles 将保持为 null 并且不再引用与 sam.bicycles 相同的对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-19
      相关资源
      最近更新 更多