2011-01-10 13 views
3

angenommen, wir haben eine enum, die FlagsAttribute hat.Enumeration mit FlagsAttributes

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

dies könnte leicht verwendet werden. nehmen nun an dieses

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

natürlich diese syntaktisch nicht korrekt ist. aber ein Auto kann nicht gleichzeitig mechanisches und elektrisches Schiebedach haben oder Schwarz und Purpur Getöntes Fenster haben.
Die Frage ist: Gibt es einen Mechanismus, um die Flags-Enumeration zu implementieren, die nicht einige Attribute gleichzeitig haben kann?

Antwort

2

Es gibt keinen eingebauten Mechanismus dafür. Flag-Enumerationen ermöglichen die Kombination beliebiger Elemente. In einem solchen Szenario müssen Sie eine manuelle Validierung durchführen oder ein Modell erstellen, das keine ungültigen Optionen akzeptiert. Es gibt andere Optionen, aber der bevorzugte Ansatz, den ich wählen würde, ist ähnlich wie diese:

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 
} 

Wie Sie sehen, habe ich von der ursprünglichen Aufzählung befreien zusammen. Ich sehe keinen Grund, ein solches Konstrukt in diesem Szenario zu verwenden - Kombinationen von verschiedenen Variablen, die ebenfalls eine domänenspezifische Kombinationslogik benötigen, sind keine guten Kandidaten für Flag-Enumerationen. Die Optionen und die Logik sollten in einer Klasse (oder möglicherweise einer Struktur, abhängig davon, wie sie verwendet werden soll) eingekapselt werden.

Flag-Enumerationen sind nur für sehr einfache und/oder spezialisierte Fälle nützlich.

3

Ich denke, Sie würden dies tun, indem Sie verschiedene Enums für Sunroofs und TingedWindows verwenden.

1

Sie haben zwei Möglichkeiten, wie ich es sehe:

1) Verwenden Sie keine enum verwenden. Verwenden Sie einen anderen Mechanismus zum Festlegen von Optionen, die in Kombinationen auftreten, die miteinander in Konflikt stehen.

2) Definieren Sie ungültige Kombinationen und für sie überprüfen, wenn Fahnen Einstellung:

[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) 
{ 
} 
+1

Ja, aber CarOptions schlägt vor, dass Sie alle Attribute kombinieren können. Erstellen Sie keine Konstrukte wie diese, für die Semantik zusätzliche EXTERN-Logik benötigt. Wenn neue Enum-Werte angezeigt werden, müssten Sie alle "if-Logik" für die gesamte Anwendung untersuchen und möglicherweise neue Abhängigkeiten hinzufügen. Schlechtes Konzept. – dzendras

+0

@dzendras, daher war die erste Lösung einfach, keine enum's zu verwenden. –

+0

Sie können Aufzählungen verwenden, aber trennen Sie sie, wie Sprinter252 zeigte. – dzendras

1

Sie ein Bit der Flags verwenden könnte ein besonderes Merkmal vorhanden ist, um anzuzeigen, und eine andere den „Geschmack“ von der, um anzuzeigen, feature:

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

Es ist dann unmöglich, beide "Aromen" zusammen zu haben.

+0

Nicht wirklich. Es bietet nur einen Standardwert, keine Exklusivität: 'var x = CarOptions.SunroofMechanical; if (x.HasFlag (CarOptions.SunroofElectrical)) Console.WriteLine ("Hat elektrisches Schiebedach"); ' – LukeH

+0

Wie geht C# mit der Konvertierung von int in eine solche enum um, wo int den Wert 8 hat? – dzendras

+0

@LukeH - wahr, ich dachte mehr daran, die Flaggen zu setzen, als sie zu testen. Sie müssten Ihre Tests so strukturieren, dass sie zuerst nach den "nicht standardmäßigen" Geschmacksrichtungen testen. –