在启用了null安全的情况下,如何从Iterable.first中的orElse返回null



在空安全镖之前,以下是有效语法:

final list = [1, 2, 3];
final x = list.firstWhere((element) => element > 3, orElse: () => null);
if (x == null) {
// do stuff...
}

现在,firstWhere需要orElse返回int,而不是int?,因此我不能返回null。

如何从orElse返回null?

一个方便的函数firstWhereOrNull解决了这个确切的问题。

导入package:collection,其中包括对Iterable的扩展方法。

import 'package:collection/collection.dart';
final list = [1, 2, 3];
final x = list.firstWhereOrNull((element) => element > 3);
if (x == null) {
// do stuff...
}

您不需要外部包,而是可以使用try/catch

int? x;
try {
x = list.firstWhere((element) => element > 3);
} catch(e) {
x = null;
}

要添加到@Alex Hartfords的答案中,对于那些不想仅为此功能导入完整包的人来说,这是您可以添加到应用程序的collection包中的firstWhereOrNull的实际实现。

extension FirstWhereExt<T> on List<T> {
/// The first element satisfying [test], or `null` if there are none.
T? firstWhereOrNull(bool Function(T element) test) {
for (final element in this) {
if (test(element)) return element;
}
return null;
}
}

有点晚了,但我想到了这个:


typedef FirstWhereClosure = bool Function(dynamic);
extension FirstWhere on List {
dynamic frstWhere(FirstWhereClosure closure) {
int index = this.indexWhere(closure);
if (index != -1) {
return this[index];
}
return null;
}
}

示例用法:

class Test{
String name;
int code;

Test(code, this.name);
}
Test? test = list.frstWhere(t)=> t.code==123);

另一种选择是将可为null的类型设置为列表。

您编写的不是[1, 2, 3],而是<int?>[1, 2, 3],使其可以为null

void main() {
final list = <int?>[1, 2, 3];
final x = list.firstWhere(
(element) => element != null ? (element > 3) : false,
orElse: () => null);
print(x);
}

这应该有效,而且是一个更好的解决方案:


extension IterableExtensions<T> on Iterable<T> {
T? firstWhereOrNull(bool Function(T element) comparator) {
try {
return firstWhere(comparator);
} on StateError catch (_) {
return null;
}
}
}

最新更新