Map built with Map.fromIterable instead of a for element
ID |
dart.performance.prefer_for_elements_map_fromiterable |
Severity |
info |
Remediation Complexity |
medium |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Idiom |
Language |
Dart |
Description
Reports a Map.fromIterable call, which a map literal with a for element expresses directly. Map.fromIterables and Map.fromEntries are not reported - neither has a for-element equivalent that is as short.
Rationale
Map.fromIterable takes its key and value as closures, so building a map of n entries allocates two closures once and then calls them n times through a function pointer, none of which the compiler can see through. Its typing is worse than the cost: the constructor is declared over dynamic, so the key and value closures receive dynamic parameters and the inferred result is a Map of dynamic to dynamic unless every type argument is written out by hand - which is why the closures in real code so often contain a cast. A map literal with a for element has no closures, infers both type arguments from the expressions, and reads in the order the entries are produced.
The following code illustrates the pattern detected by this rule:
class Catalog {
final List<int> ids;
Catalog(this.ids);
Map<int, String> labels() {
// FLAGGED: Map built with Map.fromIterable instead of a for element
return Map.fromIterable(
ids,
key: (id) => id as int,
value: (id) => 'item-$id',
);
}
}