Are Enums Comparable in Dart?

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.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *