问题描述
我注意到 forEach
和 for in
会产生不同的行为.我有一个 RegExp
列表,并希望在每个列表上运行 hasMatch
.当使用 forEach
遍历列表时,hasMatch
永远不会返回 true.但是,如果我使用 for in
,hasMatch
返回 true.
I noticed that forEach
and for in
to produce different behavior. I have a list of RegExp
and want to run hasMatch
on each one. When iterating through the list using forEach
, hasMatch
never returns true. However, if I use for in
, hasMatch
returns 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"
}
a
和 b
方法的唯一区别是 a
使用 forEach
和 b
使用 for in
,但它们产生不同的结果.这是为什么?
The only difference between the methods a
and b
is that a
uses forEach
and b
uses for in
, yet they produce different results. Why is this?
推荐答案
虽然有一个 prefer_foreach
lint,该建议专门用于可以将其与撕下(对现有函数的引用)一起使用的情况.有效的 Dart 推荐 反对使用Iterable.forEach
和其他任何东西,并且有相应的avoid_function_literals_in_foreach_calls
lint 来强制执行.
Although there is a prefer_foreach
lint, that recommendation is specifically for cases where you can use it with a tear-off (a reference to an existing function). Effective Dart recommends against using Iterable.forEach
with anything else, and there is a corresponding avoid_function_literals_in_foreach_calls
lint to enforce it.
除了回调是撕掉的那些简单情况外,Iterable.forEach
并不比使用基本和更通用的 for
循环更简单.使用 Iterable.forEach
有更多的陷阱,这就是其中之一.
Except for those simple cases where the callback is a tear-off, Iterable.forEach
is not any simpler than using a basic and more general for
loop. There are more pitfalls using Iterable.forEach
, and this is one of them.
Iterable.forEach
是一个将 回调 作为参数的函数.Iterable.forEach
不是控制结构,回调是普通函数.因此,您不能使用break
提前停止迭代或使用continue
跳到下一次迭代.
Iterable.forEach
is a function that takes a callback as an argument.Iterable.forEach
is not a control structure, and the callback is an ordinary function. You therefore cannot usebreak
to stop iterating early or usecontinue
to skip to the next iteration.
回调中的return
语句从回调中返回,返回值被忽略.Iterable.forEach
的调用者永远不会收到返回的值,也永远不会有机会传播它.例如,在:
A return
statement in the callback returns from the callback, and the return value is ignored. The caller of Iterable.forEach
will never receive the returned value and will never have an opportunity to propagate it. For example, in:
bool f(List<int> list) {
for (var i in list) {
if (i == 42) {
return true;
}
}
return false;
}
return true
语句从函数 f
返回并停止迭代.相比之下,使用 forEach
:
the return true
statement returns from the function f
and stops iteration. In contrast, with forEach
:
bool g(List<int> list) {
list.forEach((i) {
if (i == 42) {
return true;
}
});
return false;
}
return true
语句仅从回调中返回.函数g
直到它完成all 次迭代并到达最后的return false
语句时才会返回.这也许更清楚:
the return true
statement returns from only the callback. The function g
will not return until it completes all iterations and reaches the return false
statement at the end. This perhaps is clearer as:
bool callback(int i) {
if (i == 42) {
return true;
}
}
bool g(List<int> list) {
list.forEach(callback);
return false;
}
更明显的是:
callback
无法使g
返回true
.callback
不会沿所有路径返回值.
- There is no way for
callback
to causeg
to returntrue
. callback
does not return a value along all paths.
(这就是你遇到的问题.)
(That's the problem you encountered.)
Iterable.forEach
不得与异步回调一起使用.由于回调返回的任何值都被忽略,因此永远无法等待异步回调.
Iterable.forEach
must not be used with asynchronous callbacks. Because any value returned by the callback is ignored, asynchronous callbacks can never be waited upon.
我还应该指出,如果您启用 Dart 的新空安全功能,它启用更严格的类型检查,您的 forEach
代码将生成一个错误,因为它在回调中返回一个值预期有一个 void
返回值.
I should also point out that if you enable Dart's new null-safety features, which enable stricter type-checking, your forEach
code will generate an error because it returns a value in a callback that is expected to have a void
return value.
这篇关于forEach 与 for in:调用方法时的不同行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!