[C#] Cast int pour enum en C #


Answers

Juste le jeter:

MyEnum e = (MyEnum)3;

Vous pouvez vérifier s'il est dans la plage en utilisant Enum.IsDefined :

if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }
Question

Comment un int peut-il être converti en une enum en C #?







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 analyser les valeurs d'indicateur individuelles 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);
    }
}



Pour convertir une chaîne ENUM ou int en constante ENUM, nous devons utiliser la fonction Enum.Parse. Voici une vidéo sur youtube https://www.youtube.com/watch?v=4nhx4VwdRDk qui montre réellement avec une 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 la couleur ENUM qui a les constantes de couleur.

MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");



J'utilise ce morceau de code pour lancer int à mon énumération:

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

Je trouve que c'est la meilleure solution.




Ceci est une méthode de conversion sécurisée par énumération de 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;
}



Je ne sais plus où je reçois la partie de cette extension enum, mais elle vient de . Je suis désolé pour cela! Mais j'ai pris celui-ci et l'ai modifié pour enums avec Flags. Pour enums 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;



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



À partir d'une chaîne: (Enum.Parse est en dehors de Date, utilisez Enum.TryParse)

enum Importance
{}

Importance importance;

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



Je pense que pour avoir une réponse complète, les gens doivent savoir comment fonctionnent les enums en interne .NET.

Comment ça fonctionne

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 énumération correspond:

public enum Foo : short

Dans ce cas, l'énumération est mappée au type de données short , ce qui signifie qu'il sera stocké en mémoire en tant que court-circuit et se comportera comme un court-circuit lorsque vous le lancerez et l'utiliserez.

Si vous le regardez d'un point de vue IL, une enum (normal, 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 la value__ est stockée séparément des valeurs enum. Dans le cas de l'enum Foo ci-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 tiens à souligner que System.Enum est un type de valeur, ce qui signifie essentiellement que BarFlag prendra 4 octets en mémoire et Foo prendra 2 - par exemple la taille du type sous-jacent (il est en fait plus compliqué que ça, mais bon ...).

La réponse

Donc, si vous avez un nombre entier que vous voulez mapper à une énumération, le moteur d'exécution doit seulement faire 2 choses: copier les 4 octets et le nommer quelque chose d'autre (le nom de l'énumération). La copie est implicite parce que les données sont stockées en tant que type de valeur - cela signifie essentiellement que si vous utilisez du code non géré, vous pouvez simplement échanger des énumérations et des entiers sans copier de données.

Pour être sûr, je pense que c'est une bonne pratique de savoir que les types sous-jacents sont identiques ou implicitement convertibles et de s'assurer que les valeurs enum existent (elles ne sont pas coché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 lancer sur e2 fonctionne également! De la perspective 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 alors 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 lancez 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 avoir 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 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();
}





Links