I'm creating a flags enumeration in C#, similar to the following:
[Flags]
public enum DriversLicenseFlags
{
None = 0,
Suspended = 1 << 1,
Revoked = 1 << 2,
Restored = 1 << 3,
SuspendedAndRestored = Suspended | Restored,
RevokedAndRestored = Revoked | Restored,
}
A couple notes about my intentions here:
Suspended
andRevoked
are unique states that can, but don't necessarily lead to a restore.Restored
should only be possible if the user has also beenSuspended
orRevoked
(or both). It's important to track specifically which event was the precursor to the restore.- A license can be both
Suspended
andRevoked
(andRestored
)
Also, I'm trying to stick to suggestions made in MSDN's Designing Flags Enumerations. In particular:
- Consider providing special enumeration values for commonly used combinations of flags.
SuspendedAndRestored
andRevokedAndRestored
will both be common.
- Avoid creating flags enumerations when certain combinations of values are invalid.
- This is my problem, because
Restored
is not valid unless at least one ofSuspended
andRevoked
is set.
- This is my problem, because
Ideally, I'd like a value for Restored
to be present in the enum for internal usage, but only available to set publicly via some valid combination. Unfortunately, internal
isn't a valid modifier for enum values.
I've thought of a few alternatives, but each seems to have drawbacks:
Keep
Restored
as a public value, note the limitations in comments and do a precondition check for invalid combinations on public APIs.This would work, and is likely the solution I will go with. However, it seems like their should be a cleaner solution.
Use an enhanced, java-like enum as described here and define
Restored
asinternal static
.This would also work, but feels like overkill because I don't need any of the other functionality at this point.
Don't define
Restored
as a value, but reserve the value for OR'ing, and for checking the value in consuming methods. i.e.:internal const int RestoredFlag = 1 << 3; [Flags] public enum DriversLicenseFlags { None = 0, Suspended = 1 << 1, Revoked = 1 << 2, SuspendedAndRestored = Suspended | RestoredFlag, RevokedAndRestored = Revoked | RestoredFlag, }
This feels hacky me, both in how it's defined and how it will be used internally.
SuspendedAndRevoked
anSuspendedAndRevokedAndRestored
. – Ormiston