2012-02-03 12 views
13

Właśnie zauważyłem, że jest tylko mała różnica w deklarując niebędącego członkiem dyskryminowane UNION:Enum vs non-członka dyskryminowane unii

type Color = 
    | Red 
    | Green 
    | Blue 

i deklarowania ENUM:

type Color = 
    | Red = 0 
    | Green = 1 
    | Blue = 2 

Co są ich główne różnice pod względem wydajności, użytkowania itp.? Czy masz sugestie, kiedy użyć czego?

Odpowiedz

14

Enum to kostki i dlatego są przydzielane na stosie, a dyskryminowane związki są typami referencji, więc przydzielane są sterty. Tak więc, można by oczekiwać, że DU będzie nieco mniej wydajne, ale w rzeczywistości prawdopodobnie nigdy nie zauważysz tej różnicy.

Co ważniejsze, unia dyskryminowana może być tylko jednym z zadeklarowanych typów, gdzie jako wyliczenia są tak naprawdę tylko liczbą całkowitą, więc można rzucić liczbę całkowitą, która nie jest członkiem wyliczenia do typu wyliczeniowego. Oznacza to, że gdy wzorzec pasujący do kompilatora może potwierdzić, że dopasowywanie wzorca jest kompletne, gdy obstawiłeś wszystkie przypadki dla DU, ale dla wyliczenia zawsze musisz umieścić domyślny haczyk dla całego przypadku, np. Dla wyliczenia Zawsze będziesz potrzebował dopasowywania wzorców, takiego jak:

match enumColor with 
| Red -> 1 
| Green -> 2 
| Blue -> 3 
| _ -> failwith "not an enum member" 

gdzie taki ostatni przypadek nie byłby konieczny w przypadku dalszego użytkownika.

Jedna ostatnia kwestia, ponieważ nagłówki są natywnie obsługiwane zarówno w językach C#, jak i VB.NET, ponieważ nie są takimi użytkownikami, wyliczenia często stanowią lepszy wybór podczas tworzenia publicznego interfejsu API do wykorzystania przez inne języki.

6

Oprócz tego, co powiedział Robert, dopasowywanie wzorów do związków odbywa się na dwa sposoby. W przypadku związków z tylko przypadkami zerowymi, tj. Przypadkami bez powiązanej wartości (odpowiada to ściśle wyliczeniom), sprawdzana jest właściwość Tag generowana przez kompilator, która jest int. W takim przypadku możesz oczekiwać, że wydajność będzie taka sama, jak przy przeliczeniach. W przypadku związków z nie-zerowymi przypadkami stosuje się test typu, który, jak sądzę, jest również dość szybki. Jak powiedział Robert, jeśli istnieje rozbieżność wyników, jest ona znikoma. Ale w pierwszym przypadku powinno być dokładnie to samo.

Odnośnie nieodłącznej "niekompletności" wyliczeń, gdy nie uda się dopasować wzorca, co naprawdę chcesz wiedzieć, to czy przypadek nie był objęty sprawą. Nie generalnie dbasz o to, czy niepoprawna liczba całkowita została rzucona do enum. W takim przypadku chcesz, aby mecz się nie powiódł. Prawie zawsze wolę związki zawodowe, ale kiedy muszę używać wyliczeń (zwykle dla interoperacyjności), w obowiązkowej skrzynce wieloznacznej przekazuję niedopasowaną wartość do a function that distinguishes between valid and invalid values i zgłaszam odpowiedni błąd.

0

Od F # 4.1 są struct discriminated unions.

Mają one zalety wydajności wynikające z alokacji stosu.

Mają lepsze dopasowanie dyskryminowanych związków.

Są one specyficzne dla F #, więc jeśli musisz być zrozumiany przez inne języki .Net, powinieneś używać wyliczeń.