问题
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.
Here is a DartPad with sample code https://dartpad.dev/daab4a914762256369bbf582ffcfb7cd
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?
回答1:
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.
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.forEachis a function that takes a callback as an argument.Iterable.forEachis not a control structure, and the callback is an ordinary function. You therefore cannot usebreakto stop iterating early or usecontinueto skip to the next iteration.A
returnstatement in the callback returns from the callback, and the return value is ignored. The caller ofIterable.forEachwill 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; }the
return truestatement returns from the functionfand stops iteration. In contrast, withforEach:bool g(List<int> list) { list.forEach((i) { if (i == 42) { return true; } }); return false; }the
return truestatement returns from only the callback. The functiongwill not return until it completes all iterations and reaches thereturn falsestatement 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; }which makes it more obvious that:
- There is no way for
callbackto causegto returntrue. callbackdoes not return a value along all paths.
(That's the problem you encountered.)
- There is no way for
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.
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.
来源:https://stackoverflow.com/questions/65417146/foreach-vs-for-in-different-behavior-when-calling-a-method