Wyliczenia i stałe. Którego użyć kiedy?

97

Czytałem o wyliczeniach i stwierdziłem, że są bardzo podobne do deklarowania stałych. Skąd mam wiedzieć, kiedy użyć stałej, a nie wyliczenia, lub odwrotnie. Jakie są zalety używania wyliczeń?

Draco
źródło
zobacz także stackoverflow.com/questions/11575376/…, aby uzyskać podobne pytanie dotyczące języka Java (odpowiedzi dotyczą głównie języka C #).
Alexei Levenkov

Odpowiedzi:

97

Użyj wyliczeń, gdy chcesz zdefiniować zakres wartości, które mogą być. Kolor jest oczywistym przykładem:

public enum Colour
{
    White,
    Red,
    Blue
}

A może zestaw możliwych rzeczy, takich jak: (Przykład, który ukradłem stąd, ponieważ jestem leniwy)

[FlagsAttribute]
enum DistributedChannel
{
  None = 0,
  Transacted = 1,
  Queued = 2,
  Encrypted = 4,
  Persisted = 16,
  FaultTolerant = Transacted | Queued | Persisted
}

Stałe powinny dotyczyć jednej wartości, np. PI. Nie ma zakresu wartości PI, jest tylko PI.

Inne kwestie do rozważenia to:

  • a: Stałe niekoniecznie wskazują na związek między stałymi, podczas gdy wyliczenie wskazuje, że coś może być jednym ze zbioru zdefiniowanego przez wyliczenie.
  • b: Zdefiniowane wyliczenie może pomóc w sprawdzaniu typu, gdy jest używane jako argument. Stałe to tylko wartości, więc nie dostarczają żadnych dodatkowych informacji semantycznych.
Andrew Barrett
źródło
1
Co się stanie, jeśli w końcu użyjesz .ToString()często wyliczenia, jakiejkolwiek wartości w używaniu klasy z ciągami stałymi, która wygląda i działa jak wyliczenie, ale omija wywołanie ToString()? Przykład
Sinjai
Czekaj, myślę, że odpowiedziałem na własne pytanie. Kod w tym przykładzie nie działałby: należałoby potraktować dane wejściowe jako ciąg, który tak naprawdę nie zachowywałby się jak wyliczenie.
Sinjai
1
Dlaczego jednak nie mógłbyś mieć statycznej klasy Color ze stałymi kolorami zamiast wyliczenia? Co za różnica?
WDUK
w skrócieType Safety"
ahmednabil88
31

W innych odpowiedziach brakuje tego, że wyliczenia mają bazowy typ całkowity. Możesz zmienić wartość domyślną z int na dowolny inny typ całkowity z wyjątkiem char, na przykład:

enum LongEnum : long {
    foo,
    bar,
}

Można rzutować jawnie zi niejawnie na typ podstawowy, co jest przydatne w instrukcjach przełączania. Pamiętaj, że można rzutować dowolną wartość typu podstawowego na wyliczenie, nawet jeśli wyliczenie nie ma elementu członkowskiego o odpowiedniej wartości. Dlatego używanie zawsze domyślnej sekcji przełącznika jest dobrym pomysłem. BTW, sam .NET pozwala nawet na wyliczenia o wartościach zmiennoprzecinkowych, ale nie można ich zdefiniować w C #, chociaż myślę, że nadal można ich używać (z wyjątkiem przełącznika).

Ponadto stosowanie wyliczeń zapewnia większe bezpieczeństwo typów. Jeśli zamierzasz użyć np. Stałych int jako parametrów metody, to mógłbym wywołać metodę z dowolną wartością int. Owszem, przez rzutowanie może się to zdarzyć również w przypadku wyliczeń, ale nie stanie się to przypadkowo. Gorzej jest z możliwością pomylenia kolejności parametrów.

void method(int a, int b) {...}

Jeśli tylko stała A może przejść do a, a stała B tylko do b, to użycie dwóch różnych typów wyliczeń ujawni wszelkie nadużycia podczas kompilacji.

Johannes
źródło
21

Stała to funkcja języka, która mówi, że zmienna nie zmieni wartości (więc kompilator może dokonać optymalizacji wokół tej wiedzy), gdy wyliczenie jest określonym typem.

Stałe mogą mieć dowolny typ danych, ale wyliczenie jest wyliczeniem.

Używam wyliczenia w każdym miejscu, w którym możesz mieć wiele opcji i chcesz poprawić czytelność kodu. tj. możesz mieć poziomy śledzenia jako int z wartościami 0, 1, 2 lub jako wyliczenie jako błąd, ostrzeżenie i informacje.

Enum mogą być również używane jako operatory bitowe, np. FontStyle.Bold | FontStyle.Italic zapewni czcionki pogrubione i pochylone.

Robert MacLean
źródło
8

Oprócz odpowiedzi Roberta:

  1. Użyj enum dla skończonego zestawu nazwanych wartości. Nie przejmujesz się wartościami liczbowymi za każdym symbolem (ale nadal masz możliwość ich narzucenia, np. W celu zgodności ze starszym systemem).

  2. Robert: Tak, Enum mogą być używane jako pola bitowe. Użyj atrybutu Flags (i upewnij się, że elementy członkowskie wyliczenia mają odpowiednie wartości liczbowe).

Serge Wautier
źródło
3

Stała AC # jest podobna do zmiennej, ponieważ nadaje zdefiniowanej nazwie wartości. Jednak stała różni się od zmiennej standardowej, ponieważ raz zdefiniowana wartość przypisana do stałej nigdy nie może zostać zmieniona. Główną zaletą stałych jest ich pomoc w tworzeniu samodokumentującego się kodu, a także umożliwienie deklaracji kluczowych wartości w jednym miejscu, co pozwala na łatwą obsługę w przypadku konieczności aktualizacji wartości i ponownej kompilacji oprogramowania.

Natomiast listy Enumerator są przydatne do definiowania sekwencji i stanów, szczególnie gdy następuje naturalny postęp przez te stany. Dzieje się tak, ponieważ każdą stałą na liście można sformatować i porównać przy użyciu jej nazwy lub wartości. Wyliczenia można również użyć do zdefiniowania ograniczonego zestawu prawidłowych wartości.

po prostu ostry
źródło
3

Jedną rzeczą, którą uważam za przydatną podczas używania enumzamiast tego, constjest to, że można iterować po wartościach w an enum, znacznie trudniej jest to zrobić z constwartościami.

David Klempfner
źródło