开发者

enumeration with FlagsAttributes

开发者 https://www.devze.com 2023-02-03 15:28 出处:网络
assume we have an enum that has FlagsAttribute. [Flags] enum CarOptions { Sunroof = 1, Spoiler = 2, TintedWindow = 4

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消