Question

Je souhaite créer une méthode générique pour la conversion de tout type dérivé de System.Enum à sa valeur entière correspondante, sans coulée et de préférence sans l'analyse d'une chaîne de caractères.

Par exemple, ce que je veux quelque chose comme ceci:

// 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 lancer l'expression de type 'System.Enum' taper 'int'.

Maintenant, je suis venu avec cette solution, mais je préfère avoir quelque chose de plus efficace.

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

Toutes les suggestions?

Était-ce utile?

La solution

Si vous ne voulez pas jeter,

Convert.ToInt32()

pourrait faire l'affaire.

La distribution directe (via (int)enumValue) est impossible. Notez que ce serait aussi « dangereux » car un ENUM peut avoir différents types sous-jacents (int, long, byte ...).

Plus formellement: System.Enum n'a pas de relation directe avec l'héritage Int32 (bien que les deux sont ValueTypes), de sorte que la distribution explicite ne peut pas être correct dans le système de type

Autres conseils

Je l'ai à travailler par coulée à un objet, puis à un int:

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

Ceci est laid et sans doute pas la meilleure façon. Je vais continuer à jouer avec elle, pour voir si je peux trouver quelque chose de mieux ....

EDIT:. Était sur le point de publier ce Convert.ToInt32 (enumValue) fonctionne aussi bien, et a remarqué que MartinStettner me devança

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

Test:

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 que dans C # 3.0. Je viens de tester cela dans VS2005 comme ça et ça a marché:

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));
    }

Si vous devez convertir any ENUM à son type sous-jacent (pas toutes les énumérations sont soutenus par int), vous pouvez utiliser:

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

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

Il est moins de frappe, 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();

De ma réponse :

Compte tenu 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 simplement laid. Le premier devrait être plus lisible, bien que le second est 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();

Castings d'un System.Enum à un int fonctionne bien pour moi (il est aussi sur la MSDN ). Peut-être est un bug de ReSharper.

Depuis énumérations sont limités à l'octet, sbyte, bref, ushort, int, uint, long et ulong, nous pouvons faire des hypothèses.

Nous pouvons éviter des exceptions lors de la conversion en utilisant le plus grand récipient disponible. Malheureusement, ce récipient à utiliser est pas clair parce que ulong va exploser pour les nombres négatifs et à long explosera pour les nombres entre long.MaxValue et ulong.MaxValue. Nous devons passer entre ces choix en fonction du type sous-jacent.

Bien sûr, vous avez encore besoin de décider quoi faire lorsque le résultat ne correspond pas à l'intérieur d'un int. Je pense que la coulée est correct, mais il y a encore quelques précautions:

  1. pour énumérations basée sur un type avec un espace de champ plus grand que int (long et ulong), il est possible que certains énumérations évalueront à la même valeur.
  2. Castings un plus grand nombre que Int.MaxValue va lancer une exception si vous êtes dans une région contrôlée.

Voici ma suggestion, je vais laisser au lecteur de décider où exposer cette fonction; comme une aide ou une extension.

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

Ne pas oublier que le type Enum lui-même a un tas de fonctions d'aide statiques en elle. Si tout ce que vous voulez faire est de convertir une instance de la ENUM à son type entier correspondant, puis coulée est probablement la façon la plus efficace.

Je pense que ReSharper se plaint parce que Enum n'est pas une énumération d'un type particulier, et énumérations eux-mêmes dérivent d'un valuetype scalaire, non Enum. Si vous avez besoin coulée adaptable de façon générique, je dirais que cela pourrait vous suite bien (notez que le type d'énumération lui-même est également inclus dans le générique:

public static EnumHelpers
{
    public static T Convert<T, E>(E enumValue)
    {
        return (T)enumValue;
    }
}

Cela pourrait alors être utilisé comme ceci:

public enum StopLight: int
{
    Red = 1,
    Yellow = 2,
    Green = 3
}

// ...

int myStoplightColor = EnumHelpers.Convert<int, StopLight>(StopLight.Red);

Je ne peux pas dire que du haut de ma tête, mais le code ci-dessus pourrait même être pris en charge par inférence de type de C #, ce qui permet ce qui suit:

int myStoplightColor = EnumHelpers.Convert<int>(StopLight.Red);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top