Pregunta

¿Cómo se obtiene el valor máximo de una enumeración?

¿Fue útil?

Solución

Enum.GetValues() parece devolver los valores en orden, por lo que puedes 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 puedes 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.

Otros consejos

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 de parámetro de tipo genérico, no encontré una mejor manera de restringir T a Enum sino lo siguiente.

Cualquier idea sería muy apreciada.

PS. ignore mi implícita VB, me encanta usar VB de esta manera, esa es la fortaleza de VB y es por eso que amo VB.

Howeva, aquí está:

C #:

static void Main(string[] args)
{
    MyEnum x = GetMaxValue<MyEnum>();
}

public static TEnum GetMaxValue<TEnum>() 
    where TEnum : IComparable, IConvertible, IFormattable
    //In C#>=7.3 substitute with 'where TEnum : Enum', and remove the following check:
{
    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
}

VB:

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 complicado, pero el valor máximo real de cualquier enumeración es Int32.MaxValue (suponiendo que sea una enumeración derivada de int). Es perfectamente legal emitir cualquier valor Int32 a cualquier enumeración, 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 en otra ocasión, 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 el & Quot; max & Quot; La función 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).

Existen 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 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 ningún número, por lo que para obtener el valor máximo para mi enumeración solo necesito saber cuántos elementos había en la matriz.

Fragmentos de código de 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")

'''''''

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   

Ejecutarlo ...

> type Foo = | Fizz = 3 | Bang = 2
> val ToSeq : 'A -> seq<'B> when 'A : enum<'B>
> val FooMax : Foo = Fizz

El compilador no requiere when 'A : enum<'B> para la definición, pero se requiere 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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top