Creo que el compilador podría manejar esto, en lugar de usar una llamada de Reflection. Una respuesta que utilizara un método de tiempo de compilación para esta información recibiría mi voto positivo.
palswim
Respuestas:
214
Enum.GetValues () parece devolver los valores en orden, por lo que puede hacer algo como esto:
// given this enum:publicenumFoo{Fizz=3,Bar=1,Bang=2}// this gets Fizzvar lastFoo =Enum.GetValues(typeof(Foo)).Cast<Foo>().Last();
Editar
Para aquellos que no están dispuestos a leer los comentarios: también puede hacerlo de esta manera:
var lastFoo =Enum.GetValues(typeof(Foo)).Cast<Foo>().Max();
... que funcionará cuando algunos de sus valores de enumeración sean negativos.
Estaba golpeándome la cabeza, pensando que esto era realmente trivial, pero se dio una solución elegante. Además, si desea obtener el valor de enumeración, use Convert.ToInt32 () después. Esto es para los resultados de google.
jdelator
54
Si va a usar LINQ, ¿por qué no usar Max (), que es mucho más claro y no se basa en "parece"?
Marc Gravell
3
Funciona mejor, pero solo si los valores de la enumeración no son negativos, lo que podrían ser.
ICR
44
Yo también voto por Max (). The Last () fallaría si enum no es negativo, mira aquí
AZ.
42
Estoy de acuerdo con la respuesta de Matt. Si necesita solo valores int mínimos y máximos, puede hacerlo de la siguiente manera.
Según la respuesta de Matt Hamilton, pensé en crear un método de extensión para ello.
Dado que ValueTypeno se acepta como una restricción parámetro de tipo genérico, no he encontrado una mejor manera de restringir Ta Enumpero el siguiente.
Cualquier idea sería muy apreciada.
PD. por favor ignore mi implícita VB, me encanta usar VB de esta manera, esa es la fortaleza de VB y por eso me encanta VB.
Howeva, aquí está:
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
también puede agregar "struct" a su ubicación, ya que esto garantizará que sea un ValueType pero no lo restrinja a Enum. Esto es lo que uso: where T: struct, IComparable, IFormattable
jdawiz
2
Podrías actualizar tu respuesta. En C # 7.3, en realidad podría hacer el método de extensión y también restringir al tipo Enum (en lugar de struct).
Nordes
Sin embargo, este no es un método de extensión . Pero un buen método de utilidad.
Ray
14
Esto es un poco quisquilloso, pero el valor máximo real de cualquiera enumes Int32.MaxValue(suponiendo que se enumderiva de int). Es perfectamente legal emitir cualquier Int32valor a cualquiera, enumindependientemente de si realmente declaró o no un miembro con ese valor.
Legal:
enumSomeEnum{Fizz=42}publicstaticvoidSomeFunc(){SomeEnum e =(SomeEnum)5;}
He tenido casos en los que establecer una variable Integer en una enumeración devuelta falla con la falta de coincidencia de tipos cuando se proporciona un valor loco, por lo que es mejor usar un Long en su lugar (¡si perezosamente no está atrapando el error correctamente!).
AjV Jsy
9
Después de intentarlo otra vez, obtuve este método de extensión:
... Como palabra por palabra, semánticamente hablando, ¿no parece tener tanto sentido? (siempre es bueno tener diferentes formas, pero no veo el beneficio en esta última).
Usar GetUpperBound devuelve un recuento (4, no 40) para mí: MyEnum {a = 0, b = 10, c = 20, d = 30, e = 40}
alirobe
Buena captura, no me había dado cuenta de eso. De acuerdo, esta versión es ideal para las entradas automáticas estándar, pero no para las enumeraciones con valores personalizados. Supongo que el ganador sigue siendo el señor Hamilton. :)
Ingeniero
GetUpperBound es bueno cuando su Enum tiene valores bit a bit. (es decir, 1, 2, 4, 8, etc.). Por ejemplo, si estuviera escribiendo una prueba unitaria, desearía trabajar a través de un bucle con esta cantidad de iteraciones: Math.Pow (2, Enum.GetValues (typeof (MyEnum)). GetUpperBound (0)).
WEFX
¿Qué tiene de malo la longitud (para el número de valores en la enumeración)? Más simple es mejor. (No es que esto responda a la pregunta original).
Ian Goldby
2
Hay métodos para obtener información sobre los tipos enumerados en System.Enum.
Entonces, en un proyecto VB.Net en Visual Studio, puedo escribir "System.Enum". y el intellisense trae todo tipo de bondad.
Un método en particular es System.Enum.GetValues (), que devuelve una matriz de los valores enumerados. Una vez que tenga la matriz, debería poder hacer lo que sea apropiado para sus circunstancias particulares.
En mi caso, mis valores enumerados comenzaron en cero y no omitieron números, por lo que para obtener el valor máximo de mi enumeración solo necesito saber cuántos elementos había en la matriz.
No funciona cuando la matriz tiene huecos. También funciona solo por accidente, porque el índice del elemento es igual al valor almacenado en ese índice. GetUpperBound()recupera el índice más alto posible en la matriz devuelta por GetValues(), no el valor más alto almacenado dentro de esa matriz.
JensG
2
En F #, con una función auxiliar para convertir la enumeración en una secuencia:
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
Ejecutándolo ...
> tipo Foo = | Fizz = 3 | Bang = 2
> val ToSeq: 'A -> seq <' B> cuando 'A: enumeración <' B>
> val FooMax: Foo = Fizz
No when 'A : enum<'B>es requerido por el compilador para la definición, pero es requerido para cualquier uso de ToSeq, incluso por un tipo de enumeración válido.
No es utilizable en todas las circunstancias, pero a menudo yo mismo defino el valor máximo:
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));
Por supuesto, esto no funcionará cuando use valores personalizados en una enumeración, pero a menudo puede ser una solución fácil.
Usé lo siguiente cuando necesitaba los valores mínimo y máximo de mi enumeración. Acabo de establecer un mínimo igual al valor más bajo de la enumeración y un máximo igual al valor más alto en la enumeración como valores enum.
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!");}
Respuestas:
Enum.GetValues () parece devolver los valores en orden, por lo que puede hacer algo como esto:
Editar
Para aquellos que no están dispuestos a leer los comentarios: también puede hacerlo de esta manera:
... que funcionará cuando algunos de sus valores de enumeración sean negativos.
fuente
Estoy de acuerdo con la respuesta de Matt. Si necesita solo valores int mínimos y máximos, puede hacerlo de la siguiente manera.
Máximo:
Mínimo:
fuente
Según la respuesta de Matt Hamilton, pensé en crear un método de extensión para ello.
Dado que
ValueType
no se acepta como una restricción parámetro de tipo genérico, no he encontrado una mejor manera de restringirT
aEnum
pero el siguiente.Cualquier idea sería muy apreciada.
PD. por favor ignore mi implícita VB, me encanta usar VB de esta manera, esa es la fortaleza de VB y por eso me encanta VB.
Howeva, aquí está:
C#:
VB:
fuente
Esto es un poco quisquilloso, pero el valor máximo real de cualquiera
enum
esInt32.MaxValue
(suponiendo que seenum
deriva deint
). Es perfectamente legal emitir cualquierInt32
valor a cualquiera,enum
independientemente de si realmente declaró o no un miembro con ese valor.Legal:
fuente
Después de intentarlo otra vez, obtuve este método de extensión:
fuente
Usar la última función no pudo obtener el valor máximo. Utilice la función "max" podría. Me gusta:
fuente
De acuerdo con Matthew J Sullivan, para C #:
Realmente no estoy seguro de por qué alguien querría usar:
... Como palabra por palabra, semánticamente hablando, ¿no parece tener tanto sentido? (siempre es bueno tener diferentes formas, pero no veo el beneficio en esta última).
fuente
Hay métodos para obtener información sobre los tipos enumerados en System.Enum.
Entonces, en un proyecto VB.Net en Visual Studio, puedo escribir "System.Enum". y el intellisense trae todo tipo de bondad.
Un método en particular es System.Enum.GetValues (), que devuelve una matriz de los valores enumerados. Una vez que tenga la matriz, debería poder hacer lo que sea apropiado para sus circunstancias particulares.
En mi caso, mis valores enumerados comenzaron en cero y no omitieron números, por lo que para obtener el valor máximo de mi enumeración solo necesito saber cuántos elementos había en la matriz.
Fragmentos de código VB.Net:
fuente
GetUpperBound()
recupera el índice más alto posible en la matriz devuelta porGetValues()
, no el valor más alto almacenado dentro de esa matriz.En F #, con una función auxiliar para convertir la enumeración en una secuencia:
Ejecutándolo ...
No
when 'A : enum<'B>
es requerido por el compilador para la definición, pero es requerido para cualquier uso de ToSeq, incluso por un tipo de enumeración válido.fuente
No es utilizable en todas las circunstancias, pero a menudo yo mismo defino el valor máximo:
Por supuesto, esto no funcionará cuando use valores personalizados en una enumeración, pero a menudo puede ser una solución fácil.
fuente
Usé lo siguiente cuando necesitaba los valores mínimo y máximo de mi enumeración. Acabo de establecer un mínimo igual al valor más bajo de la enumeración y un máximo igual al valor más alto en la enumeración como valores enum.
fuente