Comment lancer int pour énumérer?

3196

Comment convertir un intan enumen C #?

lomaxx
la source

Réponses:

3795

À partir d'une chaîne:

YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString);

// The foo.ToString().Contains(",") check is necessary for enumerations marked with an [Flags] attribute
if (!Enum.IsDefined(typeof(YourEnum), foo) && !foo.ToString().Contains(","))
{
    throw new InvalidOperationException($"{yourString} is not an underlying value of the YourEnum enumeration.")
}

D'un int:

YourEnum foo = (YourEnum)yourInt;

Mise à jour:

De nombre, vous pouvez également

YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);
FlySwat
la source
31
@FlySwat, que se passe-t-il si YourEnumest dynamique et ne sera connu qu'au moment de l'exécution, et que je veux convertir Enum?
Shimmy Weitzhandler
226
Sachez que Enum.Parse ne fonctionnera PAS si votre code est obscurci. Au moment de l'exécution après l'obscurcissement, la chaîne est comparée aux noms d'énumération, et à ce stade, les noms des énumérations ne sont pas ce que vous attendez d'eux. Votre analyse échouera là où ils ont réussi auparavant.
jropella
158
ATTENTION Si vous utilisez la syntaxe "à partir d'une chaîne" ci-dessus et que vous transmettez une chaîne non valide qui est un nombre (par exemple "2342342" - en supposant que ce n'est pas une valeur de votre énumération), cela permettra effectivement cela sans générer d'erreur! Votre énumération aura cette valeur (2342342) même si ce n'est pas un choix valide dans l'énumération elle-même.
JoeCool
132
Je pense que cette réponse est un peu datée maintenant. Pour la chaîne, vous devriez vraiment utiliser de var result = Enum.TryParse(yourString, out yourEnum)nos jours (et vérifier le résultat pour déterminer si la conversion a échoué).
Justin T Conroy
20
Il est également possible d'avoir Enum.Parseété insensible à la casse en ajoutant une truevaleur de paramètre à l'appel:YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString, true);
Erik Schierboom
900

Il suffit de le lancer:

MyEnum e = (MyEnum)3;

Vous pouvez vérifier si elle est à portée en utilisant Enum.IsDefined :

if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }
Matt Hamilton
la source
218
Attention, vous ne pouvez pas utiliser Enum.IsDefined si vous utilisez l'attribut Flags et que la valeur est une combinaison d'indicateurs par exemple: Keys.L | Keys.Control
dtroy
15
Concernant Enum.IsDefined, sachez que cela peut être dangereux: msdn.microsoft.com/en-us/library/ms229025(VS.90).aspx
adrian
3
Je préfère cette définition: "Retourne une indication si une constante avec une valeur spécifiée existe dans une énumération spécifiée" de MSDN
Pap
3
... Parce que votre définition peut être trompeuse, parce que vous dites: "... vérifiez si elle est dans la plage ..." ce qui implique dans une plage de nombres avec des limites de début et de fin ...
Pap
3
@ mac9416 J'ai essayé de donner un exemple succinct sur gist.github.com/alowdon/f7354cda97bac70b44e1c04bc0991bcc - en gros, en utilisant IsDefinedpour vérifier les valeurs d'entrée, vous vous exposez aux personnes qui ajoutent de nouvelles valeurs d'énumération plus tard qui passeraient un IsDefinedcontrôle (depuis la nouvelle existe dans le nouveau code), mais qui pourrait ne pas fonctionner avec le code d'origine que vous avez écrit. Il est donc plus sûr de spécifier explicitement les valeurs d'énumération que votre code est capable de gérer.
adrian
238

Vous pouvez également utiliser une méthode d'extension au lieu d'une ligne unique:

public static T ToEnum<T>(this string enumString)
{
    return (T) Enum.Parse(typeof (T), enumString);
}

Usage:

Color colorEnum = "Red".ToEnum<Color>();

OU

string color = "Red";
var colorEnum = color.ToEnum<Color>();
Abdul Munim
la source
7
Pour traiter les entrées utilisateur, c'est probablement une bonne idée d'appeler la surcharge d'Enum.Parse qui vous permet de spécifier que la comparaison ne respecte PAS la casse (c'est-à-dire qu'un utilisateur tapant "rouge" (en minuscules) planterait le code ci-dessus sans ce changement .)
BrainSlugs83
9
Pratique, mais la question porte spécifiquement sur les pouces.
BJury
2
cela fonctionne également si la chaîne est un entier, par exemple "2"
TruthOf42
2
Cela lèvera une exception si enumString est null (a eu un problème similaire hier). Envisagez d'utiliser TryParse au lieu de Parse. TryParse vérifiera également si T est un type Enum
Justin
Ce type de méthode d'extension System.Stringsemble être une pollution d'espace de noms
Mr Anderson
160

Je pense que pour obtenir une réponse complète, les gens doivent savoir comment les énumérations fonctionnent en interne dans .NET.

Comment ça marche

Une énumération dans .NET est une structure qui mappe un ensemble de valeurs (champs) à un type de base (la valeur par défaut est int). Cependant, vous pouvez réellement choisir le type intégral auquel votre enum mappe:

public enum Foo : short

Dans ce cas, l'énumération est mappée à la short type de données, ce qui signifie qu'elle sera stockée en mémoire sous la forme d'un court métrage et se comportera comme un court métrage lorsque vous la transtyperez et l'utiliserez.

Si vous le regardez d'un point de vue IL, une énumération (normale, int) ressemble à ceci:

.class public auto ansi serializable sealed BarFlag extends System.Enum
{
    .custom instance void System.FlagsAttribute::.ctor()
    .custom instance void ComVisibleAttribute::.ctor(bool) = { bool(true) }

    .field public static literal valuetype BarFlag AllFlags = int32(0x3fff)
    .field public static literal valuetype BarFlag Foo1 = int32(1)
    .field public static literal valuetype BarFlag Foo2 = int32(0x2000)

    // and so on for all flags or enum values

    .field public specialname rtspecialname int32 value__
}

Ce qui devrait attirer votre attention ici, c'est que le value__est stocké séparément des valeurs d'énumération. Dans le cas de l'énumération Fooci-dessus, le type de value__est int16. Cela signifie essentiellement que vous pouvez stocker tout ce que vous voulez dans une énumération, tant que les types correspondent .

À ce stade, je voudrais souligner qu'il System.Enums'agit d'un type de valeur, ce qui signifie essentiellement qu'il BarFlagprendra 4 octets en mémoire et Fooen prendra 2 - par exemple, la taille du type sous-jacent (c'est en fait plus compliqué que cela, mais Hey...).

La réponse

Donc, si vous avez un entier que vous souhaitez mapper à une énumération, le runtime n'a qu'à faire 2 choses: copier les 4 octets et lui donner un autre nom (le nom de l'énumération). La copie est implicite car les données sont stockées en tant que type de valeur - cela signifie essentiellement que si vous utilisez du code non managé, vous pouvez simplement échanger des énumérations et des entiers sans copier les données.

Pour le rendre sûr, je pense que c'est une meilleure pratique de savoir que les types sous-jacents sont les mêmes ou implicitement convertibles et de s'assurer que les valeurs d'énumération existent (elles ne sont pas vérifiées par défaut!).

Pour voir comment cela fonctionne, essayez le code suivant:

public enum MyEnum : int
{
    Foo = 1,
    Bar = 2,
    Mek = 5
}

static void Main(string[] args)
{
    var e1 = (MyEnum)5;
    var e2 = (MyEnum)6;

    Console.WriteLine("{0} {1}", e1, e2);
    Console.ReadLine();
}

Notez que le casting e2fonctionne également! Du point de vue du compilateur ci-dessus, cela a du sens: le value__champ est simplement rempli de 5 ou 6 et lors des Console.WriteLineappels ToString(), le nom de e1est résolu tandis que le nom dee2 ne l'est pas.

Si ce n'est pas ce que vous vouliez, utilisez Enum.IsDefined(typeof(MyEnum), 6)pour vérifier si la valeur que vous convertissez correspond à une énumération définie.

Notez également que je suis explicite sur le type sous-jacent de l'énumération, même si le compilateur vérifie réellement cela. Je fais cela pour m'assurer de ne pas rencontrer de surprises sur la route. Pour voir ces surprises en action, vous pouvez utiliser le code suivant (en fait, j'ai vu cela se produire souvent dans le code de la base de données):

public enum MyEnum : short
{
    Mek = 5
}

static void Main(string[] args)
{
    var e1 = (MyEnum)32769; // will not compile, out of bounds for a short

    object o = 5;
    var e2 = (MyEnum)o;     // will throw at runtime, because o is of type int

    Console.WriteLine("{0} {1}", e1, e2);
    Console.ReadLine();
}
atlaste
la source
7
Je me rends compte que c'est un ancien poste, mais comment gagnez-vous ce niveau de connaissance en c #? Est-ce à partir de la lecture de la spécification C #?
Rolan
20
@Rolan Je souhaite parfois que plus de gens le demandent. :-) Pour être honnête, je ne sais pas vraiment; J'essaie de comprendre comment les choses fonctionnent et d'obtenir des informations partout où je peux les obtenir. J'ai lu la norme C #, mais je décompile aussi régulièrement du code avec Reflector (je regarde même beaucoup le code assembleur x86) et je fais des tonnes de petites expériences. De plus, la connaissance d'autres langues est utile dans ce cas; Je fais du CS depuis environ 30 ans maintenant, et à un moment donné certaines choses deviennent «logiques» - f.ex. une énumération doit être de type intégral, car sinon l'interopérabilité se brisera (ou vos performances diminueront).
atlaste
9
Je crois que la clé pour faire du génie logiciel correctement est de savoir comment les choses fonctionnent. Pour moi, cela signifie que si vous écrivez un morceau de code, vous savez comment il se traduit grossièrement en f.ex. les opérations du processeur et la mémoire récupère / écrit. Si vous demandez comment atteindre ce niveau, je vous suggère de construire une tonne de petits cas de test, de les rendre plus difficiles au fur et à mesure, d'essayer de prédire le résultat à chaque fois et de les tester ensuite (y compris la décompilation, etc.). Après avoir compris tous les détails et toutes les caractéristiques, vous pouvez vérifier si vous avez bien compris la norme (terne). Ce serait du moins mon approche.
atlaste
1
Réponse fantastique, merci! Dans votre dernier exemple de code, il lève une exception à l'exécution car o est un objet. Vous pouvez convertir une variable int en short tant qu'elle se situe dans la plage courte.
gravidThoughts
@gravidThoughts Merci. En fait, c'est une opération de déballage, donc il ne fera aucune conversion implicite comme celles que vous décrivez. Le casting est parfois déroutant en C # si vous ne connaissez pas les détails ... Quoi qu'il en soit, car int! = short, Il lancera (le déballage échoue). Si vous le faites object o = (short)5;, cela fonctionnera, car alors les types correspondront. Ce n'est pas une question de gamme, c'est vraiment une question de type.
atlaste
121

Prenons l'exemple suivant:

int one = 1;
MyEnum e = (MyEnum)one;
abigblackman
la source
64

J'utilise ce morceau de code pour convertir l'intégralité de mon enum:

if (typeof(YourEnum).IsEnumDefined(valueToCast)) return (YourEnum)valueToCast;
else { //handle it here, if its not defined }

Je trouve que c'est la meilleure solution.

MSkuta
la source
1
c'est bon. j'ai été surpris qu'il n'y ait pas d'exception lors de la conversion d'une valeur non valide en une énumération int-soutenue.
orion elenzil
Ce n'est pas vraiment différent de la réponse la mieux notée. Cette réponse traite également de l'utilisation d'Enum.IsDefined après avoir converti la chaîne en type Enum. Donc, même si la chaîne a été castée sans erreur, Enum.IsDefined l'attrapera toujours
Don Cheadle
53

Vous trouverez ci-dessous une belle classe utilitaire pour Enums

public static class EnumHelper
{
    public static int[] ToIntArray<T>(T[] value)
    {
        int[] result = new int[value.Length];
        for (int i = 0; i < value.Length; i++)
            result[i] = Convert.ToInt32(value[i]);
        return result;
    }

    public static T[] FromIntArray<T>(int[] value) 
    {
        T[] result = new T[value.Length];
        for (int i = 0; i < value.Length; i++)
            result[i] = (T)Enum.ToObject(typeof(T),value[i]);
        return result;
    }


    internal static T Parse<T>(string value, T defaultValue)
    {
        if (Enum.IsDefined(typeof(T), value))
            return (T) Enum.Parse(typeof (T), value);

        int num;
        if(int.TryParse(value,out num))
        {
            if (Enum.IsDefined(typeof(T), num))
                return (T)Enum.ToObject(typeof(T), num);
        }

        return defaultValue;
    }
}
Tawani
la source
47

Pour les valeurs numériques, cela est plus sûr car il retournera un objet quoi qu'il arrive:

public static class EnumEx
{
    static public bool TryConvert<T>(int value, out T result)
    {
        result = default(T);
        bool success = Enum.IsDefined(typeof(T), value);
        if (success)
        {
            result = (T)Enum.ToObject(typeof(T), value);
        }
        return success;
    }
}
Sébastien Duval
la source
Ne fonctionne pas pour les énumérations de drapeaux
Seyed Morteza Mousavi
44

Si vous êtes prêt pour le 4.0 .NET Framework, il y a une nouvelle fonction Enum.TryParse () qui est très utile et joue bien avec l'attribut [Flags]. Voir Enum.TryParse, méthode (String, TEnum%)

Ryan Russon
la source
21
C'est utile lors de la conversion à partir d'une chaîne. Mais pas lors de la conversion d'un int.
CodesInChaos
35

Si vous avez un entier qui agit comme un masque de bits et pourrait représenter une ou plusieurs valeurs dans une énumération [Indicateurs], vous pouvez utiliser ce code pour analyser les valeurs d'indicateur individuelles dans une liste:

for (var flagIterator = 0; flagIterator < 32; flagIterator++)
{
    // Determine the bit value (1,2,4,...,Int32.MinValue)
    int bitValue = 1 << flagIterator;

    // Check to see if the current flag exists in the bit mask
    if ((intValue & bitValue) != 0)
    {
        // If the current flag exists in the enumeration, then we can add that value to the list
        // if the enumeration has that flag defined
        if (Enum.IsDefined(typeof(MyEnum), bitValue))
            Console.WriteLine((MyEnum)bitValue);
    }
}

Notez que cela suppose que le type sous-jacent de enumest un entier signé 32 bits. S'il s'agissait d'un type numérique différent, vous devriez changer le 32 codé en dur pour refléter les bits de ce type (ou le dériver par programmation en utilisant Enum.GetUnderlyingType())

Evan M
la source
1
Cette boucle n'est-elle jamais terminée? flagIterator = 0x00000001, flagIterator = 0x00000002, flagIterator = 0x00000004, ..., flagIterator = 0x40000000, flagIterator = 0x80000000, flagIterator = 0x00000000. En d'autres termes, la valeur sera toujours inférieure à 0x80000000 car elle débordera à zéro après le cas où le bit D31 = 1. Ensuite, elle restera à jamais car le décalage à gauche de la valeur 0 donne 0
Christian Gingras
Grande prise @christiangingras, merci! J'ai modifié la réponse pour tenir compte de cela, et elle devrait prendre en compte lorsque le bit le plus élevé est défini (c'est-à-dire 0x80000000 / Int32.MinValue)
Evan M
27

Parfois, vous avez un objet du MyEnumtype. Comme

var MyEnumType = typeof(MyEnumType);

Alors:

Enum.ToObject(typeof(MyEnum), 3)
LD
la source
26

Il s'agit d'une méthode de conversion sûre compatible avec l'énumération des drapeaux:

public static bool TryConvertToEnum<T>(this int instance, out T result)
  where T: Enum
{
  var enumType = typeof (T);
  var success = Enum.IsDefined(enumType, instance);
  if (success)
  {
    result = (T)Enum.ToObject(enumType, instance);
  }
  else
  {
    result = default(T);
  }
  return success;
}
Daniel Fisher lennybacon
la source
3
Cela peut maintenant être amélioré avec C # 7.3 en contraignant à la Enumplace de struct, ce qui signifie que nous n'avons pas à nous fier à la vérification de l'exécution!
Scott
20

entrez la description de l'image ici

Pour convertir une chaîne en ENUM ou int en constante ENUM, nous devons utiliser la fonction Enum.Parse. Voici une vidéo youtube https://www.youtube.com/watch?v=4nhx4VwdRDk qui démontre réellement la chaîne avec la même chose pour int.

Le code va comme indiqué ci-dessous où "rouge" est la chaîne et "MyColors" est la couleur ENUM qui a les constantes de couleur.

MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");
Shivprasad Koirala
la source
20

S'éloignant légèrement de la question d'origine, mais j'ai trouvé une réponse à la question Stack Overflow Obtenir la valeur int de enum utile. Créez une classe statique avec des public const intpropriétés, ce qui vous permet de rassembler facilement un tas de intconstantes connexes , sans avoir à les convertir intlors de leur utilisation.

public static class Question
{
    public static readonly int Role = 2;
    public static readonly int ProjectFunding = 3;
    public static readonly int TotalEmployee = 4;
    public static readonly int NumberOfServers = 5;
    public static readonly int TopBusinessConcern = 6;
}

Évidemment, certaines des fonctionnalités de type enum seront perdues, mais pour stocker un tas de constantes d'ID de base de données, cela semble être une solution assez ordonnée.

Ted
la source
5
les énumérations ont remplacé l'utilisation de constantes entières comme celle-ci car elles offrent plus de sécurité de type
Paul Richards
1
Paul, il s'agit d'une méthode de collecte des constantes int liées (par exemple, les constantes id de la base de données) afin qu'elles puissent être utilisées directement sans avoir à les convertir en int à chaque fois qu'elles sont utilisées. Leur type est un entier, pas par exemple, DatabaseIdsEnum.
Ted
1
Il y a au moins une situation que j'ai trouvée dans laquelle la sécurité de type enum peut être involontairement contournée.
Thierry
Mais les énumérations garantissent également que les valeurs sont toutes uniques, ce qui manque également à cette approche
derHugo
15

Cela analyse les entiers ou les chaînes en une énumération cible avec une correspondance partielle dans dot.NET 4.0 en utilisant des génériques comme dans la classe d'utilité de Tawani ci-dessus. Je l'utilise pour convertir des variables de commutateur de ligne de commande qui peuvent être incomplètes. Puisqu'une énumération ne peut pas être nulle, vous devez logiquement fournir une valeur par défaut. Il peut être appelé comme ceci:

var result = EnumParser<MyEnum>.Parse(valueToParse, MyEnum.FirstValue);

Voici le code:

using System;

public class EnumParser<T> where T : struct
{
    public static T Parse(int toParse, T defaultVal)
    {
        return Parse(toParse + "", defaultVal);
    }
    public static T Parse(string toParse, T defaultVal) 
    {
        T enumVal = defaultVal;
        if (defaultVal is Enum && !String.IsNullOrEmpty(toParse))
        {
            int index;
            if (int.TryParse(toParse, out index))
            {
                Enum.TryParse(index + "", out enumVal);
            }
            else
            {
                if (!Enum.TryParse<T>(toParse + "", true, out enumVal))
                {
                    MatchPartialName(toParse, ref enumVal);
                }
            }
        }
        return enumVal;
    }

    public static void MatchPartialName(string toParse, ref T enumVal)
    {
        foreach (string member in enumVal.GetType().GetEnumNames())
        {
            if (member.ToLower().Contains(toParse.ToLower()))
            {
                if (Enum.TryParse<T>(member + "", out enumVal))
                {
                    break;
                }
            }
        }
    }
}

FYI: La question portait sur les entiers, que personne n'a mentionné convertira également explicitement dans Enum.TryParse ()

CZahrobsky
la source
13

À partir d'une chaîne: (Enum.Parse est obsolète, utilisez Enum.TryParse)

enum Importance
{}

Importance importance;

if (Enum.TryParse(value, out importance))
{
}
Will Yu
la source
4
La question porte spécifiquement sur les nombres entiers.
BJury
4
Yu pourra-t-il modifier votre réponse pour que tout le monde sache que Enum.TryParse travaillera sur une chaîne de la valeur ou du nom de l'énumération (je n'ai pas pu résister)
JeremyWeir
1
Jeremy, Weir y travaille (n'a pas pu résister non plus).
huysentruitw
11

Voici une méthode d'extension légèrement meilleure

public static string ToEnumString<TEnum>(this int enumValue)
        {
            var enumString = enumValue.ToString();
            if (Enum.IsDefined(typeof(TEnum), enumValue))
            {
                enumString = ((TEnum) Enum.ToObject(typeof (TEnum), enumValue)).ToString();
            }
            return enumString;
        }
Kamran Shahid
la source
10

Dans mon cas, je devais retourner l'énumération d'un service WCF. J'avais également besoin d'un nom convivial, pas seulement de l'énum.ToString ().

Voici ma classe WCF.

[DataContract]
public class EnumMember
{
    [DataMember]
    public string Description { get; set; }

    [DataMember]
    public int Value { get; set; }

    public static List<EnumMember> ConvertToList<T>()
    {
        Type type = typeof(T);

        if (!type.IsEnum)
        {
            throw new ArgumentException("T must be of type enumeration.");
        }

        var members = new List<EnumMember>();

        foreach (string item in System.Enum.GetNames(type))
        {
            var enumType = System.Enum.Parse(type, item);

            members.Add(
                new EnumMember() { Description = enumType.GetDescriptionValue(), Value = ((IConvertible)enumType).ToInt32(null) });
        }

        return members;
    }
}

Voici la méthode d'extension qui obtient la description de l'énumération.

    public static string GetDescriptionValue<T>(this T source)
    {
        FieldInfo fileInfo = source.GetType().GetField(source.ToString());
        DescriptionAttribute[] attributes = (DescriptionAttribute[])fileInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);            

        if (attributes != null && attributes.Length > 0)
        {
            return attributes[0].Description;
        }
        else
        {
            return source.ToString();
        }
    }

La mise en oeuvre:

return EnumMember.ConvertToList<YourType>();
LawMan
la source
9

Je ne sais plus où obtenir la partie de cette extension enum, mais elle provient de stackoverflow. Je suis désolé pour cela! Mais j'ai pris celui-ci et l'ai modifié pour des énumérations avec des drapeaux. Pour les énumérations avec des drapeaux, j'ai fait ceci:

  public static class Enum<T> where T : struct
  {
     private static readonly IEnumerable<T> All = Enum.GetValues(typeof (T)).Cast<T>();
     private static readonly Dictionary<int, T> Values = All.ToDictionary(k => Convert.ToInt32(k));

     public static T? CastOrNull(int value)
     {
        T foundValue;
        if (Values.TryGetValue(value, out foundValue))
        {
           return foundValue;
        }

        // For enums with Flags-Attribut.
        try
        {
           bool isFlag = typeof(T).GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0;
           if (isFlag)
           {
              int existingIntValue = 0;

              foreach (T t in Enum.GetValues(typeof(T)))
              {
                 if ((value & Convert.ToInt32(t)) > 0)
                 {
                    existingIntValue |= Convert.ToInt32(t);
                 }
              }
              if (existingIntValue == 0)
              {
                 return null;
              }

              return (T)(Enum.Parse(typeof(T), existingIntValue.ToString(), true));
           }
        }
        catch (Exception)
        {
           return null;
        }
        return null;
     }
  }

Exemple:

[Flags]
public enum PetType
{
  None = 0, Dog = 1, Cat = 2, Fish = 4, Bird = 8, Reptile = 16, Other = 32
};

integer values 
1=Dog;
13= Dog | Fish | Bird;
96= Other;
128= Null;
Franki1986
la source
9

Vous devez intégrer une relaxation de correspondance de type pour être plus robuste.

public static T ToEnum<T>(dynamic value)
{
    if (value == null)
    {
        // default value of an enum is the object that corresponds to
        // the default value of its underlying type
        // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/default-values-table
        value = Activator.CreateInstance(Enum.GetUnderlyingType(typeof(T)));
    }
    else if (value is string name)
    {
        return (T)Enum.Parse(typeof(T), name);
    }

    return (T)Enum.ToObject(typeof(T),
             Convert.ChangeType(value, Enum.GetUnderlyingType(typeof(T))));
}

Cas de test

[Flags]
public enum A : uint
{
    None  = 0, 
    X     = 1 < 0,
    Y     = 1 < 1
}

static void Main(string[] args)
{
    var value = EnumHelper.ToEnum<A>(7m);
    var x = value.HasFlag(A.X); // true
    var y = value.HasFlag(A.Y); // true

    var value2 = EnumHelper.ToEnum<A>("X");

    var value3 = EnumHelper.ToEnum<A>(null);

    Console.ReadKey();
}

la source
Ceci est une bonne réponse. C'est dommage que ce soit si loin en bas de la page en ce moment!
MikeBeaton
8

Différentes façons de diffuser vers et depuis Enum

enum orientation : byte
{
 north = 1,
 south = 2,
 east = 3,
 west = 4
}

class Program
{
  static void Main(string[] args)
  {
    orientation myDirection = orientation.north;
    Console.WriteLine(“myDirection = {0}”, myDirection); //output myDirection =north
    Console.WriteLine((byte)myDirection); //output 1

    string strDir = Convert.ToString(myDirection);
        Console.WriteLine(strDir); //output north

    string myString = north”; //to convert string to Enum
    myDirection = (orientation)Enum.Parse(typeof(orientation),myString);


 }
}
utilisateur gmail
la source
8

Il peut vous aider à convertir toutes les données d'entrée en énumération souhaitée par l'utilisateur . Supposons que vous ayez une énumération comme ci-dessous qui par défaut int . Veuillez ajouter une valeur par défaut au premier de votre énumération. Qui est utilisé chez helpers medthod lorsqu'aucune correspondance n'est trouvée avec la valeur d'entrée.

public enum FriendType  
{
    Default,
    Audio,
    Video,
    Image
}

public static class EnumHelper<T>
{
    public static T ConvertToEnum(dynamic value)
    {
        var result = default(T);
        var tempType = 0;

        //see Note below
        if (value != null &&
            int.TryParse(value.ToString(), out  tempType) && 
            Enum.IsDefined(typeof(T), tempType))
        {
            result = (T)Enum.ToObject(typeof(T), tempType); 
        }
        return result;
    }
}

NB: Ici, j'essaie d'analyser la valeur en int, car enum est par défaut int Si vous définissez enum comme celui-ci qui est de type octet .

public enum MediaType : byte
{
    Default,
    Audio,
    Video,
    Image
} 

Vous devez modifier l'analyse syntaxique à la méthode d'assistance de

int.TryParse(value.ToString(), out  tempType)

à

byte.TryParse(value.ToString(), out tempType)

Je vérifie ma méthode pour les entrées suivantes

EnumHelper<FriendType>.ConvertToEnum(null);
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("-1");
EnumHelper<FriendType>.ConvertToEnum("6");
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("2");
EnumHelper<FriendType>.ConvertToEnum(-1);
EnumHelper<FriendType>.ConvertToEnum(0);
EnumHelper<FriendType>.ConvertToEnum(1);
EnumHelper<FriendType>.ConvertToEnum(9);

Désolé pour mon anglais

reza.cse08
la source
8

Voici une méthode d'extension qui se transforme Int32enEnum .

Il honore les drapeaux au niveau du bit même lorsque la valeur est supérieure au maximum possible. Par exemple, si vous avez une énumération avec les possibilités 1 , 2 et 4 , mais que l'int est 9 , il comprend cela comme 1 en l'absence de 8 . Cela vous permet d'effectuer des mises à jour des données avant les mises à jour du code.

   public static TEnum ToEnum<TEnum>(this int val) where TEnum : struct, IComparable, IFormattable, IConvertible
    {
        if (!typeof(TEnum).IsEnum)
        {
            return default(TEnum);
        }

        if (Enum.IsDefined(typeof(TEnum), val))
        {//if a straightforward single value, return that
            return (TEnum)Enum.ToObject(typeof(TEnum), val);
        }

        var candidates = Enum
            .GetValues(typeof(TEnum))
            .Cast<int>()
            .ToList();

        var isBitwise = candidates
            .Select((n, i) => {
                if (i < 2) return n == 0 || n == 1;
                return n / 2 == candidates[i - 1];
            })
            .All(y => y);

        var maxPossible = candidates.Sum();

        if (
            Enum.TryParse(val.ToString(), out TEnum asEnum)
            && (val <= maxPossible || !isBitwise)
        ){//if it can be parsed as a bitwise enum with multiple flags,
          //or is not bitwise, return the result of TryParse
            return asEnum;
        }

        //If the value is higher than all possible combinations,
        //remove the high imaginary values not accounted for in the enum
        var excess = Enumerable
            .Range(0, 32)
            .Select(n => (int)Math.Pow(2, n))
            .Where(n => n <= val && n > 0 && !candidates.Contains(n))
            .Sum();

        return Enum.TryParse((val - excess).ToString(), out asEnum) ? asEnum : default(TEnum);
    }
Chad Hedgcock
la source
6

la manière simple et claire de convertir un int enum en c #:

 public class Program
    {
        public enum Color : int
        {
            Blue = 0,
            Black = 1,
            Green = 2,
            Gray = 3,
            Yellow =4
        }

        public static void Main(string[] args)
        {
            //from string
            Console.WriteLine((Color) Enum.Parse(typeof(Color), "Green"));

            //from int
            Console.WriteLine((Color)2);

            //From number you can also
            Console.WriteLine((Color)Enum.ToObject(typeof(Color) ,2));
        }
    }
Mohammad Aziz Nabizada
la source
6

Vous utilisez simplement la conversion explicite Cast int en enum ou enum to int

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine((int)Number.three); //Output=3

        Console.WriteLine((Number)3);// Outout three
        Console.Read();
    }

    public enum Number
    {
        Zero = 0,
        One = 1,
        Two = 2,
        three = 3
    }
}
Shivam Mishra
la source
4
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace SamplePrograme
{
    public class Program
    {
        public enum Suit : int
        {
            Spades = 0,
            Hearts = 1,
            Clubs = 2,
            Diamonds = 3
        }

        public static void Main(string[] args)
        {
            //from string
            Console.WriteLine((Suit) Enum.Parse(typeof(Suit), "Clubs"));

            //from int
            Console.WriteLine((Suit)1);

            //From number you can also
            Console.WriteLine((Suit)Enum.ToObject(typeof(Suit) ,1));
        }
    }
}
Aswal
la source
3

Vous faites juste comme ci-dessous:

int intToCast = 1;
TargetEnum f = (TargetEnum) intToCast ;

Pour vous assurer que vous convertissez uniquement les bonnes valeurs et que vous pouvez lever une exception dans le cas contraire:

int intToCast = 1;
if (Enum.IsDefined(typeof(TargetEnum), intToCast ))
{
    TargetEnum target = (TargetEnum)intToCast ;
}
else
{
   // Throw your exception.
}

Notez que l'utilisation d'IsDefined est coûteuse et même plus que le simple casting, donc cela dépend de votre implémentation pour décider de l'utiliser ou non.

Mselmi Ali
la source
3

Vous pouvez utiliser la méthode d'extension.

public static class Extensions
{

    public static T ToEnum<T>(this string data) where T : struct
    {
        if (!Enum.TryParse(data, true, out T enumVariable))
        {
            if (Enum.IsDefined(typeof(T), enumVariable))
            {
                return enumVariable;
            }
        }

        return default;
    }

    public static T ToEnum<T>(this int data) where T : struct
    {
        return (T)Enum.ToObject(typeof(T), data);
    }
}

utiliser comme code ci-dessous

énumération:

public enum DaysOfWeeks
{
    Monday = 1,
    Tuesday = 2,
    Wednesday = 3,
    Thursday = 4,
    Friday = 5,
    Saturday = 6,
    Sunday = 7,
}

Utilisation:

 string Monday = "Mon";
 int Wednesday = 3;
 var Mon = Monday.ToEnum<DaysOfWeeks>();
 var Wed = Wednesday.ToEnum<DaysOfWeeks>();
Reza Jenabi
la source