3
votes

Obtenir la valeur maximale d'énumération à l'aide de génériques

Comment puis-je obtenir la valeur max int à partir d'une énumération en utilisant des génériques?

J'ai essayé ce qui suit mais cela affiche l'erreur de compilation suivante:

Impossible de convertir implicitement T en int

    int maxValue = GetMaxValue<SomeEnum>(typeof(SomeEnum)); //expecting 2

    private static int GetMaxValue<T>(Type enumType)
    {
        return Enum.GetValues(enumType).Cast<T>().Max();
    }

    public enum SomeEnum
    {
        ValueOne = 1,
        Value = 2
    }


2 commentaires

Enum ne peut être défini que comme int, pourquoi devriez-vous utiliser des génériques et essayer de les convertir?


@ALFA En fait, une énumération peut également être définie comme octet, court ou long


3 Réponses :


2
votes

Vous devez diffuser en int , pas en T . Et vous n'avez pas réellement besoin du paramètre Type (sauf si vous ne connaissez pas le type au moment de la compilation), car vous pouvez simplement faire typeof (T) :

private static U GetMaxValue<T, U>() where U : struct
{
    return Enum.GetValues(typeof(T)).Cast<U>().Max();
}

// usage:
GetMaxValue<SomeLongEnum, long>()

Si vos énumérations ont long ou un autre type comme type sous-jacent, vous pouvez spécifier un autre paramètre de type pour les convertir:

private static int GetMaxValue<T>()
{
    return Enum.GetValues(typeof(T)).Cast<int>().Max();
}

// usage:
GetMaxValue<SomeEnum>() // 2


7 commentaires

Cela ne fonctionnera pas si votre énumération est définie comme long (ou byte ou short ). Mieux vaut utiliser Convert.ToInt32 pour couvrir ces cas (bien que cela ne couvre évidemment pas le cas de débordement avec long , mais il n'y a aucun moyen de le couvrir avec cette signature)


Je pense que vous pouvez avoir une énumération longue simplement en la castant ( int est la valeur par défaut), donc lorsque vous renvoyez à int cela ne devrait pas créer des problèmes, non?


@ALFA Ce sera le cas si la valeur est supérieure à int.MaxValue


@KevinGosse Je pense que vous ne pouvez pas avoir une valeur plus grande que int.MaxValue si pour avoir une énumération longue vous devez d'abord lancer un int < / code> au type long .


Une énumération est un ensemble de constantes nommées dont le type sous-jacent est n'importe quel type intégral , Enum Class .


@ALFA Je ne sais pas pourquoi vous supposez que vous devez effectuer un cast de int à long. public enum SomeEnum: long {ValueOne = 30000000000} est valide


@KevinGosse vous avez raison, j'étais sûr que la seule façon d'avoir une longue énumération était de la lancer à partir d'une énumération int. Je l'ai maintenant merci :)



3
votes

Dans le cas de C # 7.3 ou version ultérieure, vous pouvez implémenter l'idée de Sweeper d'une manière un peu différente (avec l'aide de où T: Enum code> contrainte):

public static T GetMaxValue<T>() where T : Enum {
  return Enum.GetValues(typeof(T)).Cast<T>().Max();
}

...

SomeEnum max = GetMaxValue<SomeEnum>();

Veuillez noter que le résultat est enum lui-même et c'est pourquoi nous n'avons aucun problème avec le type sous-jacent enum ( octet , court int , long)


0 commentaires

0
votes

Utilisez Convert.ToInt32

public enum SomeEnum
{
    ValueOne = 1,
    Value = 2,
    END
}

return (int)(SomeEnum.END - 1);

Mais en général, je fais cela, plus rapidement que d'appeler GetValues ​​

 return Convert.ToInt32(Enum.GetValues(enumType).Cast<T>().Max());


0 commentaires