Just like many programming languages, Dart allows you to create enums for defining finite sets of values. Sometimes, you may want to add fields or functions to your enum. For example, there is an enum consisting of possible statuses and each status has a unique code. That wasn't possible until Dart 2.17, which introduced enhanced enums with members.
Creating Enhanced Enum with Members
Below is a basic enum without any members.
enum Status {
pending,
success,
failed,
;
}
We are going to add a field code
to the enum. To do so, first we have to add the field to the enum (just like adding a field to a class in Dart). We also need to create a constructor with the field as the parameter and each defined enum value has to be defined by calling the constructor.
enum Status {
pending(1),
success(2),
failed(3),
;
final int code;
const Status(this.code);
}
In the example above, the code
field is final
, which means it has to be initialized. It doesn't allow null
values as well. If you want to allow null
values, just make the field nullable by adding ?
after the type (e.g. int?
).
You can have more than one field on your enum. In addition, you can also create your functions, like the example below.
enum Status {
pending(1, false),
success(2, true),
failed(3, true),
;
final int code;
final bool isFinal;
const Status(this.code, this.isFinal);
String getUpperCaseName() {
return name.toUpperCase();
}
}
Finding Enum by Field Value
In some cases, we want to get an enum value based on its field value. For example, we want to get the Status
enum above by using the given code
value. For that purpose, just create a function which accepts the field value as the parameter. Inside the function, iterate over the possible values which can be obtained from the values
field.
enum Status {
//...
static Status? getByCode(int code) {
for (Status status in Status.values) {
if (status.code == code) {
return status;
}
}
return null;
}
//...
}
However, the above code is not efficient since it will iterate over the values everytime the function is called. The solution is by caching the values to a Map
.
enum Status {
//...
static final Map<int, Status> byCode = {};
static Status? getByCode(int code) {
if (byCode.isEmpty) {
for (Status status in Status.values) {
byCode[status.code] = status;
}
}
return byCode[code];
}
//...
}
Full Code
enum/status.dart
enum Status {
pending(1, false),
success(2, true),
failed(3, true),
;
final int code;
final bool isFinal;
static final Map<int, Status> byCode = {};
const Status(this.code, this.isFinal);
static Status? getByCode(int code) {
if (byCode.isEmpty) {
for (Status status in Status.values) {
byCode[status.code] = status;
}
}
return byCode[code];
}
String getUpperCaseName() {
return name.toUpperCase();
}
@override
String toString() {
return "$name($code)";
}
}
main.dart
import 'package:dart/enum/status.dart';
void main() {
print(Status.success.getUpperCaseName()); // SUCCESS
print(Status.success.toString()); // success(2)
print(Status.getByCode(1)); // pending(1)
}
Summary
That's how to use enhanced enum with members in Dart 2.17. If your Dart version is below 2.17, you have to upgrade it or use Dart extensions instead.