105 votes

Comment convertir System.Enum en entier de base ?

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

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 une expression de type 'System.Enum' en type 'int'.

J'ai trouvé cette solution, mais je préférerais avoir quelque chose de plus efficace.

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

Des suggestions ?

1 votes

Je crois que c'est le compilateur qui se plaint, pas Resharper.

1 votes

Pas nécessairement. J'ai une méthode d'extension sur System.Enum, et de temps en temps Resharper décide de se plaindre : Cannot convert instance argument type 'Some.Cool.Type.That.Is.An.Enum' to 'System.Enum' when it unquestionably IS an enum. Si je compile et exécute le code, il fonctionne parfaitement. Si j'arrête ensuite VS, que j'efface le cache de Resharper et que je le relance, tout va bien une fois qu'il a terminé le rescanning. Pour moi, c'est une sorte de problème de cache. C'est peut-être la même chose pour lui.

0 votes

@Mir j'ai eu ReSharper "se plaindre" sur ce point aussi. Même correction pour moi. Je ne sais pas pourquoi ces types sont mélangés, mais ce n'est certainement pas le compilateur.

158voto

MartinStettner Points 14514

Si vous ne voulez pas faire le casting,

Convert.ToInt32()

pourrait faire l'affaire.

Le casting direct (via (int)enumValue ) n'est pas possible. Notez que cela serait également "dangereux" puisqu'un enum 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 ValueType s), donc le cast explicite ne peut pas être correct dans le système de type

3 votes

Converter.ToInteger(MyEnum.MyEnumConstant); ne vous donnera aucune erreur ici. Veuillez modifier cette partie.

0 votes

Merci, @nawfal, vous avez raison. J'ai modifié la réponse (et appris quelque chose de nouveau :) ...)

0 votes

Ne fonctionne pas si le type sous-jacent diffère de int

49voto

BFree Points 46421

J'ai réussi à le faire fonctionner en le convertissant en objet, puis en int :

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

C'est laid et ce n'est probablement pas la meilleure façon. Je vais continuer à travailler dessus, pour voir si je peux trouver quelque chose de mieux. ....

EDIT : J'étais sur le point de poster que Convert.ToInt32(enumValue) fonctionne également, et j'ai remarqué que MartinStettner m'a devancé.

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 qu'en C# 3.0. Je viens de le tester dans VS2005 comme ceci 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));
    }

0 votes

Je vous ai donné +1 mais cette solution ne fonctionnera qu'avec C# 3.0 et plus.

0 votes

Je pense que cela ne satisfait que le compilateur. Avez-vous réussi à tester cela au moment de l'exécution ? Je n'ai pas pu passer de valeur à cette fonction...

0 votes

Parce que c'est une méthode d'extension ? Ou est-ce que les enums sont différents dans les anciennes versions de C# ?

9voto

LukeH Points 110965

Pourquoi devez-vous réinventer la roue avec une méthode d'aide ? Il est parfaitement légal de lancer une méthode enum à son type sous-jacent.

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

int x = (int)DayOfWeek.Tuesday;

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

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

6 votes

Je veux convertir n'importe quelle valeur d'un enum. C'est-à-dire que j'ai une variété de classes qui ont des champs enum qui sont traités par un certain code d'une manière générique. C'est pourquoi une simple conversion en int n'est pas appropriée.

0 votes

@orj, je ne suis pas vraiment sûr de ce que vous voulez dire. Pouvez-vous donner un exemple montrant l'utilisation dont vous avez besoin ?

2 votes

Parfois, il n'est pas possible d'intégrer directement un enum, comme dans le cas d'une méthode générique. Comme les méthodes génériques ne peuvent pas être contraintes à des enums, vous devez les contraindre à quelque chose comme struct, qui ne peut pas être converti en int. Dans ce cas, vous pouvez utiliser Convert.ToInt32(enum) pour le faire.

4voto

nawfal Points 13500

De ma réponse ici :

Étant donné que e comme dans :

Enum e = Question.Role;

Alors ceux-ci fonctionnent :

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 moches. La première devrait être plus lisible, bien que la seconde soit beaucoup plus rapide. Ou peut-être qu'une méthode d'extension est la meilleure, 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();

0 votes

Vous êtes sûr que le second est plus rapide ? Je suppose qu'il va mettre l'enum en boîte et ensuite revenir en int ?

1 votes

@yoyo le e a déjà l'instance encadrée du type de valeur réelle, c'est-à-dire l'enum. Lorsque vous écrivez Enum e = Question.Role; il est déjà emballé. La question est de savoir comment convertir la boîte System.Enum pour revenir au type int sous-jacent (unboxing). Ainsi, ici, l'unboxing n'est qu'un problème de performance. (int)(object)e est un appel direct à l'unbox ; oui devrait être plus rapide que les autres approches. Voir ceci

0 votes

Merci pour l'explication. J'avais l'impression erronée qu'une instance de System.Enum était une valeur non encadrée. Voir aussi ceci msdn.microsoft.com/fr/us/library/aa691158(v=vs.71).aspx

1voto

jpoh Points 2610

Coulée à partir d'un System.Enum à un int fonctionne bien pour moi (c'est aussi sur la page d'accueil du site web de l'UE). MSDN ). C'est peut-être un bug de Resharper.

1 votes

Quelle version du runtime utilisez-vous ?

2 votes

Le lien montre le moulage des sous-types de System.Enum pas System.Enum lui-même.

0 votes

Un problème similaire que j'ai rencontré était un problème de cache de Resharper. En fermant VS et en supprimant le cache de Resharper, l'erreur a disparu, même après un rescan complet.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X