assume we have an enum
that has FlagsAttribute
.
[Flags]
enum CarOptions
{
Sunroof = 1,
Spoiler = 2,
TintedWindow = 4
}
this could be used easily. now assume this one
[Flags]
enum CarOptions
{
SunroofElectrical,
SunroofMechanical,
Spoiler,
TintedWindowBlack,
TintedWindowPurple
}
of course this is syntactically incorrect. but a Car can't have Mechanical and Electrical Sunroof at the same time or having Black and Purple Tinted开发者_运维百科Window both.
The question is: Is there a mechanism to implement the Flags enumeration which cannot have some attributes simultaneously?I guess you would do this by using different enums for Sunroofs and TindedWindows.
There is no built-in mechanism for this. Flag-enumerations allow any combination of the members to be combined. You will need to perform manual validation in such a scenario or create a model that does not accept invalid options. There are other options but the preferred approach I would choose is similar to this:
class CarOptions
{
public SunroofKind Sunroof { get; set; }
public SpoilerKind Spoiler { get; set; }
public TintedWindowKind TintedWindow { get; set; }
// Note that I split this into two enums - the kind of tinted window
// (UV-resistant option too maybe?) and color might be different.
// This is just an example of how such option composition can be done.
public TintedWindowColor TintedWindowColor { get; set; }
// In this class, you can also implement additional logic, such as
// "cannot have spoiler on diesel engine models" and whatever may be required.
}
enum SunroofKind
{
None,
Electrical,
Mechanical
}
enum SpoilerKind
{
None,
Standard
}
enum TintedWindowKind
{
None,
Standard
}
enum TintedWindowColor
{
Black,
Blue
}
As you see, I got rid of the original enumeration altogether. I do not see any reason to use such a construct in this scenario - combinations of different variables that also need domain-specific combination logic applied are not good candidates for flag-enumerations. The options and logic should be encapsulated in a class (or possibly a struct, depending on how it is meant to be used).
Flag-enumerations are only useful for very simple and/or specialized cases.
You have two options, as I see it:
1) Don't use an enum
. Use another mechanism for setting options that come in combinations that conflict with one another.
2) Define invalid combinations and Check for them when setting flags:
[flags]
enum CarOptions
{
SunroofElectrical = 1,
SunroofMechanical = 2,
Spoiler = 4,
TintedWindowBlack = 8,
TintedWindowPurple= 16,
// bad combos
BadSunroof = 3,
BadWindowColor = 24
}
CarOptions opt = CarOptions.SunroofElectrical | CarOptions.SunroofMechanical;
if(opt & BadSunroof)
{
}
You could use one bit of the flags to indicate a particular feature being present, and another to indicate the "flavour" of the feature:
[Flags]
enum CarOptions
{
Sunroof = 1,
SunroofElectrical = 1,
SunroofMechanical = 3,
Spoiler = 4,
TintedWindow = 8,
TintedWindowBlack = 8,
TintedWindowPurple = 24
}
It's then impossible to have both "flavours" together.
精彩评论