Myślę, że kompilator poradzi sobie z tym, zamiast używać wywołania odbicia. Odpowiedź, w której zastosowano metodę kompilacji w przypadku tych informacji, otrzymałaby moje poparcie.
palswim
Odpowiedzi:
214
Enum.GetValues () wydaje się zwracać wartości w kolejności, więc możesz zrobić coś takiego:
// given this enum:publicenumFoo{Fizz=3,Bar=1,Bang=2}// this gets Fizzvar lastFoo =Enum.GetValues(typeof(Foo)).Cast<Foo>().Last();
Edytować
Dla tych, którzy nie chcą czytać komentarzy: Możesz to również zrobić w ten sposób:
var lastFoo =Enum.GetValues(typeof(Foo)).Cast<Foo>().Max();
... co zadziała, gdy niektóre wartości wyliczenia są ujemne.
Uderzałam się w głowę, myśląc, że to naprawdę banał, ale dano eleganckie rozwiązanie. Również jeśli chcesz uzyskać wartość wyliczenia, użyj następnie Convert.ToInt32 (). To jest dla wyników Google.
jdelator
53
Jeśli zamierzasz używać LINQ, dlaczego nie użyć Max (), która jest znacznie bardziej przejrzysta i nie polega na „zdaje się”?
Marc Gravell
3
Działa lepiej, ale tylko wtedy, gdy wartości wyliczenia nie są ujemne, co mogłoby być.
ICR
4
Głosuję też na Maxa (). Last () nie powiedzie się, jeśli wyliczenie nie będzie ujemne, patrz tutaj
AZ.
41
Zgadzam się z odpowiedzią Matta. Jeśli potrzebujesz tylko minimalnych i maksymalnych wartości int, możesz to zrobić w następujący sposób.
Zgodnie z odpowiedzią Matta Hamiltona, pomyślałem o stworzeniu dla niego metody rozszerzenia.
Ponieważ ValueTypenie są akceptowane jako parametr typu rodzajowego przymusu, nie mogę znaleźć lepszy sposób, aby ograniczyć Tdo Enumale następujący.
Wszelkie pomysły byłyby naprawdę mile widziane.
PS. proszę zignoruj moją niejawność VB, uwielbiam używać VB w ten sposób, to jest siła VB i dlatego kocham VB.
Howeva, oto jest:
DO#:
staticvoidMain(string[] args){MyEnum x =GetMaxValue<MyEnum>();//In newer versions of C# (7.3+)MyEnum y =GetMaxValueOld<MyEnum>();}publicstaticTEnumGetMaxValue<TEnum>()whereTEnum:Enum{returnEnum.GetValues(typeof(TEnum)).Cast<TEnum>().Max();}//When C# version is smaller than 7.3, use this:publicstaticTEnumGetMaxValueOld<TEnum>()whereTEnum:IComparable,IConvertible,IFormattable{Type type =typeof(TEnum);if(!type.IsSubclassOf(typeof(Enum)))thrownewInvalidCastException("Cannot cast '"+ type.FullName+"' to System.Enum.");return(TEnum)Enum.ToObject(type,Enum.GetValues(type).Cast<int>().Last());}enumMyEnum{ValueOne,ValueTwo}
VB:
PublicFunctionGetMaxValue _
(OfTEnumAs{IComparable,IConvertible,IFormattable})()AsTEnumDim type =GetType(TEnum)IfNot type.IsSubclassOf(GetType([Enum]))Then _
ThrowNewInvalidCastException _
("Cannot cast '"& type.FullName&"' to System.Enum.")Return[Enum].ToObject(type,[Enum].GetValues(type) _
.Cast(OfInteger).Last)EndFunction
możesz również dodać "struct" do swojego gdzie, ponieważ zapewni to, że jest to typ wartości, ale nie ogranicza go do Enum. To jest to, czego używam: gdzie T: struct, IComparable, IFormattable
jdawiz
2
Możesz zaktualizować swoją odpowiedź. W C # 7.3 można faktycznie wykonać metodę rozszerzenia, a także ograniczyć się do typu Enum (zamiast struct).
Nordes,
Nie jest to jednak metoda rozszerzająca . Ale dobra metoda użyteczności.
Ray
14
Jest to trochę dziwaczne, ale rzeczywista maksymalna wartość dowolnego enumto Int32.MaxValue(zakładając, że enumpochodzi z int). Całkowicie legalne jest rzutowanie dowolnej Int32wartości na dowolną, enumniezależnie od tego, czy faktycznie zadeklarowała ona członka o tej wartości.
Prawny:
enumSomeEnum{Fizz=42}publicstaticvoidSomeFunc(){SomeEnum e =(SomeEnum)5;}
Miałem przypadki, w których ustawienie zmiennej typu Integer na zwrócone wyliczenie kończy się niepowodzeniem z niedopasowaniem typu, gdy podano szaloną wartość, więc najlepiej zamiast tego użyć Long (jeśli leniwie nie przechwytujesz błędu poprawnie!).
AjV Jsy
9
Po ponownym wypróbowaniu otrzymałem tę metodę rozszerzenia:
... Jako słowo w słowo, mówiąc semantycznie, nie wydaje się to mieć aż tyle sensu? (zawsze dobrze jest mieć różne sposoby, ale nie widzę korzyści w tym drugim).
Użycie GetUpperBound zwraca dla mnie liczbę (4, a nie 40): MyEnum {a = 0, b = 10, c = 20, d = 30, e = 40}
alirobe
Niezły chwyt, nie zauważyłem tego. OK, więc ta wersja świetnie nadaje się do standardowych automatycznych wyliczeń, ale nie do wyliczeń z niestandardowymi wartościami. Myślę, że zwycięzcą pozostaje pan Hamilton. :)
Inżynier
GetUpperBound jest dobra, gdy Enum ma wartości bitowe. (tj. - 1, 2, 4, 8 itd.). Na przykład, jeśli piszesz test jednostkowy, chciałbyś przejść przez pętlę z tyloma iteracjami: Math.Pow (2, Enum.GetValues (typeof (MyEnum)). GetUpperBound (0)).
WEFX
Co jest nie tak z długością (dla liczby wartości w wyliczeniu)? Prostsze znaczy lepsze. (Nie żeby to odpowiadało na pierwotne pytanie.)
Ian Goldby
2
Istnieją metody uzyskiwania informacji o typach wyliczeniowych w System.Enum.
Tak więc w projekcie VB.Net w Visual Studio mogę wpisać „System.Enum”. a inteligencja przynosi wszelkiego rodzaju dobro.
W szczególności jedną z metod jest System.Enum.GetValues (), która zwraca tablicę wyliczonych wartości. Kiedy już masz tablicę, powinieneś być w stanie zrobić wszystko, co jest odpowiednie dla twoich szczególnych okoliczności.
W moim przypadku moje wyliczone wartości zaczynały się od zera i nie pomijały żadnych liczb, więc aby uzyskać maksymalną wartość dla mojego wyliczenia, muszę tylko wiedzieć, ile elementów było w tablicy.
Nie działa, gdy tablica ma przerwy. Działa to również przypadkowo, ponieważ indeks elementu jest równy wartości przechowywanej w tym indeksie. GetUpperBound()pobiera najwyższy możliwy indeks w tablicy zwrócony przez GetValues(), a nie najwyższą wartość przechowywaną w tej tablicy.
JensG
2
W F #, z funkcją pomocniczą, aby przekonwertować wyliczenie na sekwencję: In F #, with a helper function to convert the enum to a sequence:
type Foo=|Fizz=3|Bang=2// Helper function to convert enum to a sequence. This is also useful for iterating.// stackoverflow.com/questions/972307/can-you-loop-through-all-enum-values-cletToSeq(a :'A when 'A :enum<'B>)=Enum.GetValues(typeof<'A>).Cast<'B>()// Get the max of FooletFooMax=ToSeq(Foo())|>Seq.max
Uruchamiam to ...
> wpisz Foo = | Fizz = 3 | Bang = 2
> val ToSeq: 'A -> seq <' B> when 'A: enum <' B>
> val FooMax: Foo = Fizz
when 'A : enum<'B>Nie jest wymagane przez kompilator dla definicji, ale wymagana jest ich wykorzystanie ToSeq, nawet przy pomocy ważnego typu wyliczeniowego.
Nie nadaje się do użytku w każdych okolicznościach, ale często sam definiuję maksymalną wartość:
enumValues{
one,
two,
tree,End,}for(Values i =0; i <Values.End; i++){Console.WriteLine(i);}var random =newRandom();Console.WriteLine(random.Next((int)Values.End));
Oczywiście to nie zadziała, gdy używasz wartości niestandardowych w wyliczeniu, ale często może to być łatwe rozwiązanie.
Użyłem następujących, gdy potrzebowałem wartości minimalnej i maksymalnej mojego wyliczenia. Po prostu ustawiłem min równe najniższej wartości wyliczenia i maksimum równe najwyższej wartości w wyliczeniu jako same wartości wyliczeniowe.
publicenumChannelMessageTypes:byte{Min=0x80,// Or could be: Min = NoteOffNoteOff=0x80,NoteOn=0x90,PolyKeyPressure=0xA0,ControlChange=0xB0,ProgramChange=0xC0,ChannelAfterTouch=0xD0,PitchBend=0xE0,Max=0xE0// Or could be: Max = PitchBend}// I use it like this to check if a ... is a channel message.if(...>=ChannelMessageTypes.Min||...<=ChannelMessages.Max){Console.WriteLine("Channel message received!");}
Odpowiedzi:
Enum.GetValues () wydaje się zwracać wartości w kolejności, więc możesz zrobić coś takiego:
Edytować
Dla tych, którzy nie chcą czytać komentarzy: Możesz to również zrobić w ten sposób:
... co zadziała, gdy niektóre wartości wyliczenia są ujemne.
źródło
Zgadzam się z odpowiedzią Matta. Jeśli potrzebujesz tylko minimalnych i maksymalnych wartości int, możesz to zrobić w następujący sposób.
Maksymalny:
Minimum:
źródło
Zgodnie z odpowiedzią Matta Hamiltona, pomyślałem o stworzeniu dla niego metody rozszerzenia.
Ponieważ
ValueType
nie są akceptowane jako parametr typu rodzajowego przymusu, nie mogę znaleźć lepszy sposób, aby ograniczyćT
doEnum
ale następujący.Wszelkie pomysły byłyby naprawdę mile widziane.
PS. proszę zignoruj moją niejawność VB, uwielbiam używać VB w ten sposób, to jest siła VB i dlatego kocham VB.
Howeva, oto jest:
DO#:
VB:
źródło
Jest to trochę dziwaczne, ale rzeczywista maksymalna wartość dowolnego
enum
toInt32.MaxValue
(zakładając, żeenum
pochodzi zint
). Całkowicie legalne jest rzutowanie dowolnejInt32
wartości na dowolną,enum
niezależnie od tego, czy faktycznie zadeklarowała ona członka o tej wartości.Prawny:
źródło
Po ponownym wypróbowaniu otrzymałem tę metodę rozszerzenia:
źródło
Użyj funkcji Last nie może uzyskać maksymalnej wartości. Użyj funkcji „max”. Lubić:
źródło
W porozumieniu z Matthew J Sullivanem, dla C #:
Naprawdę nie jestem pewien, dlaczego ktoś miałby chcieć użyć:
... Jako słowo w słowo, mówiąc semantycznie, nie wydaje się to mieć aż tyle sensu? (zawsze dobrze jest mieć różne sposoby, ale nie widzę korzyści w tym drugim).
źródło
Istnieją metody uzyskiwania informacji o typach wyliczeniowych w System.Enum.
Tak więc w projekcie VB.Net w Visual Studio mogę wpisać „System.Enum”. a inteligencja przynosi wszelkiego rodzaju dobro.
W szczególności jedną z metod jest System.Enum.GetValues (), która zwraca tablicę wyliczonych wartości. Kiedy już masz tablicę, powinieneś być w stanie zrobić wszystko, co jest odpowiednie dla twoich szczególnych okoliczności.
W moim przypadku moje wyliczone wartości zaczynały się od zera i nie pomijały żadnych liczb, więc aby uzyskać maksymalną wartość dla mojego wyliczenia, muszę tylko wiedzieć, ile elementów było w tablicy.
Fragmenty kodu VB.Net:
źródło
GetUpperBound()
pobiera najwyższy możliwy indeks w tablicy zwrócony przezGetValues()
, a nie najwyższą wartość przechowywaną w tej tablicy.W F #, z funkcją pomocniczą, aby przekonwertować wyliczenie na sekwencję: In F #, with a helper function to convert the enum to a sequence:
Uruchamiam to ...
when 'A : enum<'B>
Nie jest wymagane przez kompilator dla definicji, ale wymagana jest ich wykorzystanie ToSeq, nawet przy pomocy ważnego typu wyliczeniowego.źródło
Nie nadaje się do użytku w każdych okolicznościach, ale często sam definiuję maksymalną wartość:
Oczywiście to nie zadziała, gdy używasz wartości niestandardowych w wyliczeniu, ale często może to być łatwe rozwiązanie.
źródło
Użyłem następujących, gdy potrzebowałem wartości minimalnej i maksymalnej mojego wyliczenia. Po prostu ustawiłem min równe najniższej wartości wyliczenia i maksimum równe najwyższej wartości w wyliczeniu jako same wartości wyliczeniowe.
źródło