2013-05-12 14 views
7

Deweloper przy pracy zaczął ostatnio używać wzorca klasy zamiast wyliczania w miejscach, w których zwykle mieściły się wyliczanki. Zamiast tego używa czegoś podobnego do tego poniżej:Kiedy i jak należy używać klas wyliczeniowych zamiast wyliczania?

internal class Suit 
{ 
    public static readonly Suit Hearts = new Suit(); 
    public static readonly Suit Diamonds = new Suit(); 
    public static readonly Suit Spades = new Suit(); 
    public static readonly Suit Clubs = new Suit(); 
    public static readonly Suit Joker = new Suit(); 
    private static Suit() 
    { 

    } 
    public static bool IsMatch(Suit lhs, Suit rhs) 
    { 
     return lhs.Equals(rhs) || (lhs.Equals(Joker) || rhs.Equals(Joker)); 
    } 
} 

Jego rozumowanie jest to, że niewidoczny wygląda wyliczenie, ale pozwala mu zawierać metod związanych z numeracją (jak IsMatch powyżej), aby być zawarty w sama wyliczenie.

Nazwał to klasą wyliczeń, ale nie jest to coś, co kiedykolwiek widziałem. Zastanawiałem się, jakie są zalety i wady i gdzie mogę znaleźć więcej informacji?

Dzięki

Edit: Inną zaletą opisał była możliwość dodania specyficznych toString() wdrażanie do policzenia.

+0

Cóż, nie można tego zrobić za pomocą 'enum' ponieważ nie można wpisać enum do typu złożonego. Domyślam się, że to jest główny powód używania czegoś takiego? –

+0

Jedynym prawdziwym minusem (poza tym, że niektóre biblioteki stron trzecich nie są zbytnio z tego powodu zadowolone), z jakim się zetknąłem, jest to, że nie można (trywialnie) zrobić przełącznika/obudowy na typie. Ale potem nie używałem tej techniki szeroko w języku C#. –

+0

Unikanie instrukcji zmiany było właściwie jego głównym punktem sprzedaży. Użył go, aby uniknąć tego, co opisał jako monolityczne instrukcje przełączające. Chodzi o to, że powstrzymuje cię to przed użyciem, nawet jeśli chcesz. –

Odpowiedz

1

Główną zaletą wyliczeń jest to, że są to w zasadzie liczby całkowite z niektórymi nazwanymi wartościami, jako że są one z natury przenośne i można je szeregować. Operacje arytmetyczne i logiczne są również szybsze w wyliczeniach.

Klasy wyliczeń są używane, gdy potrzebna jest nieprzezroczysta wartość, która zawiera dodatkowe informacje o stanie. Na przykład ogólny Warstwa dostępu do danych może mieć jako interfejs jak:

 
public static class Dal 
{ 
    public static Record Query(Operation operation, Parameters parameters); 
} 

var result = Dal.Query(Operation.DoSomething, new DoSomethingParameters {...}); 

dla użytkowników Operacji Dal jest tylko wyliczenie czynności dostępnych, ale może zawierać ciąg połączenia, instrukcję SQL lub przechowywane procedura i wszelkie inne dane wymagane przez rodzajowy Dal.

Innym "powszechnym" zastosowaniem jest tryb publiczny w systemie (stan lub strategia). Z perspektywy użytkownika tryb jest wartością nieprzezroczystą, ale może zawierać informacje lub funkcje wewnętrzne niezbędne do wdrożenia systemu. Zmyślony przykład:

 

public class TheSystem 
{ 
    public SystemMode Mode; 
    public void Save() 
    { 
     Mode.Save(); 
    } 
    public SystemDocument Read() 
    { 
     return Mode.Read(); 
    } 
} 

public abstract class SystemMode 
{ 
    public static SystemMode ReadOnly = new ReadOnlyMode(); 
    public static SystemMode ReadWrite = new ReadWriteMode(); 

    internal abstract void Save(); 
    internal abstract SystemDocument Read(); 

    private class ReadOnlyMode : SystemMode 
    { 
     internal override void Save() {...} 
     internal override SystemDocument Read() {...} 
    } 

    private class ReadWriteMode : SystemMode 
    { 
     internal override void Save() {...} 
     internal override SystemDocument Read() {...} 
    } 
} 


TheSystem.Mode = SystemMode.ReadOnly; 

Nie sądzę, po prostu mającą IsMatch metoda statyczna warrantów nie stosując proste teksty stałe. W tym przypadku można osiągnąć coś bardzo podobnego dzięki metodom rozszerzania.

+0

Więc są znanym narzędziem, które ma swoje zastosowania, ale nie powinno się go używać wszędzie. Jak większość rzeczy. Dzięki za przykłady. –

1

Wykończenia są idealne dla informacji o niewielkich obciążeniach. Na przykład, wyliczenie kolorów (z wyjątkiem niebieskiego) byłoby dobre dla zapytania o stan sygnalizacji świetlnej. Prawdziwy kolor wraz z całą koncepcją koloru i całego jego bagażu (alfa, przestrzeń kolorów, itp.) Nie ma znaczenia, tylko w jakim stanie jest światło. Również, zmieniając trochę wyliczenie, aby reprezentować stan sygnalizacji świetlnej :

[Flags()] 
public enum LightColors 
{ 
    unknown = 0, 
    red = 1, 
    yellow = 2, 
    green = 4, 
    green_arrow = 8 
} 

Obecny stan światło może być ustawiony jako:

LightColors c = LightColors.red | LightColors.green_arrow; 

I zapytaliśmy jak:

if ((c & LightColors.red) == LightColors.red) 
    { 
     //Don't drive 
    } 
    else if ((c & LightColors.green_arrow) == LightColors.green_arrow) 
    { 
     //Turn 
    } 

statyczne członkowie klasy kolor będzie w stanie obsługiwać tę wielokrotność stan bez dodatkowej funkcjonalności.

Jednak statyczni członkowie klasy są wspaniali dla powszechnie używanych obiektów. Członkowie System.Drawing.Color są świetnymi przykładami, ponieważ reprezentują kolory o znanej nazwie, które mają niejasne konstruktory (chyba że znasz swoje kolory hex).Gdyby były realizowane jako teksty stałe trzeba by zrobić coś takiego za każdym razem chciał użyć wartości jako kolor:

colors c = colors.red; 
     switch (c) 
     { 
      case colors.red: 
       return System.Drawing.Color.FromArgb(255, 0, 0); 
       break; 
      case colors.green: 
       return System.Drawing.Color.FromArgb(0,255,0); 
       break; 
     } 

Więc jeśli masz enum i okaże się, że ciągle robi przełącznika/case/if/else/cokolwiek do wyprowadzenia obiektu, możesz użyć statycznych elementów klasy. Jeśli tylko pytasz o stan czegoś, będę trzymać się wyrażeń. Ponadto, jeśli musisz przekazać dane w niebezpieczny sposób, wyliczenia prawdopodobnie przetrwają lepiej niż seryjna wersja twojego obiektu. tworzą

odniesienie do starego posta z tego forum: When to use enums, and when to replace them with a class with static members?

+0

Ten post bardzo przypomina to, czego szukałem, z dobrym przykładem z frameworka. Dzięki –

4

wyliczenia są dobrze w wielu sytuacjach, ale dość słaba w innych. Zazwyczaj znajdę jakieś problemy z wyliczenia:

  • Zachowanie związane z wyliczeniem dostaje rozrzucone wokół aplikacji
  • Nowe wyliczenie wartości wymagają strzelbą CHIRURGIA
  • Wyliczenia nie przestrzegają Open-Closed Principle

Zachowanie wyliczeniowe wokół, nigdy nie możemy przywrócić go do typu źródła, ponieważ typy wyliczeń nie mogą mieć żadnego zachowania (lub stan).

W drugiej z Wyliczanie klasy:

Wszystkie odmiany każdego typu wyliczenia może być popychany w dół nie tylko do klasy wyliczenia, ale do każdego konkretnego podtypu.

Wyliczenia działają dobrze w różnych scenariuszach, ale mogą szybko się zepsuć w modelu domeny. Klasy wyliczeń zapewniają dużo tej samej użyteczności, z dodatkową korzyścią stania się celem dla zachowania.

Instrukcje przełączania nie są już potrzebne, ponieważ mogę popchnąć tę zmienność i wiedzę tam, gdzie ona należy, z powrotem do modelu. Jeśli z jakiegoś powodu muszę sprawdzić określone wartości klas wyliczeniowych, opcja jest dla mnie wciąż otwarta. Ten wzorzec nie powinien zastępować wszystkich wyliczeń, ale miło mieć alternatywę.

można przeczytać na tej here

Powiązane problemy