2012-05-13 7 views
10

zauważyłem te dwa wzory do sprawdzania flagą ENUM:Najlepsze praktyki dla sprawdzanie flagą enum

[Flags] 
public enum PurchaseType 
{ 
    None = 0, 
    SalePrice = 2, 
    RegularPrice = 4, 
    Clearance = 8, 
    CreditCard = 16 
} 

public void Test() 
{ 
    PurchaseType type = PurchaseType.Clearance; 
    type |= PurchaseType.CreditCard; 

    // Practice 1 
    if ((type & PurchaseType.Clearance) == PurchaseType.Clearance) 
    { 
     // Clearance item handling 
    } 

    // Practice 2 
    if ((type & PurchaseType.CreditCard) != 0) 
    { 
     // Credit card item handling 
    } 
} 

Z tych dwóch sposobów sprawdzania flagą enum, który z nich jest lepszy wydajność wrt, czytelność, kod zdrowia i wszelkie inne uwagi, które powinienem zrobić?

Dzięki Mohammed

+1

Lepiej na co? Czytelność? Wydajność? Faza księżyca? Coś innego? – Oded

+2

Głosuję na praktykę 1. Jak byś przetestował dla 'PurchaseType.None' z praktyką 2? Edycja: Myślę, że możesz zrobić (wpisz & PurchaseType.None) == 0, ale teraz twoje kontrole nie są naprawdę spójne. – Tung

+0

@ Tung Er, 'None' nie jest flagą, na którą można przetestować. 'type & PurchaseType.None' to' 0' dla wszystkich wartości 'type'. Nigdy nie możesz testować na "Brak", więc nie ma sensu martwić się, jak zrobić to, czego nie można zrobić i nigdy nie jest zrobione. –

Odpowiedz

15

.Net 4 wprowadza HasFlag metodę, która określa, czy jeden lub więcej pól bitowych są ustawione w bieżącej instancji, to jest zdecydowanie najlepsza praktyka:

type.HasFlag(PurchaseType.CreditCard); // true 
+0

To wygląda na łatwiejsze w użyciu. Widziałem ten [problem z połączeniem] (http://connect.microsoft.com/VisualStudio/feedback/details/554908/enum-hasflag-umiejętnie-współpraca) dotyczący wydajności. Zastanawiam się, czy zostało to naprawione w wersji 4.0. –

+2

A [wpis na blogu] (http://blogs.microsoft.co.il/blogs/bnaya/archive/2011/01/28/enum-hasflag-good-or-bad.aspx) dotyczący tej i złej wydajności. Wydaje się, że nie jest to tylko zwykły cukier syntaktyczny. Ta metoda wydaje się wykorzystywać refleksję zgodnie z tym postem. –

+0

Widzę wiele upvotes dla tej odpowiedzi i teraz jestem ciekawy. Powiedzmy, że była kara za stosowanie tego w stosunku do innych. Czy tutaj lepsza czytelność przyniesie lepsze wyniki? –

2

wybrałbym pierwszy:

if ((type & PurchaseType.Clearance) == PurchaseType.Clearance) 
{ 
    // Clearance item item handling 
} 

bo to wyraźnie małże, że jesteś sprawdzanie Clearance typu obecności.

+3

Hmm, nie lubię tak bardzo. Widzę duplikację. Jeśli zmieniłeś opcję "Rozliczenie" na jedną z innych flag, ale zapomniałeś zrobić to w obu lokalizacjach, to Twój kod by się skompilował, ale nie zrobiłby tego, co chcesz. '! = 0' wygrywa dla mnie. –

+0

@DavidHeffernan: zgadzam się (w przypadku duplikowania), ale podobnie jak wyraźne oświadczenie. – Tigran

+0

@ David: Rzeczywiście popełniłem ten błąd podczas pisania mojego pytania! –

1

Osobiście zawsze wolą wyraźną czytelność HasFlag.

Jednak z dwóch opcji w pytaniu uważam, że !=0 jest bezpieczniejsze, ponieważ nie ma duplikacji. Jeśli używasz alternatywy, to jest to zbyt proste, gdy kodowanie konduktancyjne zmienia jedną z flag i zapominasz o zmianie drugiej. I wtedy można skończyć z tym

if ((type & PurchaseType.Clearance) == PurchaseType.CreditCard) 
+0

w kontekście wydajności. czy obsada polega na użyciu sprawdzenia! = 0? –

+0

W jaki sposób porównanie z 0 może mieć wpływ na wydajność? –

+0

Czy podczas sprawdzania należy zerwać wartość 0? Jeśli tak, to czy jest gorsza od innej opcji w moim pytaniu? –

1

wolałbym (type & PurchaseType.CreditCard) != 0 bo jeśli chcesz sprawdzić więcej niż jeden bit wtedy prawa strona staje się uciążliwe. Ufam w operacje bitowe, które powyższe będą prawdziwe tylko wtedy, gdy ustawione są bity.