Cast int enum en C#

comment un int peut-il être moulé à un enum en C#?

2625
demandé sur alexy13 2008-08-27 07:58:21

21 réponses

D'une chaîne de caractères:

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:

du numéro vous pouvez aussi

YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);
3174
répondu FlySwat 2017-01-05 08:56:25

Juste de voter pour elle:

MyEnum e = (MyEnum)3;

vous pouvez vérifier si elle est dans la gamme en utilisant Enum.IsDefined :

if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }
736
répondu Matt Hamilton 2008-08-27 04:01:14

alternativement, utiliser une méthode d'extension au lieu d'une doublure unique:

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

Utilisation:

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

ou

string color = "Red";
var colorEnum = color.ToEnum<Color>();
203
répondu Abdul Munim 2016-01-07 20:07:50

je pense que pour obtenir une réponse complète, les gens doivent savoir comment les enums travaillent en interne .NET.

Comment ça marche

un enum dans .NET est une structure qui établit une correspondance entre un ensemble de valeurs (champs) et un type de base (la valeur par défaut est int ). Cependant, vous pouvez réellement choisir le type intégral que votre enum correspond à:

public enum Foo : short

dans ce cas, l'enum est mappé sur les données short type, ce qui signifie qu'il sera stockée dans la mémoire à court et se comporte comme un court lorsque vous lancez et l'utiliser.

si vous le regardez d'un point de vue IL, un (normal, int) enum 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 est que le value__ est stocké séparément des valeurs enum. Dans le cas de l'enum Foo ci-dessus, le type de value__ est int16. Cela signifie que vous pouvez stocker tout ce que vous voulez dans un enum, aussi longtemps que les types correspondent .

à ce point je voudrais souligner que System.Enum est un type de valeur, qui signifie essentiellement que BarFlag prendra 4 octets en mémoire et Foo prendra 2 -- par exemple la taille du type sous-jacent (c'est en fait plus compliqué que cela, mais bon...).

la réponse

donc, si vous avoir un entier que vous voulez mapper à un enum, l'exécution ne doit faire que 2 choses: copier les 4 octets et lui donner un autre nom (le nom de l'enum). Copier est implicite parce que les données sont stockées comme type de valeur - cela signifie fondamentalement que si vous utilisez du code non géré, vous pouvez simplement échanger des énums et des entiers sans copier des données.

pour être sûr, je pense que c'est une bonne pratique de savoir que les types sous-jacents sont les mêmes ou implicitement convertible et pour s'assurer que les valeurs enum 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 de e2 fonctionne aussi! Du point de vue du compilateur ci-dessus, cela a du sens: le champ value__ est simplement rempli avec 5 ou 6 et lorsque Console.WriteLine appelle ToString() , le nom de e1 est résolu tandis que le nom de e2 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 utilisez correspond à un enum défini.

notez aussi que je suis explicite sur le type sous-jacent de l'enum, même si le compilateur le vérifie. Je fais ça pour m'assurer de ne pas tomber dans des surprises. Pour voir ces surprises en action, vous pouvez utiliser le code suivant (en fait, j'ai vu ce qui se passe beaucoup 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();
}
121
répondu atlaste 2014-04-03 07:39:44

prendre l'exemple suivant:

int one = 1;
MyEnum e = (MyEnum)one;
92
répondu abigblackman 2016-12-25 09:39:23

j'utilise ce morceau de code pour lancer int à 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.

56
répondu MSkuta 2011-10-21 10:05:43

ci-dessous est une classe d'utilité nice 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;
    }
}
45
répondu Tawani 2010-09-07 04:42:51

si vous êtes prêt pour le 4.0 .NET Framework, Il ya un nouveau Enum.TryParse () fonction qui est très utile et qui joue bien avec l'attribut [Flags]. Voir Enum.Méthode TryParse (String, TEnum)%)

37
répondu Ryan Russon 2012-08-31 20:33:02

pour les valeurs numériques, c'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;
    }
}
37
répondu Sébastien Duval 2016-01-07 20:09:01

si vous avez un entier qui agit comme un masque de bits et pourrait représenter une ou plusieurs valeurs dans une énumération [Flags], vous pouvez utiliser ce code pour séparer les valeurs de chaque drapeau dans une liste:

for (var flagIterator = 0x1; flagIterator <= 0x80000000; flagIterator <<= 1)
{
    // Check to see if the current flag exists in the bit mask
    if ((intValue & flagIterator) != 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), flagIterator))
            ListOfEnumValues.Add((MyEnum)flagIterator);
    }
}
25
répondu Evan M 2011-04-13 20:13:13

parfois, vous avez un objet du type MyEnum . Comme

var MyEnumType = typeof(MyEnumType);

puis:

Enum.ToObject(typeof(MyEnum), 3)
22
répondu L. D. 2012-08-31 20:30:55

il s'agit d'une méthode de conversion sûre tenant compte de l'énumération des drapeaux:

public static bool TryConvertToEnum<T>(this int instance, out T result)
  where T: struct
{
  var enumType = typeof (T);
  if (!enumType.IsEnum)
  {
    throw new ArgumentException("The generic type must be an enum.");
  }
  var success = Enum.IsDefined(enumType, instance);
  if (success)
  {
    result = (T)Enum.ToObject(enumType, instance);
  }
  else
  {
    result = default(T);
  }
  return success;
}
18
répondu Daniel Fisher lennybacon 2017-09-20 13:16:55

enter image description here

pour convertir une chaîne en enum ou int en constante ENUM, nous devons utiliser Enum.Fonction d'analyse. Voici une vidéo youtube https://www.youtube.com/watch?v=4nhx4VwdRDk qui montrent réellement avec la chaîne et la même chose s'applique pour int.

le code va comme montré ci-dessous où" rouge "est la chaîne et" MyColors " est l'ÉNUM de couleur qui a les constantes de couleur.

MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");
17
répondu Shivprasad Koirala 2014-02-05 12:15:25

s'éloignant légèrement de la question originale, mais j'ai trouvé une réponse à la question de débordement de pile obtenir la valeur int de enum utile. Créez une classe statique avec les propriétés public const int , vous permettant de rassembler facilement un tas de constantes int liées, et ensuite ne pas avoir à les mouler à int en les utilisant.

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 fonctionnalités du type enum seront perdu, mais pour stocker un tas de constantes d'id de base de données, il semble comme une solution assez ordonnée.

14
répondu Ted 2017-05-23 10:31:39

ce parses entiers ou Chaînes à un enum cible avec correspondance partielle dans dot.NET 4.0 utiliser des génériques comme dans la classe d'utilité de Tawani ci-dessus. Je l'utilise pour convertir les variables de commutateur de ligne de commande qui peuvent être incomplètes. Puisqu'un enum ne peut pas être null, vous devriez logiquement fournir une valeur par défaut. On peut l'appeler ainsi:

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

pour information: la question portait sur les entiers, que personne n'a mentionnés seront aussi explicitement convertis en Enum.TryParse ()

10
répondu CZahrobsky 2014-07-30 22:16:59

à Partir d'une chaîne: (Enum.L'analyse est périmée, utilisez Enum.TryParse)

enum Importance
{}

Importance importance;

if (Enum.TryParse(value, out importance))
{
}
10
répondu Will Yu 2014-11-21 00:32:24

ci-dessous est légèrement meilleure méthode d'extension

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;
        }
8
répondu Kamran Shahid 2018-09-06 10:22:38

dans mon cas, je devais rendre l'enum d'un service de la WCF. J'avais aussi besoin d'un nom Amical, pas seulement l'enum.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'Enum.

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

mise en Œuvre:

return EnumMember.ConvertToList<YourType>();
7
répondu LawMan 2014-07-02 14:58:49

Différentes manières de fonte et de 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);


 }
}
5
répondu gmail user 2014-01-08 15:18:34

Je ne sais plus où je trouve la partie de cette extension enum, mais elle vient de stackoverflow. Je suis désolé pour cette! Mais j'ai pris celui-ci et je l'ai modifié pour des énums avec des drapeaux. Pour les énums 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;
5
répondu Franki1986 2016-01-07 11:40:50

il peut vous aider à convertir n'importe quelles données d'entrée à l'utilisateur désiré enum . Supposons que vous ayez un enum comme ci-dessous qui par défaut int . Veuillez ajouter une valeur par défaut au début de votre enum. Qui est utilisé chez helpers medthod quand il n'y a pas de correspondance 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;
    }
}

N. B: ici, j'essaie de décomposer la valeur en int, car enum est par défaut int Si vous définissez enum comme ceci qui est byte type.

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

vous devez changer l'analyse à la méthode helper 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

5
répondu reza.cse08 2016-11-17 12:49:05