forEach vs for in:调用方法时的不同行为 [英] forEach vs for in: Different Behavior When Calling a Method
问题描述
我注意到 forEach
和 for in
会产生不同的行为.我有一个 RegExp
列表,并且想在每个列表上运行 hasMatch
.使用 forEach
遍历列表时, hasMatch
永远不会返回true.但是,如果我在中使用
,则 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?
推荐答案
尽管有推荐反对使用 Iterable.forEach
和其他任何东西,并且有一个相应的
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
是一个以 callback 作为参数的函数.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
直到完成所有所有迭代并在最后到达 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;
}
这使得显而易见的是:
-
回调
无法使g
返回true
. -
回调
不会沿所有路径返回值.
- 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的新的null安全功能(该功能可以进行更严格的类型检查),您的 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 vs for in:调用方法时的不同行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!