Comment lancer int pour énumérer?


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

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)) { ... }

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

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

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


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.


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

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

Ne fonctionne pas pour les énumérations de drapeaux
Seyed Morteza Mousavi


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())


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)

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

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

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.


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 ()


13

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

enum Importance
{}

Importance importance;

if (Enum.TryParse(value, out importance))
{
}

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

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

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;

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

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


 }
}

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


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

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

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

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

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.


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>();
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.