dart 镖空/假/空检查:这个怎么写短一点?

mklgxw1f  于 2022-12-16  发布在  其他
关注(0)|答案(9)|浏览(122)

这是我的代码,除了空字符串、null和false之外,其他都为true:

if (routeinfo["no_route"] == "" || routeinfo["no_route"] == null || routeinfo["no_route"] == false) {
    // do sth ...
}

这是我的代码,除了空字符串、null、false或zero之外,其他都为true:

if (routeinfo["no_route"] == "" || routeinfo["no_route"] == null || routeinfo["no_route"] == false || routeinfo["no_route"] == 0) {
    // do sth...
}

我怎样才能用 dart 把它写得更短呢?还是不可能?

kkih6yb8

kkih6yb81#

如果您的要求只是空的或null(就像我在搜索结果中看到这个标题时一样),您可以使用Dart的安全导航操作符使它更简洁一些:

if (routeinfo["no_route"]?.isEmpty ?? true) {
  // 
}

地点

  • isEmpty检查空字符串,但如果routeinfo是null,则不能对null调用isEmpty,因此我们使用以下语句检查null
  • ?.safe navigation operator,它只在对象不为空时调用isEmpty,否则生成null。
  • ??null coalescing operator的一个或多个

如果你的map是一个可以为空的类型,那么你必须安全地导航:

if (routeinfo?["no_route"]?.isEmpty ?? true) {
  //
}

ct2axkht

ct2axkht2#

你可以

if (["", null, false, 0].contains(routeinfo["no_route"])) {
  // do sth
}
uidvcgyl

uidvcgyl3#

2020年末更新

总结

  • 除了isNullisNotNull之外,这个答案是正确的,当Null Safety将来在dart/flutter中引入时,它们不再提供类型提升。
  • 其他helper(如isNullOrEmpty)不提供类型提升,因为与callsite相比,它们位于不同的(子)作用域中。
  • 我个人的意见是,你可以放弃isNullisNotNull,但保留其他助手,因为你不应该期望他们为你做类型提升。

解释

演示

下面演示了为什么isNull== null)和isNotNull!= null)的封装/helper-getter是一个非常大的问题:

// Promotion works
int definitelyInt(int? aNullableInt) {
  if (aNullableInt == null) { // Promote variable `aNullableInt` of Nullable type `int?` to Non-Nullable type `int`
    return 0;
  }
  return aNullableInt; // Can't be null! This variable is promoted to non-nullable type `int`
}

当您使用的dart版本中包含“Null Safety”时,上述代码中的类型提升有效!

// Promotion does NOT work!!!
int definitelyInt(int? aNullableInt) {
  if (aNullableInt.isNull) { // does NOT promote variable `aNullableInt` of Nullable type `int?`
    return 0;
  }
  return aNullableInt; // This variable is still of type `int?`!!!
}

上面的方法不起作用,因为空校验== null!= null封装在子作用域(不同的堆栈帧)中,并且在definitelyInt作用域中不被推断为具有这种“提升”效果。

2020年初更新

下面是一个修改后的版本,它使用getters代替了示例/类方法,并覆盖了空格isNullisNotNull

第二次更新

现在它也可以解释空列表和Map了!

第三次更新

为安全性和模块化/可维护性添加了私有getter。

第四次更新

更新了答案以修复Map的一个特定问题,当为空时无法正确处理!因为Map不是Iterable。通过引入_isMapObjectEmpty U解决了此问题
溶液

extension TextUtilsStringExtension on String {
  /// Returns true if string is:
  /// - null
  /// - empty
  /// - whitespace string.
  ///
  /// Characters considered "whitespace" are listed [here](https://stackoverflow.com/a/59826129/10830091).
  bool get isNullEmptyOrWhitespace =>
      this == null || this.isEmpty || this.trim().isEmpty;
}

/// - [isNullOrEmpty], [isNullEmptyOrFalse], [isNullEmptyZeroOrFalse] are from [this StackOverflow answer](https://stackoverflow.com/a/59826129/10830091)
extension GeneralUtilsObjectExtension on Object {
  /// Returns true if object is:
  /// - null `Object`
  bool get isNull => this == null;

  /// Returns true if object is NOT:
  /// - null `Object`
  bool get isNotNull => this != null;

  /// Returns true if object is:
  /// - null `Object`
  /// - empty `String`s
  /// - empty `Iterable` (list, set, ...)
  /// - empty `Map`
  bool get isNullOrEmpty =>
      isNull ||
      _isStringObjectEmpty ||
      _isIterableObjectEmpty ||
      _isMapObjectEmpty;

  /// Returns true if object is:
  /// - null `Object`
  /// - empty `String`
  /// - empty `Iterable` (list, map, set, ...)
  /// - false `bool`
  bool get isNullEmptyOrFalse =>
      isNull ||
      _isStringObjectEmpty ||
      _isIterableObjectEmpty ||
      _isMapObjectEmpty ||
      _isBoolObjectFalse;

  /// Returns true if object is:
  /// - null `Object`
  /// - empty `String`
  /// - empty `Iterable` (list, map, set, ...)
  /// - false `bool`
  /// - zero `num`
  bool get isNullEmptyFalseOrZero =>
      isNull ||
      _isStringObjectEmpty ||
      _isIterableObjectEmpty ||
      _isMapObjectEmpty ||
      _isBoolObjectFalse ||
      _isNumObjectZero;

  // ------- PRIVATE EXTENSION HELPERS -------
  /// **Private helper**
  ///
  /// If `String` object, return String's method `isEmpty`
  ///
  /// Otherwise return `false` to not affect logical-OR expression. As `false` denotes undefined or N/A since object is not `String`
  bool get _isStringObjectEmpty =>
      (this is String) ? (this as String).isEmpty : false;

  /// **Private helper**
  ///
  /// If `Iterable` object, return Iterable's method `isEmpty`
  ///
  /// Otherwise return `false` to not affect logical-OR expression. As `false` denotes undefined or N/A since object is not `Iterable`
  bool get _isIterableObjectEmpty =>
      (this is Iterable) ? (this as Iterable).isEmpty : false;

  /// **Private helper**
  ///
  /// If `Map` object, return Map's method `isEmpty`
  ///
  /// Otherwise return `false` to not affect logical-OR expression. As `false` denotes undefined or N/A since object is not `Map`
  bool get _isMapObjectEmpty => (this is Map) ? (this as Map).isEmpty : false;

  /// **Private helper**
  ///
  /// If `bool` object, return `isFalse` expression
  ///
  /// Otherwise return `false` to not affect logical-OR expression. As `false` denotes undefined or N/A since object is not `bool`
  bool get _isBoolObjectFalse =>
      (this is bool) ? (this as bool) == false : false;

  /// **Private helper**
  ///
  /// If `num` object, return `isZero` expression
  ///
  /// Otherwise return `false` to not affect logical-OR expression. As `false` denotes undefined or N/A since object is not `num`
  bool get _isNumObjectZero => (this is num) ? (this as num) == 0 : false;
}

假设

这假定Dart 2.7或更高版本支持Extension Methods

用法

以上是两个扩展类。一个用于Object,另一个用于String。将它们分别/一起放在一个文件中,并在callsite文件中导入文件/file。

描述

来自Swift,我倾向于使用像user @Benjamin Menrad的answer这样的扩展,但在适用的情况下使用getter而不是方法/函数--镜像Dart的计算属性,如String.isEmpty
来自C#,我喜欢他们的字符串的助手方法IsNullOrWhiteSpace
我的版本融合了上述两个概念。

命名

你可以随意重命名扩展类,我倾向于这样命名它们:

XY延伸导线

其中:

*X是文件/作者/应用程序/唯一名称。
*Y是正在扩展的类型的名称。

名称示例:

  • MyAppIntExtension
  • DartDoubleExtension
  • TextUtilsStringExtension
  • OHProviderExtension

批评

为什么使用私有getter而不是简单的this == null || this == '' || this == [] || this == 0 || !this

  • 我认为这是更安全的,因为它首先将对象强制转换为我们要与之进行值比较的正确类型。
  • 更加模块化,因为更改集中在私有getter中,任何修改都反映在各处。
  • 如果类型检查在私有getter中失败,我们返回false,这不会影响根逻辑OR表达式的结果。
iibxawm4

iibxawm44#

我会编写一个帮助函数,而不是内联所有内容。

bool isNullEmptyOrFalse(Object o) =>
  o == null || false == o || "" == o;

bool isNullEmptyFalseOrZero(Object o) =>
  o == null || false == o || 0 == o || "" == o;

这避免了重复查找(如contains操作),但可读性更强,而且不会为每次检查创建新的List文本(使列表常量化可以解决这个问题)。

if (isNullEmptyOrFalse(routeinfo["no_route"])) { ... }

当你在努力使某个函数简短易读时,创建一个名字恰当的helper函数通常是最好的解决方案。
(补充:既然Dart有了扩展方法,就可以将功能添加为对象上的方法或getter,这样就可以直接编写value.isNullOrEmpty)。

nwlqm0z1

nwlqm0z15#

由于来自Android和Kotlin,我更喜欢扩展方法而不是静态助手方法。现在在Dart 2.7中,你也可以使用扩展方法:

extension Extension on Object {
  bool isNullOrEmpty() => this == null || this == '';

  bool isNullEmptyOrFalse() => this == null || this == '' || !this;

  bool isNullEmptyZeroOrFalse() =>
      this == null || this == '' || !this || this == 0;
}

现在,您可以从代码中的任何位置调用这些方法:

if (anyVariable.isNullOrEmpty()) {
  // do something here
}

您可能需要手动导入dart类,在其中放置扩展方法,例如:

import 'package:sampleproject/utils/extensions.dart';
wljmcqd8

wljmcqd86#

具有零安全性:

比如说,你有一个可以为空的Map和一个List,其中有可以为空的值。

Map<String, List?>? map;
List<String?>? list;

要检查集合是否既不为null也不为空,可以执行以下操作:

if (map?.keys.contains('foo') ?? false) {
  print('map is not-null, and foo has a value');
}

if (list?.isNotEmpty ?? false) {
  print('list is not-null and not empty');
}
kx1ctssn

kx1ctssn7#

对于字符串,我喜欢这种方法:

extension NullableStringExtensions<E> on String? {
  /// Returns `true` if this string is `null` or empty.
  bool get isNullOrEmpty {
    return this?.isEmpty ?? true;
  }

  /// Returns `true` if this string is not `null` and not empty.
  bool get isNotNullNorEmpty {
    return this?.isNotEmpty ?? false;
  }
}

感谢本软件包的作者:https://pub.dev/packages/string_ext

csga3l58

csga3l588#

bool isNullString(String? value) {
      if (value == null || value.isEmpty ) {
        return true;
      } else {
        return false;
      }
    }

使用这种方法

isNullString(yourValue)
fhity93d

fhity93d9#

package:quiver具有isEmpty函数,如果参数为null或空字符串,则该函数返回true
自己实现这样的函数也很简单。

相关问题