forEach与forin:调用方法时的不同行为
我注意到了这一点,forEach并for in产生了不同的行为。我有一个列表,RegExp并希望hasMatch在每个列表上运行。使用 遍历列表时forEach,hasMatch永远不会返回 true。但是,如果我使用for in,则hasMatch返回 true。
示例代码:
class Foo {
final str = "Hello";
final regexes = [new RegExp(r"(w+)")];
String a() {
regexes.forEach((RegExp reg) {
if (reg.hasMatch(str)) {
return 'match';
}
});
return 'no match';
}
String b() {
for (RegExp reg in regexes) {
if (reg.hasMatch(str)) {
return 'match';
}
}
return 'no match';
}
}
void main() {
Foo foo = new Foo();
print(foo.a()); // prints "no match"
print(foo.b()); // prints "match"
}
(带有上述示例代码的 DartPad)
方法a和之间的唯一区别b是a使用forEach和b使用for in,但它们产生不同的结果。为什么是这样?
回答
尽管有prefer_foreachlint,但该建议专门用于可以将其与撕下(对现有函数的引用)一起使用的情况。Effective Dart建议不要Iterable.forEach与其他任何东西一起使用,并且有相应的avoid_function_literals_in_foreach_callslint来强制执行它。
除了回调是撕裂的那些简单情况外,Iterable.forEach并不比使用基本和更通用的for循环更简单。使用 存在更多陷阱Iterable.forEach,这就是其中之一。
-
Iterable.forEach是一个将回调作为参数的函数。Iterable.forEach不是控制结构,回调是普通函数。因此,您不能使用break来提前停止迭代或使用continue跳到下一次迭代。 -
return回调中的语句从 callback返回,返回值被忽略。的调用者Iterable.forEach永远不会收到返回的值,也永远不会有机会传播它。例如,在:bool f(List<int> list) { for (var i in list) { if (i == 42) { return true; } } return false; }该
return true语句从函数返回f并停止迭代。相反,与forEach:bool g(List<int> list) { list.forEach((i) { if (i == 42) { return true; } }); return false; }该
return true语句仅从回调返回。在g完成所有迭代并到达最后的return false语句之前,该函数不会返回。这也许更清楚:bool callback(int i) { if (i == 42) { return true; } } bool g(List<int> list) { list.forEach(callback); return false; }这使得更明显的是:
- 没有办法
callback导致g返回true。 callback不会沿所有路径返回值。
(这就是你遇到的问题。)
- 没有办法
-
Iterable.forEach不得与异步回调一起使用。因为回调返回的任何值都被忽略,所以永远不能等待异步回调。
我还应该指出,如果您启用 Dart 的新空安全功能,它启用更严格的类型检查,您的forEach代码将生成一个错误,因为它在预期具有void返回值的回调中返回一个值。