Enums in Dart don’t inherently implement the Comparable
interface. This means you can’t directly use them in sorted collections like List.sort()
or tree-based structures like SplayTreeSet
or SplayTreeMap
without encountering errors. Attempting to do so will result in a runtime exception indicating that the enum type is not a subtype of Comparable
.
Why Enums Aren’t Directly Comparable
Dart enums are essentially named constants representing a set of distinct values. While they have an underlying integer index, this index isn’t automatically used for comparison by default. This design decision likely stems from the intention that the order of enum values shouldn’t necessarily dictate their comparison logic. The developer should define the comparison behavior based on the specific semantics of the enum.
Working Around the Limitation: Manual Comparison
To enable comparison for enums, you need to provide a custom comparison function. This typically involves using the index
property of the enum values and leveraging the compareTo
method of integers.
Here’s how you can sort a list of enums:
enum MyEnum { One, Two }
void main() {
final items = [MyEnum.Two, MyEnum.One];
// Correct way to sort: Provide a comparison function
items.sort((a, b) => a.index.compareTo(b.index));
print(items); // Output: [MyEnum.One, MyEnum.Two]
}
Similarly, you can use a custom comparator when creating sorted collections:
import 'dart:collection' show SplayTreeMap, SplayTreeSet;
enum MyEnum { One, Two, Three }
void main() {
// Using a comparator for SplayTreeSet
final orderedSet = SplayTreeSet<MyEnum>((a, b) => a.index.compareTo(b.index));
orderedSet.addAll([MyEnum.Three, MyEnum.One, MyEnum.Two]);
print(orderedSet); // Output: {MyEnum.One, MyEnum.Two, MyEnum.Three}
// Using a comparator for SplayTreeMap
final orderedMap = SplayTreeMap<MyEnum, String>((a, b) => a.index.compareTo(b.index));
orderedMap[MyEnum.Two] = 'two';
orderedMap[MyEnum.One] = 'one';
orderedMap[MyEnum.Three] = 'three';
print(orderedMap); // Output: {MyEnum.One: one, MyEnum.Two: two, MyEnum.Three: three}
}
Conclusion: Explicit Comparison for Clarity
Requiring explicit comparison for enums promotes clarity and intent. It allows developers to define the ordering semantics that best suit their application’s logic, rather than relying on an implicit ordering based on the enum declaration. While it introduces a minor inconvenience of writing a custom comparator, it ensures that the comparison behavior is well-defined and predictable. Remember to always provide a comparator when using enums in sorted contexts to avoid runtime errors and ensure correct ordering.