I stepped over this enum in C:
typedef enum
{
UndefinedGravity,
ForgetGravity = 0,
NorthWestGravity = 1,
NorthGravity = 2,
NorthEastGravity = 3,
WestGravity = 4,
CenterGravity = 5,
EastGravity = 6,
SouthWestGravity = 7,
SouthGravity = 8,
SouthEastGravity = 9
} GravityType;
I built its corresponding enum type in dart:
enum GravityType {
UndefinedGravity(0),
ForgetGravity(0),
NorthWestGravity(1),
NorthGravity(2),
NorthEastGravity(3),
WestGravity(4),
CenterGravity(5),
EastGravity(6),
SouthWestGravity(7),
SouthGravity(8),
SouthEastGravity(9);
final int value;
const GravityType(this.value);
static GravityType fromValue(int value) => GravityType.values.firstWhere((e) => e.value == value);
}
You can see that UndefinedGravity
and ForgetGravity
have the same int
value in C, and theyhave the same int
value in dart.
Now consider this C function:
int myFunc(...){
GravityType gt = ForgetGravity;
return gt;
}
If I call this function from dart, it will return a dart int (0 in this case). Then I can call GravityType.fromValue(returnedValue)
But how can I know if it represents UndefinedGravity
or ForgetGravity
so I can map it properly in dart?The current implementation of fromValue
is naiive and will return the first match of the int value, so how can I return the same enum as the one that was meant to be sent from C?
CodePudding user response:
Let's take the following enum:
// Broken example, firstType and secondType have the same value but aren't equal.
enum MyType {
firstType(0),
secondType(0),
thirdType(123);
final int value;
const MyType(this.value);
static MyType fromValue(int value) => MyType.values.firstWhere((e) => e.value == value);
}
The ideal solution for sparse, overlapping enum values is to declare them as static const:
enum MyType {
firstType(0),
thirdType(123);
// Make the overlapping value an alias of the first
static const secondType = firstType;
final int value;
const MyType(this.value);
static MyType fromValue(int value) => MyType.values.firstWhere((e) => e.value == value);
}
Now MyType.firstType == MyType.secondType
returns true, secondType
feels the same as a real enum value but is really just an alias.
One more problem you might notice is that print(MyType.secondType)
confusingly prints MyType.firstType
, this can be solved by making a new value with a more descriptive name:
enum MyType {
firstOrSecondType(0),
thirdType(123);
// Both values are now an alias of firstOrSecondType
static const firstType = firstOrSecondType;
static const secondType = firstOrSecondType;
final int value;
const MyType(this.value);
static MyType fromValue(int value) => MyType.values.firstWhere((e) => e.value == value);
}
Enums in C do not store their name, their literal values are ints, so no information is lost by giving both firstType and secondType the same name.
CodePudding user response:
Enumeration constants (these things: UndefinedGravity
) in C basically work like this:
- They always have type
int
. - If no value is specified for the first item, it defaults to zero.
- If no value is specified for any other item, it defaults to previous enumeration constant 1.
- If a value is specified with
=
assignment, it uses that value. - Duplicates are allowed.