krótka odpowiedź, tak. W tym konkretnym przypadku możesz rozważyć użycieTimeSpan
Jodrell
1
Używanie metod rozszerzających na wyliczeniu sprawiłoby, że czułbym się brudny. Utwórz klasę, aby hermetyzować to, co jest potrzebne. Utrzymuj wyliczenie tak proste, jak to tylko możliwe. Jeśli potrzebujesz więcej logiki z nim skojarzonej, utwórz klasę Duration, która uwidacznia dzień, tydzień, miesiąc oraz każdą inną logikę, która byłaby w metodzie rozszerzającej.
Jason Evans
2
Lubię mieć metody rozszerzenia wyliczeń dla grup flag. Wolę się, jeśli na przykład klauzule Day.IsWorkday()nad (Day & Days.Workday) > 0z Days.Workdayzdefiniowana jako Monday | Tuesday ... | Friday. Ta pierwsza jest moim zdaniem bardziej przejrzysta i ma zaimplementowaną dokładnie tę drugą.
Metody rozszerzające umożliwiają pisanie metod dla istniejących klas w sposób, w jaki inne osoby w Twoim zespole mogą faktycznie je odkrywać i używać. Biorąc pod uwagę, że wyliczenia są klasami jak wszystkie inne, nie powinno dziwić, że można je rozszerzyć, na przykład:
Myślę, że wyliczenia nie są ogólnie najlepszym wyborem, ale przynajmniej pozwala to scentralizować niektóre przełączniki / jeśli je obsługiwać i nieco je oddzielić, aż będziesz mógł zrobić coś lepszego. Pamiętaj, aby sprawdzić, czy wartości również mieszczą się w zakresie.
Uważam, że komentarz „wyliczenia są złe” jest nie na miejscu, ale ma podstawę w rzeczywistości. Uważam, że wyliczenia mogą być problemem, są nadużywane, ponieważ w pewnym sensie zamykają cię w pewnych kontekstach i zachowaniach.
Ed Schwehm
1
Enumy w C # trochę do dupy, ponieważ kompiluje się i uruchamia:Duration d = 0;
Graham
16
Given that enums are classesnie, to nie są zajęcia.
Skrzydłowy Sendon
1
Używam tego rodzaju rozszerzenia tylko wtedy, gdy dotyczy bezpośrednio wyliczenia, na przykład dni tygodnia i metod rozszerzających IsWeekday (), IsWeekendday (). Ale klasy mają na celu hermetyzację zachowań, więc jeśli jest dużo lub skomplikowanych zachowań do hermetyzacji, klasa jest prawdopodobnie lepsza. Jeśli jest ograniczony i podstawowy, osobiście uważam, że rozszerzenia wyliczeń są w porządku. Podobnie jak w przypadku większości decyzji projektowych istnieją niejasne granice między wyborami (IMO). Warto zauważyć, że rozszerzenia można wykonywać tylko na klasach statycznych najwyższego poziomu, a nie na klasach zagnieżdżonych. Jeśli wyliczenie jest częścią klasy, musisz utworzyć klasę.
FreeText
51
Możesz również dodać metodę rozszerzenia do typu Enum zamiast wystąpienia Enum:
/// <summary> Enum Extension Methods </summary>/// <typeparam name="T"> type of Enum </typeparam>publicclassEnum<T>where T :struct,IConvertible{publicstaticintCount{get{if(!typeof(T).IsEnum)thrownewArgumentException("T must be an enumerated type");returnEnum.GetNames(typeof(T)).Length;}}}
Czy klasa może staticzapewnić, że wszystkie jej metody zachowują się jak rozszerzenia?
Jatin Sanghvi,
15
Dla przyszłych czytelników: niejednoznaczność nazwy Enum<T>jest nieco myląca. Klasę można również wywołać, EnumUtils<T>a wywołanie metody rozwiązałoby się do EnumUtils<Duration>.Count.
Namoshek
46
Oczywiście możesz na przykład powiedzieć, że chcesz użyć DescriptionAttribuena swoich enumwartościach:
using System.ComponentModel.DataAnnotations;publicenumDuration{[Description("Eight hours")]Day,[Description("Five days")]Week,[Description("Twenty-one days")]Month}
Teraz chcesz móc zrobić coś takiego:
Duration duration =Duration.Week;var description = duration.GetDescription();// will return "Five days"
Twoja metoda rozszerzenia GetDescription()może być zapisana w następujący sposób:
using System.ComponentModel;
using System.Reflection;publicstaticstringGetDescription(thisEnumvalue){FieldInfo fieldInfo =value.GetType().GetField(value.ToString());if(fieldInfo ==null)returnnull;var attribute =(DescriptionAttribute)fieldInfo.GetCustomAttribute(typeof(DescriptionAttribute));return attribute.Description;}
Chciałem stworzyć rozszerzenie do prawie dokładnie tego, co zrobiłeś, z wyjątkiem mojego użycia DisplayAttribute Localized GetDescription. okrzyki
George
To fajna alternatywa, chociaż myślę, że przestrzeń nazw to po prostu System.ComponentModel?
TomDestry
Fajna perspektywa i dziękuję za pokazanie implementacji oraz kodu rozszerzenia. Aby uzupełnić: swoją implementację możesz również nazwać w ten sposób: var description = Duration.Week.GetDescription ();
Spencer Sullivan
31
Wszystkie odpowiedzi są świetne, ale mówią o dodaniu metody rozszerzenia do określonego typu wyliczenia.
A co, jeśli chcesz dodać metodę do wszystkich wyliczeń, na przykład zwracającą int bieżącej wartości zamiast jawnego rzutowania?
publicstaticclassEnumExtensions{publicstaticintToInt<T>(this T soure)where T :IConvertible//enum{if(!typeof(T).IsEnum)thrownewArgumentException("T must be an enumerated type");return(int)(IConvertible) soure;}//ShawnFeatherly funtion (above answer) but as extention methodpublicstaticintCount<T>(this T soure)where T :IConvertible//enum{if(!typeof(T).IsEnum)thrownewArgumentException("T must be an enumerated type");returnEnum.GetNames(typeof(T)).Length;}}
Sztuczka IConvertiblepolega na tym, że Hierarchia dziedziczenia, patrz MDSN
Tak samo. Działa, jeśli dzwonię bezpośrednio do rozszerzenia (np. MyExtention.DoThing(myvalue)), Ale w rzeczywistości nie dołączam do wyliczenia (np. myvalue.DoThing())
Sinaesthetic
1
FYI, C # 7.3 obsługuje teraz Enum jako ograniczenie typu ogólnego
redtetrahedron
7
Możesz utworzyć rozszerzenie dla wszystkiego, nawet object(chociaż nie jest to uważane za najlepszą praktykę ). Zrozum metodę rozszerzania tak samo, jak public staticmetodę. Możesz użyć dowolnego typu parametru w metodach.
voidWartość zwracana na enum jest trochę dziwne. Pomyślałbym o bardziej realistycznej próbce.
psubsee2003
3
@ psubsee2003 OP z pewnością ma wystarczającą wiedzę, aby zmienić to zgodnie z jego potrzebami? Dlaczego próbka ma znaczenie, wystarczy odpowiedzieć na wstępne pytanie.
LukeHennerley
3
Czy tylko ja uważam, że przykłady kodu w witrynie MSDN są dziwne? W większości przypadków potrzebujesz prawdziwego wysiłku, aby zrozumieć, co próbują zrobić!
TimeSpan
Day.IsWorkday()
nad(Day & Days.Workday) > 0
zDays.Workday
zdefiniowana jakoMonday | Tuesday ... | Friday
. Ta pierwsza jest moim zdaniem bardziej przejrzysta i ma zaimplementowaną dokładnie tę drugą.Odpowiedzi:
Według tej strony :
Metody rozszerzające umożliwiają pisanie metod dla istniejących klas w sposób, w jaki inne osoby w Twoim zespole mogą faktycznie je odkrywać i używać. Biorąc pod uwagę, że wyliczenia są klasami jak wszystkie inne, nie powinno dziwić, że można je rozszerzyć, na przykład:
Myślę, że wyliczenia nie są ogólnie najlepszym wyborem, ale przynajmniej pozwala to scentralizować niektóre przełączniki / jeśli je obsługiwać i nieco je oddzielić, aż będziesz mógł zrobić coś lepszego. Pamiętaj, aby sprawdzić, czy wartości również mieszczą się w zakresie.
Możesz przeczytać więcej tutaj w Microsft MSDN.
źródło
Duration d = 0;
Given that enums are classes
nie, to nie są zajęcia.Możesz również dodać metodę rozszerzenia do typu Enum zamiast wystąpienia Enum:
Możesz wywołać powyższą metodę rozszerzenia, wykonując:
To nie jest prawdziwa metoda rozszerzenia. Działa tylko dlatego, że Enum <> jest innego typu niż System.Enum.
źródło
static
zapewnić, że wszystkie jej metody zachowują się jak rozszerzenia?Enum<T>
jest nieco myląca. Klasę można również wywołać,EnumUtils<T>
a wywołanie metody rozwiązałoby się doEnumUtils<Duration>.Count
.Oczywiście możesz na przykład powiedzieć, że chcesz użyć
DescriptionAttribue
na swoichenum
wartościach:Teraz chcesz móc zrobić coś takiego:
Twoja metoda rozszerzenia
GetDescription()
może być zapisana w następujący sposób:źródło
Wszystkie odpowiedzi są świetne, ale mówią o dodaniu metody rozszerzenia do określonego typu wyliczenia.
A co, jeśli chcesz dodać metodę do wszystkich wyliczeń, na przykład zwracającą int bieżącej wartości zamiast jawnego rzutowania?
Sztuczka
IConvertible
polega na tym, że Hierarchia dziedziczenia, patrz MDSNDziękuję ShawnFeatherly za odpowiedź
źródło
MyExtention.DoThing(myvalue)
), Ale w rzeczywistości nie dołączam do wyliczenia (np.myvalue.DoThing()
)Możesz utworzyć rozszerzenie dla wszystkiego, nawet
object
(chociaż nie jest to uważane za najlepszą praktykę ). Zrozum metodę rozszerzania tak samo, jakpublic static
metodę. Możesz użyć dowolnego typu parametru w metodach.źródło
Zobacz MSDN .
źródło
void
Wartość zwracana na enum jest trochę dziwne. Pomyślałbym o bardziej realistycznej próbce.właśnie stworzyliśmy rozszerzenie wyliczenia dla c # https://github.com/simonmau/enum_ext
To tylko implementacja dla typesafeenum, ale działa świetnie, więc stworzyliśmy pakiet do udostępnienia - baw się dobrze
Wiem, że przykład jest trochę bezużyteczny, ale masz pomysł;)
źródło
Proste obejście.
źródło