Często zdarza mi się implementować klasę, która utrzymuje jakąś własną właściwość statusu jako wyliczenie: mam wyliczenie Status i JEDEN Właściwość Status typu Status. Jak mam rozwiązać ten konflikt nazw?
public class Car
{
public enum Status
{
Off,
Starting,
Moving
};
Status status = Status.Off;
public Status Status // <===== Won't compile =====
{
get { return status; }
set { status = value; DoSomething(); }
}
}
Gdyby wyliczenie Status było wspólne dla różnych typów, umieściłbym je poza klasą i problem zostałby rozwiązany. Ale Status dotyczy tylko samochodu, dlatego nie ma sensu deklarowanie wyliczenia poza klasą.
Jakiej konwencji nazewnictwa używasz w tym przypadku?
Uwaga: to pytanie było częściowo omawiane w komentarzach do odpowiedzi na to pytanie . Ponieważ nie było to główne pytanie, nie było zbyt dobrze widoczne.
EDYCJA: Filip Ekberg sugeruje doskonałe obejście IMO dla konkretnego przypadku „Status”. Byłbym jednak interesujący, gdyby przeczytał o rozwiązaniach, w których nazwa wyliczenia / właściwości jest inna, jak w odpowiedź .
EDIT2 (maj 2010): Moim ulubionym rozwiązaniem jest dodanie liczby mnogiej nazwy typu wyliczenia, zgodnie z sugestią Chrisa S. Zgodnie z wytycznymi MS, powinno to być używane tylko dla wyliczeń flag. Ale coraz bardziej to lubię. Teraz używam go również do zwykłych wyliczeń.
źródło
Odpowiedzi:
Dodam do dyskusji moje 1 euro, ale prawdopodobnie nie dodam niczego nowego.
Oczywistym rozwiązaniem jest usunięcie statusu zagnieżdżonego Enum. Większość wyliczeń .NET (z wyjątkiem być może niektórych w przestrzeni nazw Windows.Forms) nie jest zagnieżdżonych, co sprawia, że używanie przez programistę używającego interfejsu API jest denerwujące, ponieważ musi poprzedzać nazwę klasy.
Jedną rzeczą, o której nie wspomniano, jest to, że wyliczenia flag zgodnie z wytycznymi MSDN powinny być rzeczownikami w liczbie mnogiej wyliczenia liczbie które prawdopodobnie już znasz (Status jest prostym wyliczeniem, więc należy używać rzeczowników w liczbie pojedynczej).
Stan (wyliczenie nazywane Stany) jest wołaczem, „Status” jest mianownikiem rzeczownika, który język angielski, podobnie jak większość naszego języka, został wchłonięty z łaciny. Vocative to to, co nazywasz rzeczownikiem ze względu na jego stan, a mianownik jest podmiotem czasownika.
Innymi słowy, kiedy samochód się porusza , to jest czasownik - ruch to jego status. Ale samochód nie gaśnie, ale jego silnik. Ani się nie uruchamia, ale silnik nie (prawdopodobnie wybrałeś tutaj przykład, więc może to nie mieć znaczenia).
public class Car { VehicleState _vehicleState= VehicleState.Stationary; public VehicleState VehicleState { get { return _vehicleState; } set { _vehicleState = value; DoSomething(); } } } public enum VehicleState { Stationary, Idle, Moving }
Stan jest tak uogólnionym rzeczownikiem, czy nie lepiej byłoby opisać, do jakiego stanu się odnosi? Tak jak powyżej
Przykład typu również w moim widoku nie odnosi się do typu czytnika, ale do jego bazy danych. Wolałbym, żebyś opisywał produkt bazy danych czytelnika, który niekoniecznie jest odpowiedni dla typu czytnika (np. Typ czytnika może być tylko przekazywany, buforowany i tak dalej). Więc
W rzeczywistości tak się nigdy nie dzieje, ponieważ są one zaimplementowane jako sterowniki i łańcuch dziedziczenia zamiast używać wyliczeń, dlatego powyższa linia nie wygląda naturalnie.
źródło
public class EngineState
powinienem byćpublic enum EngineState
w tym przykładzie, prawda?Definicje „Off”, „Start” i „Moving” to coś, co nazwałbym „Stanem”. A kiedy sugerujesz, że używasz „Stanu”, jest to Twój „Status”. Więc!
public class Car { public enum State { Off, Starting, Moving }; State state = State.Off; public State Status { get { return state ; } set { state= value; DoSomething(); } } }
Jeśli weźmiemy inny przykład z podanego, w którym chciałbyś użyć słowa „Typ”, w tym przypadku:
public class DataReader { public enum Type { Sql, Oracle, OleDb } public Type Type { get; set; } // <===== Won't compile ===== }
Naprawdę musisz zobaczyć, że istnieje różnica między wyliczeniami a wyliczeniami, prawda? Ale tworząc framework lub rozmawiając o architekturze, musisz skupić się na podobieństwach, ok, znajdźmy je:
Kiedy coś jest ustawione na stan, jest to definiowane jako stan „rzeczy”
Przykład: stan samochodu to Running State, Stopped i tak dalej.
To, co chcesz osiągnąć w drugim przykładzie, jest mniej więcej takie:
Możesz pomyśleć, że to mówi przeciwko temu, o czym głosiłem innym, że musisz przestrzegać standardu. Ale postępujesz zgodnie ze standardem! Przypadek Sql jest również szczególnym przypadkiem i dlatego wymaga nieco konkretnego rozwiązania.
Jednak wyliczenie będzie możliwe do ponownego użycia w Twoim
System.Data
przestrzeni i o to właśnie chodzi we wzorcach.Innym przypadkiem, któremu należy przyjrzeć się z „Typem”, jest „Zwierzę”, gdzie Typ określa gatunek.
public class Animal { public enum Type { Mammal, Reptile, JonSkeet } public Type Species{ get; set; } }
Jest to zgodne z wzorcem, nie musisz specjalnie „znać” obiektu w tym celu i nie określasz „AnimalType” ani „DataReaderType”, możesz ponownie użyć wyliczeń w wybranej przestrzeni nazw.
źródło
Myślę, że prawdziwy problem polega na tym, że stan wyliczenia jest zamknięty w klasie, co
Car.Status
jest niejednoznaczne zarówno dla właściwości, jakStatus
i wyliczeniaStatus
Jeszcze lepiej, umieść wyliczenie poza klasą:
public enum Status { Off, Starting, Moving } public class Car { public Status Status { ... } }
AKTUALIZACJA
Ze względu na poniższe komentarze wyjaśnię powyżej mój projekt.
Jestem osobą, która nie wierzy, że wyliczenia, klasy lub jakikolwiek inny obiekt powinien znajdować się w innej klasie, chyba że będzie to całkowicie prywatne w tej klasie. Weźmy na przykład powyższy przykład:
public class Car { public enum Status {...} ... public Status CarStatus { get; set;} }
Podczas gdy niektórzy komentatorzy twierdzą, że Status nie ma żadnego znaczenia poza zakresem klasy Car, fakt, że ustawiasz właściwość publiczną, oznacza, że istnieją inne części programu, które będą używać tego wyliczenia:
public Car myCar = new Car(); myCar.CarStatus = Car.Status.Off;
A to dla mnie zapach kodu. Jeśli mam patrzeć na tego statusu zewnątrz z
Car
, równie dobrze mogę zdefiniować go na zewnątrz , jak również.W związku z tym prawdopodobnie zmienię jego nazwę na:
public enum CarStatus {...} public class Car { ... public CarStatus Status { get; set; } }
Jeśli jednak to wyliczenie będzie używane w obrębie klasy samochodu i tylko w jej obrębie , mogę zadeklarować tam wyliczenie.
źródło
OR
iCR
. Oba mają własny zestaw stanów, więc nie można ich definiować poza własnym zakresem.Wiem, że moja sugestia jest sprzeczna z konwencjami nazewnictwa .NET, ale osobiście poprzedzam wyliczenia literą „E”, a flagi wyliczenia literą „F” (podobnie jak w przypadku interfejsów poprzedzamy literę „I”). Naprawdę nie rozumiem, dlaczego to nie jest konwencja. Wyliczenia / flagi to szczególny przypadek, taki jak interfejsy, które nigdy nie zmienią swojego typu. Nie tylko wyjaśnia, co to jest, ale jest bardzo łatwe do wpisania w trybie Intellisense, ponieważ przedrostek będzie filtrował większość innych typów / zmiennych / itp. I nie będzie takich konfliktów nazw.
Rozwiązałoby to również inny problem, w którym w przykładach w WPF używają klas statycznych, takich jak wyliczenia (np. FontWeights), które mają wstępnie zdefiniowane wystąpienia typów, ale nie wiesz, czy ich nie szukasz. Gdyby po prostu dodali do nich przedrostek „E”, wszystko, co musiałbyś zrobić, to wpisać znak, aby znaleźć te specjalne klasy statyczne.
źródło
Niech będą przeklęci hejterzy notacji węgierskiej i jej odmian. Używam konwencji dodawania wyliczeń z sufiksem - poczekaj na to -
Enum
. W rezultacie nigdy nie mam problemu, który opisujesz, tracę czas na martwienie się, jak je nazwać, a kod jest czytelny i samoopisowy do uruchomienia.public class Car { public enum StatusEnum { Off, Starting, Moving }; public StatusEnum Status { get; set; } }
źródło
Zmieniłbym nazwę właściwości na coś w rodzaju „CurrentStatus”. Szybko i łatwo :)
źródło
Proponuję dodać „Option” do nazwy typu (lub Flag, jeśli zawiera flagi bitowe), tj. Typ to Car.StatusOption, a właściwość to Car.Status.
W porównaniu do liczby mnogiej pozwala to uniknąć kolizji nazw podczas tworzenia kolekcji typu wyliczeniowego, w przypadku których normalnie chcesz utworzyć liczbę mnogą właściwości kolekcji , a nie typu wyliczenia .
źródło
Zwykle poprzedzam wyliczenia, np. CarStatus. Przypuszczam, że wszystko zależy od zespołu, z którym pracujesz (jeśli mają jakieś zasady / procesy na tego typu rzeczy) i wykorzystania obiektów. Tylko moje 2 centy (:
źródło