使用 FlagsAttributes 进行枚举

发布于 2024-10-11 02:28:07 字数 439 浏览 1 评论 0原文

假设我们有一个具有 FlagsAttributeenum

[Flags]
enum CarOptions
{
  Sunroof = 1,
  Spoiler = 2,
  TintedWindow = 4
}

这可以很容易地使用。 现在假设这个,

[Flags]
enum CarOptions
{
  SunroofElectrical,
  SunroofMechanical,
  Spoiler,
  TintedWindowBlack,
  TintedWindowPurple
}

当然这在语法上是不正确的。但汽车不能同时拥有机械天窗和电动天窗,或者同时拥有黑色和紫色车窗。
问题是:是否有一种机制来实现不能同时具有某些属性的 Flags 枚举?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

长梦不多时 2024-10-18 02:28:07

我想您会通过为 Sunroofs 和 TindedWindows 使用不同的枚举来做到这一点。

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

梦途 2024-10-18 02:28:07

对此没有内置机制。标志枚举允许对成员进行任意组合。在这种情况下,您将需要执行手动验证或创建一个不接受无效选项的模型。还有其他选项,但我会选择的首选方法与此类似:

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
}

如您所见,我完全摆脱了原始枚举。我认为在这种情况下没有任何理由使用这种构造 - 还需要应用特定于域的组合逻辑的不同变量的组合不是标志枚举的良好候选者。选项和逻辑应该封装在一个类中(或者可能是一个结构体,具体取决于它的使用方式)。

标志枚举仅适用于非常简单和/或特殊的情况。

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.

高冷爸爸 2024-10-18 02:28:07

在我看来,你有两个选择:

1)不要使用enum。使用另一种机制来设置相互冲突的组合选项。

2) 定义无效组合并在设置标志时检查它们:

[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 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)
{
}
带上头具痛哭 2024-10-18 02:28:07

您可以使用标志的一位来指示存在的特定功能,并使用另一位来指示该功能的“风味”:

[Flags]
enum CarOptions
{
  Sunroof = 1,
  SunroofElectrical = 1,
  SunroofMechanical = 3,
  Spoiler = 4,
  TintedWindow = 8,
  TintedWindowBlack = 8,
  TintedWindowPurple = 24
}

这样就不可能同时拥有两种“风味”。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文