Ich würde denken, dass der Compiler damit umgehen könnte, anstatt einen Reflection-Aufruf zu verwenden. Eine Antwort, die eine Methode zur Kompilierungszeit für diese Informationen verwendet, würde meine Zustimmung erhalten.
Palswim
Antworten:
214
Enum.GetValues () scheint die Werte in der angegebenen Reihenfolge zurückzugeben, sodass Sie Folgendes tun können:
// given this enum:publicenumFoo{Fizz=3,Bar=1,Bang=2}// this gets Fizzvar lastFoo =Enum.GetValues(typeof(Foo)).Cast<Foo>().Last();
Bearbeiten
Für diejenigen, die nicht bereit sind, die Kommentare durchzulesen: Sie können dies auch folgendermaßen tun:
var lastFoo =Enum.GetValues(typeof(Foo)).Cast<Foo>().Max();
... was funktioniert, wenn einige Ihrer Aufzählungswerte negativ sind.
Ich schlug mir auf den Kopf und dachte, das sei wirklich trival, aber es wurde eine elegante Lösung gegeben. Wenn Sie den Aufzählungswert erhalten möchten, verwenden Sie anschließend Convert.ToInt32 (). Dies ist für die Google-Ergebnisse.
jdelator
53
Wenn Sie LINQ verwenden möchten, verwenden Sie Max (), das viel klarer ist und sich nicht auf "scheint" verlässt.
Marc Gravell
3
Es funktioniert besser, aber nur, wenn die Werte der Aufzählung nicht negativ sind, was sie sein könnten.
ICR
4
Ich stimme auch für Max (). The Last () würde fehlschlagen, wenn die Aufzählung nicht negativ ist, siehe hier
AZ.
41
Ich stimme Matts Antwort zu. Wenn Sie nur minimale und maximale int-Werte benötigen, können Sie dies wie folgt tun.
Nach der Antwort von Matt Hamilton habe ich darüber nachgedacht, eine Erweiterungsmethode dafür zu erstellen.
Da dies ValueTypenicht als generische Einschränkung für Typparameter akzeptiert wird, habe ich keinen besseren Weg gefunden, mich Tauf EnumFolgendes zu beschränken .
Irgendwelche Ideen wären sehr dankbar.
PS. Bitte ignorieren Sie meine VB-Implizität. Ich liebe es, VB auf diese Weise zu verwenden. Das ist die Stärke von VB und deshalb liebe ich VB.
Howeva, hier ist es:
C #:
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
Sie können auch "struct" zu Ihrem where hinzufügen, da dies sicherstellt, dass es sich um einen ValueType handelt, aber nicht auf Enum beschränkt. Dies ist, was ich verwende: where T: struct, IComparable, IFormattable
jdawiz
2
Sie können Ihre Antwort aktualisieren. In C # 7.3 können Sie die Erweiterungsmethode tatsächlich ausführen und sich auch auf den Enum-Typ beschränken (anstelle von struct).
Nordes
Dies ist jedoch keine Erweiterungsmethode . Aber eine gute Gebrauchsmethode.
Ray
14
Dies ist etwas pingelig, aber der tatsächliche Maximalwert von jedem enumist Int32.MaxValue(vorausgesetzt, es ist ein enumabgeleiteter von int). Es ist völlig legal, einen Int32Wert in einen beliebigen Wert umzuwandeln, enumunabhängig davon, ob tatsächlich ein Mitglied mit diesem Wert deklariert wurde oder nicht.
Legal:
enumSomeEnum{Fizz=42}publicstaticvoidSomeFunc(){SomeEnum e =(SomeEnum)5;}
Ich hatte Fälle, in denen das Setzen einer Integer-Variablen auf eine zurückgegebene Enumeration mit einer Nichtübereinstimmung des Typs fehlschlägt, wenn ein verrückter Wert angegeben wird. Verwenden Sie stattdessen am besten ein Long (wenn Sie den Fehler träge nicht richtig abfangen!).
AjV Jsy
9
Nachdem ich es ein anderes Mal versucht hatte, bekam ich diese Erweiterungsmethode:
... Semantisch gesehen scheint es Wort für Wort nicht so sinnvoll zu sein? (Es ist immer gut, verschiedene Wege zu haben, aber ich sehe den Nutzen in letzterem nicht.)
Die Verwendung von GetUpperBound gibt für mich eine Anzahl (4, nicht 40) zurück: MyEnum {a = 0, b = 10, c = 20, d = 30, e = 40}
alirobe
Netter Fang, das hatte ich nicht bemerkt. OK, diese Version eignet sich hervorragend für Standard-Auto-Enums, jedoch nicht für Enums mit benutzerdefinierten Werten. Ich denke, der Gewinner bleibt Herr Hamilton. :)
Ingenieur
GetUpperBound ist gut, wenn Ihre Aufzählung bitweise Werte hat. (dh - 1, 2, 4, 8 usw.). Wenn Sie beispielsweise einen Komponententest schreiben, möchten Sie eine Schleife mit so vielen Iterationen durcharbeiten: Math.Pow (2, Enum.GetValues (typeof (MyEnum)). GetUpperBound (0)).
WEFX
Was ist los mit Länge (für die Anzahl der Werte in der Aufzählung)? Einfacher ist besser. (Nicht, dass dies die ursprüngliche Frage beantwortet.)
Ian Goldby
2
Unter System.Enum gibt es Methoden zum Abrufen von Informationen zu Aufzählungstypen.
In einem VB.Net-Projekt in Visual Studio kann ich also "System.Enum" eingeben. und der Intellisense bringt alle Arten von Güte hervor.
Eine Methode ist insbesondere System.Enum.GetValues (), die ein Array der aufgezählten Werte zurückgibt. Sobald Sie das Array haben, sollten Sie in der Lage sein, alles zu tun, was für Ihre besonderen Umstände angemessen ist.
In meinem Fall begannen meine Aufzählungswerte bei Null und übersprangen keine Zahlen. Um den Maximalwert für meine Aufzählung zu erhalten, muss ich nur wissen, wie viele Elemente sich im Array befanden.
Funktioniert nicht, wenn das Array Lücken aufweist. Es funktioniert auch nur aus Versehen, da der Elementindex zufällig dem in diesem Index gespeicherten Wert entspricht. GetUpperBound()Ruft den höchstmöglichen Index in dem von zurückgegebenen Array ab GetValues(), nicht den höchsten in diesem Array gespeicherten Wert.
JensG
2
In F # mit einer Hilfsfunktion zum Konvertieren der Aufzählung in eine Sequenz:
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
Laufen es ...
> Geben Sie Foo = | ein Fizz = 3 | Bang = 2
> val ToSeq: 'A -> seq <' B> wenn 'A: enum <' B>
> val FooMax: Foo = Fizz
Das when 'A : enum<'B>wird vom Compiler für die Definition nicht benötigt, ist jedoch für jede Verwendung von ToSeq erforderlich, selbst für einen gültigen Aufzählungstyp.
Es ist nicht unter allen Umständen verwendbar, aber ich definiere den Maximalwert oft selbst:
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));
Dies funktioniert natürlich nicht, wenn Sie benutzerdefinierte Werte in einer Aufzählung verwenden, aber häufig kann dies eine einfache Lösung sein.
Ich habe Folgendes verwendet, als ich die Min- und Max-Werte meiner Aufzählung benötigte. Ich habe gerade ein min gleich dem niedrigsten Wert der Aufzählung und ein max gleich dem höchsten Wert in der Aufzählung als Aufzählungswerte selbst gesetzt.
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!");}
Antworten:
Enum.GetValues () scheint die Werte in der angegebenen Reihenfolge zurückzugeben, sodass Sie Folgendes tun können:
Bearbeiten
Für diejenigen, die nicht bereit sind, die Kommentare durchzulesen: Sie können dies auch folgendermaßen tun:
... was funktioniert, wenn einige Ihrer Aufzählungswerte negativ sind.
quelle
Ich stimme Matts Antwort zu. Wenn Sie nur minimale und maximale int-Werte benötigen, können Sie dies wie folgt tun.
Maximal:
Minimum:
quelle
Nach der Antwort von Matt Hamilton habe ich darüber nachgedacht, eine Erweiterungsmethode dafür zu erstellen.
Da dies
ValueType
nicht als generische Einschränkung für Typparameter akzeptiert wird, habe ich keinen besseren Weg gefunden, michT
aufEnum
Folgendes zu beschränken .Irgendwelche Ideen wären sehr dankbar.
PS. Bitte ignorieren Sie meine VB-Implizität. Ich liebe es, VB auf diese Weise zu verwenden. Das ist die Stärke von VB und deshalb liebe ich VB.
Howeva, hier ist es:
C #:
VB:
quelle
Dies ist etwas pingelig, aber der tatsächliche Maximalwert von jedem
enum
istInt32.MaxValue
(vorausgesetzt, es ist einenum
abgeleiteter vonint
). Es ist völlig legal, einenInt32
Wert in einen beliebigen Wert umzuwandeln,enum
unabhängig davon, ob tatsächlich ein Mitglied mit diesem Wert deklariert wurde oder nicht.Legal:
quelle
Nachdem ich es ein anderes Mal versucht hatte, bekam ich diese Erweiterungsmethode:
quelle
Verwenden Sie die Funktion Letzte konnte den Maximalwert nicht erhalten. Verwenden Sie die Funktion "max". Mögen:
quelle
In Übereinstimmung mit Matthew J Sullivan für C #:
Ich bin mir wirklich nicht sicher, warum jemand Folgendes verwenden möchte:
... Semantisch gesehen scheint es Wort für Wort nicht so sinnvoll zu sein? (Es ist immer gut, verschiedene Wege zu haben, aber ich sehe den Nutzen in letzterem nicht.)
quelle
Unter System.Enum gibt es Methoden zum Abrufen von Informationen zu Aufzählungstypen.
In einem VB.Net-Projekt in Visual Studio kann ich also "System.Enum" eingeben. und der Intellisense bringt alle Arten von Güte hervor.
Eine Methode ist insbesondere System.Enum.GetValues (), die ein Array der aufgezählten Werte zurückgibt. Sobald Sie das Array haben, sollten Sie in der Lage sein, alles zu tun, was für Ihre besonderen Umstände angemessen ist.
In meinem Fall begannen meine Aufzählungswerte bei Null und übersprangen keine Zahlen. Um den Maximalwert für meine Aufzählung zu erhalten, muss ich nur wissen, wie viele Elemente sich im Array befanden.
VB.Net-Code-Schnipsel:
quelle
GetUpperBound()
Ruft den höchstmöglichen Index in dem von zurückgegebenen Array abGetValues()
, nicht den höchsten in diesem Array gespeicherten Wert.In F # mit einer Hilfsfunktion zum Konvertieren der Aufzählung in eine Sequenz:
Laufen es ...
Das
when 'A : enum<'B>
wird vom Compiler für die Definition nicht benötigt, ist jedoch für jede Verwendung von ToSeq erforderlich, selbst für einen gültigen Aufzählungstyp.quelle
Es ist nicht unter allen Umständen verwendbar, aber ich definiere den Maximalwert oft selbst:
Dies funktioniert natürlich nicht, wenn Sie benutzerdefinierte Werte in einer Aufzählung verwenden, aber häufig kann dies eine einfache Lösung sein.
quelle
Ich habe Folgendes verwendet, als ich die Min- und Max-Werte meiner Aufzählung benötigte. Ich habe gerade ein min gleich dem niedrigsten Wert der Aufzählung und ein max gleich dem höchsten Wert in der Aufzählung als Aufzählungswerte selbst gesetzt.
quelle