user415789
user415789

Reputation:

enumeration with FlagsAttributes

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 TintedWindow both.
The question is: Is there a mechanism to implement the Flags enumeration which cannot have some attributes simultaneously?

Upvotes: 3

Views: 159

Answers (4)

Sander
Sander

Reputation: 26374

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.

Upvotes: 2

Damien_The_Unbeliever
Damien_The_Unbeliever

Reputation: 239764

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.

Upvotes: 1

Moo-Juice
Moo-Juice

Reputation: 38820

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)
{
}

Upvotes: 1

Alexander Schmidt
Alexander Schmidt

Reputation: 5723

I guess you would do this by using different enums for Sunroofs and TindedWindows.

Upvotes: 3

Related Questions