Je pense que le compilateur pourrait gérer cela, plutôt que d'utiliser un appel Reflection. Une réponse utilisant une méthode de compilation pour cette information recevrait mon vote favorable.
palswim
Réponses:
214
Enum.GetValues () semble renvoyer les valeurs dans l'ordre, vous pouvez donc faire quelque chose comme ceci:
// given this enum:publicenumFoo{Fizz=3,Bar=1,Bang=2}// this gets Fizzvar lastFoo =Enum.GetValues(typeof(Foo)).Cast<Foo>().Last();
Éditer
Pour ceux qui ne veulent pas lire les commentaires: vous pouvez également le faire de cette façon:
var lastFoo =Enum.GetValues(typeof(Foo)).Cast<Foo>().Max();
... qui fonctionnera lorsque certaines de vos valeurs d'énumération sont négatives.
Je me cognais la tête, pensant que c'était vraiment trival mais une solution élégante a été donnée. Aussi, si vous voulez obtenir la valeur d'énumération, utilisez ensuite Convert.ToInt32 (). Ceci est pour les résultats Google.
jdelator
54
Si vous allez utiliser LINQ, pourquoi ne pas utiliser Max (), qui est beaucoup plus clair et ne se fie pas au "semble-t-il"?
Marc Gravell
3
Il fonctionne mieux, mais seulement si les valeurs de l'énumération ne sont pas négatives, ce qu'elles pourraient être.
ICR
4
Je vote aussi pour Max (). Le dernier () échouerait si enum n'est pas négatif, voir ici
AZ.
42
Je suis d'accord avec la réponse de Matt. Si vous n'avez besoin que de valeurs min et max int, vous pouvez le faire comme suit.
Selon la réponse de Matt Hamilton, j'ai pensé à créer une méthode d'extension pour cela.
Étant donné que ValueTypen'est pas acceptée comme une contrainte de paramètre de type générique, je ne l' ai pas trouvé une meilleure façon de limiter Tà , Enummais ce qui suit.
Toutes les idées seraient vraiment appréciées.
PS. s'il vous plaît ignorer mon implicite VB, j'aime utiliser VB de cette façon, c'est la force de VB et c'est pourquoi j'aime VB.
Howeva, la voici:
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
vous pouvez également ajouter "struct" à votre where car cela garantira qu'il s'agit d'un ValueType mais ne le limitera pas à Enum C'est ce que j'utilise: where T: struct, IComparable, IFormattable
jdawiz
2
Vous pouvez mettre à jour votre réponse. En C # 7.3, vous pouvez en fait utiliser la méthode d'extension et vous limiter au type Enum (au lieu de struct).
Nordes
Ce n'est cependant pas une méthode d' extension . Mais une bonne méthode utilitaire.
Ray
14
C'est légèrement pointilleux, mais la valeur maximale réelle de tout enumest Int32.MaxValue(en supposant que ce soit un enumdérivé de int). Il est parfaitement légal de jeter toute Int32valeur à un tout , enumpeu importe si oui ou non elle a effectivement déclaré un membre à cette valeur.
Légal:
enumSomeEnum{Fizz=42}publicstaticvoidSomeFunc(){SomeEnum e =(SomeEnum)5;}
J'ai eu des cas où la définition d'une variable Integer sur une énumération retournée échoue avec une incompatibilité de type lorsqu'une valeur folle est fournie, il est donc préférable d'utiliser un Long à la place (si vous ne traquez pas correctement l'erreur paresseusement!).
AjV Jsy
9
Après avoir essayé une autre fois, j'ai eu cette méthode d'extension:
... Comme mot pour mot, sémantiquement parlant, cela ne semble pas avoir autant de sens? (toujours bon d'avoir des manières différentes, mais je ne vois pas l'avantage dans ce dernier.)
L'utilisation de GetUpperBound renvoie un nombre (4, pas 40) pour moi: MyEnum {a = 0, b = 10, c = 20, d = 30, e = 40}
alirobe
Belle prise, je n'avais pas remarqué ça. OK, donc cette version est idéale pour les énumérations automatiques standard, mais pas pour les énumérations avec des valeurs personnalisées. Je suppose que le gagnant reste M. Hamilton. :)
Ingénieur
GetUpperBound est bon lorsque votre Enum a des valeurs au niveau du bit. (c'est-à-dire - 1, 2, 4, 8, etc.). Par exemple, si vous écriviez un test unitaire, vous voudriez travailler sur une boucle avec autant d'itérations: Math.Pow (2, Enum.GetValues (typeof (MyEnum)). GetUpperBound (0)).
WEFX
Quel est le problème avec Length (pour le nombre de valeurs dans l'énumération)? Le plus simple, c'est mieux. (Non pas que cela réponde à la question d'origine.)
Ian Goldby
2
Il existe des méthodes pour obtenir des informations sur les types énumérés sous System.Enum.
Ainsi, dans un projet VB.Net dans Visual Studio, je peux taper «System.Enum». et l'intellisense évoque toutes sortes de bontés.
Une méthode en particulier est System.Enum.GetValues (), qui renvoie un tableau des valeurs énumérées. Une fois que vous avez le tableau, vous devriez être en mesure de faire ce qui convient à votre situation particulière.
Dans mon cas, mes valeurs énumérées ont commencé à zéro et n'ont ignoré aucun nombre, donc pour obtenir la valeur maximale de mon énumération, j'ai juste besoin de savoir combien d'éléments se trouvaient dans le tableau.
Ne fonctionne pas lorsque la matrice présente des espaces. Cela ne fonctionne également que par accident, car l'index d'élément est égal à la valeur stockée à cet index. GetUpperBound()récupère l' index le plus élevé possible dans le tableau renvoyé par GetValues(), et non la valeur la plus élevée stockée dans ce tableau.
JensG
2
En F #, avec une fonction d'assistance pour convertir l'énumération en séquence:
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
L'exécution ...
> tapez Foo = | Fizz = 3 | Bang = 2
> val ToSeq: 'A -> seq <' B> quand 'A: enum <' B>
> val FooMax: Foo = Fizz
Le when 'A : enum<'B>n'est pas requis par le compilateur pour la définition, mais est requis pour toute utilisation de ToSeq, même par un type enum valide.
Il n'est pas utilisable en toutes circonstances, mais je définis souvent moi-même la valeur max:
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));
Bien sûr, cela ne fonctionnera pas lorsque vous utilisez des valeurs personnalisées dans une énumération, mais cela peut souvent être une solution simple.
J'ai utilisé ce qui suit lorsque j'avais besoin des valeurs min et max de mon enum. Je viens de définir un min égal à la valeur la plus basse de l'énumération et un max égal à la valeur la plus élevée de l'énumération en tant que valeurs d'énumération elles-mêmes.
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!");}
Réponses:
Enum.GetValues () semble renvoyer les valeurs dans l'ordre, vous pouvez donc faire quelque chose comme ceci:
Éditer
Pour ceux qui ne veulent pas lire les commentaires: vous pouvez également le faire de cette façon:
... qui fonctionnera lorsque certaines de vos valeurs d'énumération sont négatives.
la source
Je suis d'accord avec la réponse de Matt. Si vous n'avez besoin que de valeurs min et max int, vous pouvez le faire comme suit.
Maximum:
Le minimum:
la source
Selon la réponse de Matt Hamilton, j'ai pensé à créer une méthode d'extension pour cela.
Étant donné que
ValueType
n'est pas acceptée comme une contrainte de paramètre de type générique, je ne l' ai pas trouvé une meilleure façon de limiterT
à ,Enum
mais ce qui suit.Toutes les idées seraient vraiment appréciées.
PS. s'il vous plaît ignorer mon implicite VB, j'aime utiliser VB de cette façon, c'est la force de VB et c'est pourquoi j'aime VB.
Howeva, la voici:
C #:
VB:
la source
C'est légèrement pointilleux, mais la valeur maximale réelle de tout
enum
estInt32.MaxValue
(en supposant que ce soit unenum
dérivé deint
). Il est parfaitement légal de jeter touteInt32
valeur à un tout ,enum
peu importe si oui ou non elle a effectivement déclaré un membre à cette valeur.Légal:
la source
Après avoir essayé une autre fois, j'ai eu cette méthode d'extension:
la source
L'utilisation de la fonction Dernière n'a pas pu obtenir la valeur maximale. Utilisez la fonction "max" pourrait. Comme:
la source
En accord avec Matthew J Sullivan, pour C #:
Je ne sais vraiment pas pourquoi quelqu'un voudrait utiliser:
... Comme mot pour mot, sémantiquement parlant, cela ne semble pas avoir autant de sens? (toujours bon d'avoir des manières différentes, mais je ne vois pas l'avantage dans ce dernier.)
la source
Il existe des méthodes pour obtenir des informations sur les types énumérés sous System.Enum.
Ainsi, dans un projet VB.Net dans Visual Studio, je peux taper «System.Enum». et l'intellisense évoque toutes sortes de bontés.
Une méthode en particulier est System.Enum.GetValues (), qui renvoie un tableau des valeurs énumérées. Une fois que vous avez le tableau, vous devriez être en mesure de faire ce qui convient à votre situation particulière.
Dans mon cas, mes valeurs énumérées ont commencé à zéro et n'ont ignoré aucun nombre, donc pour obtenir la valeur maximale de mon énumération, j'ai juste besoin de savoir combien d'éléments se trouvaient dans le tableau.
Extraits de code VB.Net:
la source
GetUpperBound()
récupère l' index le plus élevé possible dans le tableau renvoyé parGetValues()
, et non la valeur la plus élevée stockée dans ce tableau.En F #, avec une fonction d'assistance pour convertir l'énumération en séquence:
L'exécution ...
Le
when 'A : enum<'B>
n'est pas requis par le compilateur pour la définition, mais est requis pour toute utilisation de ToSeq, même par un type enum valide.la source
Il n'est pas utilisable en toutes circonstances, mais je définis souvent moi-même la valeur max:
Bien sûr, cela ne fonctionnera pas lorsque vous utilisez des valeurs personnalisées dans une énumération, mais cela peut souvent être une solution simple.
la source
J'ai utilisé ce qui suit lorsque j'avais besoin des valeurs min et max de mon enum. Je viens de définir un min égal à la valeur la plus basse de l'énumération et un max égal à la valeur la plus élevée de l'énumération en tant que valeurs d'énumération elles-mêmes.
la source