¿Cómo se obtiene el valor máximo de una enumeración?
¿Cómo se obtiene el valor máximo de una enumeración?
Respuestas:
Enum.GetValues () parece devolver los valores en orden, por lo que puede hacer algo como esto:
// given this enum:
public enum Foo
{
Fizz = 3,
Bar = 1,
Bang = 2
}
// this gets Fizz
var 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.
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:
Enum.GetValues(typeof(Foo)).Cast<int>().Max();
Mínimo:
Enum.GetValues(typeof(Foo)).Cast<int>().Min();
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 restringir T
a Enum
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á:
static void Main(string[] args)
{
MyEnum x = GetMaxValue<MyEnum>(); //In newer versions of C# (7.3+)
MyEnum y = GetMaxValueOld<MyEnum>();
}
public static TEnum GetMaxValue<TEnum>()
where TEnum : Enum
{
return Enum.GetValues(typeof(TEnum)).Cast<TEnum>().Max();
}
//When C# version is smaller than 7.3, use this:
public static TEnum GetMaxValueOld<TEnum>()
where TEnum : IComparable, IConvertible, IFormattable
{
Type type = typeof(TEnum);
if (!type.IsSubclassOf(typeof(Enum)))
throw new
InvalidCastException
("Cannot cast '" + type.FullName + "' to System.Enum.");
return (TEnum)Enum.ToObject(type, Enum.GetValues(type).Cast<int>().Last());
}
enum MyEnum
{
ValueOne,
ValueTwo
}
Public Function GetMaxValue _
(Of TEnum As {IComparable, IConvertible, IFormattable})() As TEnum
Dim type = GetType(TEnum)
If Not type.IsSubclassOf(GetType([Enum])) Then _
Throw New InvalidCastException _
("Cannot cast '" & type.FullName & "' to System.Enum.")
Return [Enum].ToObject(type, [Enum].GetValues(type) _
.Cast(Of Integer).Last)
End Function
Esto es un poco quisquilloso, pero el valor máximo real de cualquiera enum
es Int32.MaxValue
(suponiendo que se enum
deriva de int
). Es perfectamente legal emitir cualquier Int32
valor a cualquiera, enum
independientemente de si realmente declaró o no un miembro con ese valor.
Legal:
enum SomeEnum
{
Fizz = 42
}
public static void SomeFunc()
{
SomeEnum e = (SomeEnum)5;
}
Después de intentarlo otra vez, obtuve este método de extensión:
public static class EnumExtension
{
public static int Max(this Enum enumType)
{
return Enum.GetValues(enumType.GetType()).Cast<int>().Max();
}
}
class Program
{
enum enum1 { one, two, second, third };
enum enum2 { s1 = 10, s2 = 8, s3, s4 };
enum enum3 { f1 = -1, f2 = 3, f3 = -3, f4 };
static void Main(string[] args)
{
Console.WriteLine(enum1.one.Max());
}
}
Usar la última función no pudo obtener el valor máximo. Utilice la función "max" podría. Me gusta:
class Program
{
enum enum1 { one, two, second, third };
enum enum2 { s1 = 10, s2 = 8, s3, s4 };
enum enum3 { f1 = -1, f2 = 3, f3 = -3, f4 };
static void Main(string[] args)
{
TestMaxEnumValue(typeof(enum1));
TestMaxEnumValue(typeof(enum2));
TestMaxEnumValue(typeof(enum3));
}
static void TestMaxEnumValue(Type enumType)
{
Enum.GetValues(enumType).Cast<Int32>().ToList().ForEach(item =>
Console.WriteLine(item.ToString()));
int maxValue = Enum.GetValues(enumType).Cast<int>().Max();
Console.WriteLine("The max value of {0} is {1}", enumType.Name, maxValue);
}
}
De acuerdo con Matthew J Sullivan, para C #:
Enum.GetValues(typeof(MyEnum)).GetUpperBound(0);
Realmente no estoy seguro de por qué alguien querría usar:
Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().Last();
... 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).
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:
'''''''
Enum MattType
zerothValue = 0
firstValue = 1
secondValue = 2
thirdValue = 3
End Enum
'''''''
Dim iMax As Integer
iMax = System.Enum.GetValues(GetType(MattType)).GetUpperBound(0)
MessageBox.Show(iMax.ToString, "Max MattType Enum Value")
'''''''
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.
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-c
let ToSeq (a : 'A when 'A : enum<'B>) =
Enum.GetValues(typeof<'A>).Cast<'B>()
// Get the max of Foo
let FooMax = 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:
enum Values {
one,
two,
tree,
End,
}
for (Values i = 0; i < Values.End; i++) {
Console.WriteLine(i);
}
var random = new Random();
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.
public enum ChannelMessageTypes : byte
{
Min = 0x80, // Or could be: Min = NoteOff
NoteOff = 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!");
}