Jak wygląda poprawna implementacja enuma

Tak IMHO powinien wyglądać dobrze napisany enum:

public enum DocumentStatus : byte
{
    Draft = 1,
    Approved = 2,
    UnderRevision = 3,
    Released = 4
}

Nie enumerujemy od zera

„0” jest domyślną wartością dla enuma (bo pod spodem musi być typ całkowity). Dlatego chcemy aby nasze znaczące wartości zaczynały się od jedynki. Wtedy prościej wyśledzić w której ścieżce wykonania jest błąd, spowodowany nieustawieniem wartości. W naszych switchach zawsze wtedy wpadniemy w default gdzie najlepiej rzucić wyjątkiem.

Pozbyć się wartości Undefined

Ten enum mógłby wyglądać tak:

public enum DocumentStatus : byte
{
    Undefined = 0,
    Draft = 1,
    Approved = 2,
    UnderRevision = 3,
    Released = 4
}

Inne spotykane nazwy to Unknown, NotExists, NoValue, itp.

Niby podobnie do wzorcowego przykładu, ale jednak ma wady. Gdy generejemy instrukcję switch to z pomocą R# dostaniemy wypełnione wszystkie wartości enumów. I niestety dostaniemy też case dla Undefined, a lepiej żeby te przypadki wpadły do default i spowodowały wyjątek.

switch with undefined

Dziedziczyć po byte?

Wystarczy nie dziedziczyć po niczym wtedy domyślnie jest to int i wszystko jest w porządku. W przykładzie dziedziczę po byte ponieważ enum ląduje w bazie (korzystam z EF) i tam staram się używać typów, które mniej miejsca zajmują. W .NET nie ma to praktycznie znaczenia.

Czy nadawać wartości liczbowe wszystkim?

Kiedyś przeczytałem rozróżnienie, żeby nadawać wszystkie wartości tylko tym enumom, które lądują w bazie. To jest na pewno ważne, bo zdarza się często, że usuwamy jakąś wartość ze „środka”. Było tam też napisane, że dla enumów, które nie lądują w bazie nie powinno się tego robić, tylko zostawić to frameworkowi.

public enum DocumentStatus : byte
{
    Draft = 1,
    Approved,
    UnderRevision,
    Released
}

W praktyce wydaje mi się, że lepiej zdecydować się na jedno i zawsze nadawać wartości.

Czy macie sytuację gdzie lepiej nadać tylko pierwszą wartość równą 1 (żeby domyślnie nie numerowało od 0), a numerowanie pozostałych zostawić frameworkowi?

Advertisements
Ten wpis został opublikowany w kategorii Programowanie i oznaczony tagami , . Dodaj zakładkę do bezpośredniego odnośnika.

4 odpowiedzi na „Jak wygląda poprawna implementacja enuma

  1. Pingback: dotnetomaniak.pl

  2. Maciek pisze:

    Wydaje mi się, ze nie warto jest się pozbywać wartości Undefined. Dzięki temu możemy rozdzielić przypadki, gdy wartość jest niezdefiniowana, a np poprostu błędna. dostaję 0, aha jest undefined, bo obiekt dopiero został stworzony. Dostaję wartość np -5 wiedz, że coś się dzieje…

    • @Maciek a czy Twoja domena rozróżnia między wartością „niezdefiniowaną” a „błędną”? Chciałem uwypuklić, że lepiej traktować bardzo ostro wszystkie „niezdefiniowane/błędne” dane niż pozwalać im żyć w systemie.

  3. krepiarz pisze:

    Jawne specyfikowanie wszystkich wartości ma tę zaletę, że programista zastanowi się dwa razy, zanim potem wstawi nową wartość enuma w środek, co łamie kompatybilność binarną. Gdy wartości nie są jawnie podane, mało kto o tym pamięta i często niechcący zmienia semantykę programu.

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s