Enums
Prerequisites: switch statements and expressions, Classes and objects
An enum defines a type with a fixed set of possible values. Use one whenever a value must be one of a known list of options.
Example
enum Direction { north, south, east, west }
String arrow(Direction d) => switch (d) {
Direction.north => '↑',
Direction.south => '↓',
Direction.east => '→',
Direction.west => '←',
};
void main() {
const heading = Direction.east;
print(heading);
print(heading.name);
print(heading.index);
print(arrow(heading));
print(Direction.values);
print(Direction.values.byName('west'));
}
Expected output
Direction.east
east
2
→
[Direction.north, Direction.south, Direction.east, Direction.west]
Direction.west
- The
switchneeds no_case because it covers every value. Add a new direction later, and the compiler flags everyswitchthat doesn't handle it. nameis the value's name as text;indexits position.valueslists every value;values.byName('west')converts text back to an enum value.
Enhanced enums: fields and methods
Enum values can carry data:
enum Size {
small(250, 2.5),
medium(350, 3.0),
large(450, 3.5);
final int ml;
final double price;
const Size(this.ml, this.price);
String get label => '${name} (${ml}ml): ${price.toStringAsFixed(2)} EUR';
}
void main() {
for (final size in Size.values) {
print(size.label);
}
}
small (250ml): 2.50 EUR
medium (350ml): 3.00 EUR
large (450ml): 3.50 EUR
Note the semicolon after the last value, and the const constructor.
Common mistakes
- Using strings like
'small'for a fixed set of options. A typo in a string is a silent bug; a typo in an enum value is a compile error. - Adding a
_/defaultcase to a switch over your own enum — it hides the error you'd otherwise get when a new value is added.