web-dev-qa-db-fra.com

Comment convertir des system.Enum en entier de base?

J'aimerais créer une méthode générique pour convertir tout type dérivé System.Enum en sa valeur entière correspondante, sans transtypage et de préférence sans analyser une chaîne.

Par exemple, ce que je veux, c'est quelque chose comme ça:

// Trivial example, not actually what I'm doing.
class Converter
{
    int ToInteger(System.Enum anEnum)
    {
        (int)anEnum;
    }
}

Mais cela ne semble pas fonctionner. Resharper signale que vous ne pouvez pas convertir l'expression de type 'System.Enum' en 'int'.

Maintenant, je propose cette solution mais je préférerais quelque chose de plus efficace.

class Converter
{
    int ToInteger(System.Enum anEnum)
    {
        return int.Parse(anEnum.ToString("d"));
    }
}

Aucune suggestion?

86
orj

Si vous ne voulez pas lancer,

Convert.ToInt32()

pourrait faire l'affaire. 

La diffusion directe (via (int)enumValue) n'est pas possible. Notez que cela serait également "dangereux" car une énumération peut avoir différents types sous-jacents (int, long, byte...). 

Plus formellement: System.Enum n'a pas de relation d'héritage directe avec Int32 (bien que les deux soient ValueTypes), la conversion explicite ne peut donc pas être correcte dans le système de types

125
MartinStettner

Je l’ai obtenu en travaillant sur un objet, puis sur un int:

public static class EnumExtensions
{
    public static int ToInt(this Enum enumValue)
    {
        return (int)((object)enumValue);
    }
}

C'est moche et probablement pas le meilleur moyen. Je vais continuer à jouer avec pour voir si je peux trouver quelque chose de mieux ...

EDIT: Était sur le point de publier que Convert.ToInt32 (enumValue) fonctionne également, et a remarqué que MartinStettner me battait.

public static class EnumExtensions
{
    public static int ToInt(this Enum enumValue)
    {
        return Convert.ToInt32(enumValue);
    }
}

Tester: 

int x = DayOfWeek.Friday.ToInt();
Console.WriteLine(x); // results in 5 which is int value of Friday

EDIT 2: Dans les commentaires, quelqu'un a dit que cela ne fonctionne qu'en C # 3.0. Je viens de tester cela dans VS2005 comme ça et cela a fonctionné:

public static class Helpers
{
    public static int ToInt(Enum enumValue)
    {
        return Convert.ToInt32(enumValue);
    }
}

    static void Main(string[] args)
    {
        Console.WriteLine(Helpers.ToInt(DayOfWeek.Friday));
    }
36
BFree

Si vous devez convertir any enum en son type sous-jacent (toutes les énumérations ne sont pas sauvegardées par int), vous pouvez utiliser:

return System.Convert.ChangeType(
    enumValue,
    Enum.GetUnderlyingType(enumValue.GetType()));
12
Drew Noakes

Pourquoi avez-vous besoin de réinventer la roue avec une méthode d'assistance? Il est parfaitement légal de convertir une valeur enum en son type sous-jacent.

C'est moins taper, et à mon avis plus lisible, à utiliser ...

int x = (int)DayOfWeek.Tuesday;

... plutôt que quelque chose comme ...

int y = Converter.ToInteger(DayOfWeek.Tuesday);
// or
int z = DayOfWeek.Tuesday.ToInteger();
11
LukeH

De ma réponse ici

e comme dans:

Enum e = Question.Role;

Ensuite, ces travaux:

int i = Convert.ToInt32(e);
int i = (int)(object)e;
int i = (int)Enum.Parse(e.GetType(), e.ToString());
int i = (int)Enum.ToObject(e.GetType(), e);

Les deux derniers sont tout simplement laids. Le premier devrait être plus lisible, bien que le second soit beaucoup plus rapide. Ou peut-être une méthode d'extension est le meilleur, le meilleur des deux mondes.

public static int GetIntValue(this Enum e)
{
    return e.GetValue<int>();
}

public static T GetValue<T>(this Enum e) where T : struct, IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T>
{
    return (T)(object)e;
}

Maintenant, vous pouvez appeler: 

e.GetValue<int>(); //or
e.GetIntValue();
4
nawfal

Transtyper un System.Enum dans une int me convient très bien (il s’agit également du MSDN ). C'est peut-être un bogue Resharper.

1
jpoh

Puisque les énumérations sont limitées à byte, sbyte, short, ushort, int, uint, long et ulong, nous pouvons faire certaines hypothèses.

Nous pouvons éviter les exceptions lors de la conversion en utilisant le plus grand conteneur disponible. Malheureusement, le conteneur à utiliser n'est pas clair car ulong explose pour les nombres négatifs et long pour les nombres compris entre long.MaxValue et ulong.MaxValue. Nous devons basculer entre ces choix en fonction du type sous-jacent. 

Bien sûr, vous devez encore décider quoi faire lorsque le résultat ne rentre pas dans un int. Je pense que le casting est correct, mais il y a encore des pièges:

  1. pour les énumérations basées sur un type dont le champ est supérieur à int (long et ulong), il est possible que certaines énumérations soient évaluées à la même valeur.
  2. lancer un nombre supérieur à int.MaxValue lève une exception si vous vous trouvez dans une région cochée.

Voici ma suggestion, je laisserai au lecteur le soin de décider où exposer cette fonction; comme aide ou extension.

public int ToInt(Enum e)
{
  unchecked
  {
    if (e.GetTypeCode() == TypeCode.UInt64)
      return (int)Convert.ToUInt64(e);
    else
      return (int)Convert.ToInt64(e);
  }
}
0
eisenpony