[C#] Cast int, um in C # aufzuzählen



Answers

Einfach umwandeln:

MyEnum e = (MyEnum)3;

Sie können mit Enum.IsDefined prüfen, ob es sich in Reichweite Enum.IsDefined :

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

Wie kann ein int zu einer enum in C # umgewandelt werden?







Dies ist eine Flags-Enumerations-sichere Konvertierungsmethode:

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



Aus einer Zeichenfolge: (Enum.Parse ist veraltet, verwenden Sie Enum.TryParse)

enum Importance
{}

Importance importance;

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



Folgendes ist eine etwas bessere Erweiterungsmethode

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



Um eine Zeichenkette in ENUM oder int in ENUM Konstante zu konvertieren, müssen wir die Funktion Enum.Parse verwenden. Hier ist ein Youtube-Video https://www.youtube.com/watch?v=4nhx4VwdRDk welches tatsächlich mit string demonstriert und das selbe gilt für int.

Der Code sieht wie folgt aus: "Rot" ist die Zeichenkette und "MyColors" ist die Farbe ENUM mit den Farbkonstanten.

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



Ich denke, um eine vollständige Antwort zu bekommen, müssen die Leute wissen, wie Enums intern in .NET arbeiten.

Wie Dinge funktionieren

Eine Enumeration in .NET ist eine Struktur, die eine Gruppe von Werten (Feldern) einem Basistyp zuordnet (der Standardwert ist int ). Sie können jedoch auch den ganzzahligen Typ auswählen, dem Ihre enum zugeordnet ist:

public enum Foo : short

In diesem Fall wird die Enumeration dem short Datentyp zugeordnet, was bedeutet, dass sie im Speicher als Short gespeichert wird und sich beim Cast und der Verwendung als Short verhält.

Wenn Sie es aus der Sicht von IL betrachten, sieht eine (normale, int) Enumeration wie folgt aus:

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

Was Sie hier beachten sollten, ist, dass der value__ getrennt von den Enum-Werten gespeichert wird. Im Fall der obigen Aufzählung Foo ist der Typ von value__ . Dies bedeutet, dass Sie alles, was Sie wollen, in einer Enum speichern können, solange die Typen übereinstimmen .

An dieser Stelle möchte ich darauf hinweisen, dass System.Enum ein System.Enum ist, was im Grunde bedeutet, dass BarFlag 4 Bytes im Speicher belegt und Foo 2 - zB die Größe des zugrunde liegenden Typs (es ist eigentlich mehr) belegt Komplizierter als das, aber hey ...).

Die Antwort

Wenn Sie also eine Ganzzahl haben, die Sie einer Enumeration zuordnen möchten, muss die Laufzeit nur zwei Dinge tun: Kopieren Sie die 4 Bytes und benennen Sie sie mit etwas anderem (dem Namen der Enumeration). Das Kopieren ist implizit, da die Daten als Werttyp gespeichert werden. Dies bedeutet, dass Sie, wenn Sie nicht verwalteten Code verwenden, einfach Enums und Ganzzahlen austauschen können, ohne Daten zu kopieren.

Um es sicher zu machen, ist es eine bewährte Methode zu wissen, dass die zugrunde liegenden Typen gleich oder implizit konvertierbar sind und dass die enum-Werte vorhanden sind (sie werden nicht standardmäßig überprüft!).

Versuchen Sie den folgenden Code, um zu sehen, wie das funktioniert:

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

Beachten Sie, dass das Umwandeln in e2 auch funktioniert! Aus der Perspektive des Compilers oben ist dies sinnvoll: value__ Feld value__ wird einfach mit 5 oder 6 gefüllt, und wenn Console.WriteLine ToString() , wird der Name von e1 aufgelöst, während der Name von e2 nicht aufgelöst wird.

Wenn das nicht beabsichtigt ist, verwenden Sie Enum.IsDefined(typeof(MyEnum), 6) , um zu überprüfen, ob der Wert, den Sie übergeben, einer definierten Enumeration zugeordnet ist.

Beachten Sie auch, dass ich explizit über den zugrunde liegenden Typ der Enumeration bin, obwohl der Compiler dies tatsächlich überprüft. Ich mache das, um sicherzustellen, dass ich keine Überraschungen auf der Straße bekomme. Um diese Überraschungen in Aktion zu sehen, können Sie den folgenden Code verwenden (tatsächlich habe ich gesehen, dass dies häufig im Datenbankcode passiert):

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



Ich weiß nicht mehr wo ich den Teil dieser Enum-Erweiterung bekomme, aber es ist vom . Das tut mir leid! Aber ich nahm dieses und änderte es für Aufzählungen mit Flags. Für Enums mit Flags habe ich das gemacht:

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

Beispiel:

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



Wenn Sie eine Ganzzahl haben, die als Bitmaske fungiert und einen oder mehrere Werte in einer [Flags] -Enumeration darstellen kann, können Sie diesen Code verwenden, um die einzelnen Flagwerte in einer Liste zu analysieren:

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



Ich benutze diesen Code, um int in meine enum zu schreiben:

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

Ich finde es die beste Lösung.




Links