下面这是一段我们常写出的代码,注意其中的forEach函数,大家看看它的输出是什么。
void main(List<String> arguments) {
print(Test.inList('1'));
Test.list.add('1');
print(Test.inList('1'));
}
class Test {
static var list = <String>[];
static bool inList(String template) {
list.forEach((String item) {
if (template == item) {
return true;
} else {
return false;
}
});
return false;
}
}
我们会想当然的认为第一次print是false,第二次print是true。
然而实际上的输出
false
false
这里是forEach这个函数有个坑
/**
* Applies the function [f] to each element of this collection in iteration
* order.
*/
void forEach(void f(E element)) {
for (E element in this) f(element);
}
这是forEach的实现,非常的简单。注意这里传入的函数参数 f 的返回值是void。
函数的实现里也没有对f的返回值做任何处理,毕竟人家声明的就是void——无返回值。
虽然我们在使用的时候,f的实现里面写了return true|false ,并且编译器并没有报错,但是实际上,这里的return是毫无意义的。
更不可能会把当前函数inList的运行中断掉并返回。
那么知道了这个问题,该怎么解决呢?
可以简单的使用any函数。
/**
* Checks whether any element of this iterable satisfies [test].
*
* Checks every element in iteration order, and returns `true` if
* any of them make [test] return `true`, otherwise returns false.
*/
bool any(bool test(E element)) {
for (E element in this) {
if (test(element)) return true;
}
return false;
}
any函数和forEach的使用类似, 但是处理了传入函数test的返回值。
static bool inList(String template) {
return list.any((String item) {
if (template == item) {
return true;
} else {
return false;
}
});
}
改成这样既可,注意及时是any函数,也是不能让return直接中断inList的执行并返回的,return的值是传递到any函数的返回上,然后return any函数的返回既可。
上述代码略显啰嗦,可以再优化下,用一行代码实现:
static bool inList(String template) => list.any((String item) => template == item);
再次运行,就输出了期望的结果
false
true