我注意到了这一点,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"
}
Run Code Online (Sandbox Code Playgroud)
方法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;
}
Run Code Online (Sandbox Code Playgroud)
该return true语句从函数返回f并停止迭代。相反,与forEach:
bool g(List<int> list) {
list.forEach((i) {
if (i == 42) {
return true;
}
});
return false;
}
Run Code Online (Sandbox Code Playgroud)
该return true语句仅从回调返回。在g完成所有迭代并到达最后的return false语句之前,该函数不会返回。这也许更清楚:
bool callback(int i) {
if (i == 42) {
return true;
}
}
bool g(List<int> list) {
list.forEach(callback);
return false;
}
Run Code Online (Sandbox Code Playgroud)
这使得更明显的是:
callback导致g返回true。callback 不会沿所有路径返回值。(这就是你遇到的问题。)
Iterable.forEach不得与异步回调一起使用。因为回调返回的任何值都被忽略,所以永远不能等待异步回调。
我还应该指出,如果您启用 Dart 的新空安全功能,它启用更严格的类型检查,您的forEach代码将生成一个错误,因为它在预期具有void返回值的回调中返回一个值。
| 归档时间: |
|
| 查看次数: |
321 次 |
| 最近记录: |