Wie kann man int in enum umwandeln?

3189

Wie kann ein intin ein enumC # umgewandelt werden?

Lomaxx
quelle

Antworten:

3792

Aus einer Zeichenfolge:

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

Aus einem int:

YourEnum foo = (YourEnum)yourInt;

Aktualisieren:

Von Nummer können Sie auch

YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);
FlySwat
quelle
31
@FlySwat, was YourEnumist , wenn es dynamisch ist und nur zur Laufzeit bekannt ist, und was ich konvertieren möchte Enum?
Shimmy Weitzhandler
226
Beachten Sie, dass Enum.Parse NICHT funktioniert, wenn Ihr Code verschleiert ist. Zur Laufzeit nach der Verschleierung wird die Zeichenfolge mit den Aufzählungsnamen verglichen, und zu diesem Zeitpunkt sind die Namen der Aufzählungen nicht so, wie Sie es erwarten würden. Ihre Analyse schlägt dort fehl, wo sie zuvor erfolgreich war.
Jropella
158
ACHTUNG Wenn Sie die obige Syntax "aus einer Zeichenfolge" verwenden und eine ungültige Zeichenfolge übergeben, die eine Zahl ist (z. B. "2342342" - vorausgesetzt, dies ist kein Wert Ihrer Aufzählung), wird dies tatsächlich ohne Fehler zugelassen! Ihre Aufzählung hat diesen Wert (2342342), obwohl dies in der Aufzählung selbst keine gültige Wahl ist.
JoeCool
132
Ich denke, diese Antwort ist jetzt etwas veraltet. Für Zeichenfolgen sollten Sie var result = Enum.TryParse(yourString, out yourEnum)heutzutage wirklich verwenden (und das Ergebnis überprüfen, um festzustellen, ob die Konvertierung fehlgeschlagen ist).
Justin T Conroy
20
Es ist auch möglich, die Enum.ParseGroß- und Kleinschreibung nicht zu trueberücksichtigen, indem dem Aufruf ein Parameterwert hinzugefügt wird :YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString, true);
Erik Schierboom
900

Wirf es einfach:

MyEnum e = (MyEnum)3;

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

if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }
Matt Hamilton
quelle
218
Beachten Sie, dass Sie Enum.IsDefined nicht verwenden können, wenn Sie das Flags-Attribut verwenden und der Wert eine Kombination von Flags ist, zum Beispiel: Keys.L | Keys.Control
dtroy
15
In Bezug auf Enum.IsDefined, beachten Sie, dass es gefährlich sein kann: msdn.microsoft.com/en-us/library/ms229025(VS.90).aspx
adrian
3
Ich bevorzuge diese Definition: "Gibt eine Angabe zurück, ob eine Konstante mit einem angegebenen Wert in einer angegebenen Aufzählung vorhanden ist" von MSDN
Pap
3
... Weil Ihre Definition irreführend sein kann, weil Sie sagen: "... prüfen Sie, ob sie im Bereich liegt ...", was impliziert, dass innerhalb eines Zahlenbereichs mit Anfangs- und Endgrenzen ...
Pap
3
@ mac9416 Ich habe versucht, ein kurzes Beispiel unter gist.github.com/alowdon/f7354cda97bac70b44e1c04bc0991bcc zu geben. WennIsDefined Sie Eingabewerte überprüfen, sind Sie im Grunde anfällig für Personen, die später neue Aufzählungswerte hinzufügen, die eine IsDefinedPrüfung bestehen würden (seit dem neuen Wert ist im neuen Code vorhanden), funktioniert jedoch möglicherweise nicht mit dem ursprünglichen Code, den Sie geschrieben haben. Es ist daher sicherer, die Aufzählungswerte, die Ihr Code verarbeiten kann, explizit anzugeben.
Adrian
238

Alternativ können Sie eine Erweiterungsmethode anstelle eines Einzeilers verwenden:

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

Verwendungszweck:

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

ODER

string color = "Red";
var colorEnum = color.ToEnum<Color>();
Abdul Munim
quelle
7
Für die Verarbeitung von Benutzereingaben ist es wahrscheinlich eine gute Idee, die Überladung von Enum.Parse aufzurufen, mit der Sie angeben können, dass beim Vergleich NICHT zwischen Groß- und Kleinschreibung unterschieden wird (dh ein Benutzer, der "rot" (Kleinbuchstaben) eingibt, würde den obigen Code ohne diese Änderung zum Absturz bringen .)
BrainSlugs83
9
Praktisch, aber die Frage fragt speziell nach Ints.
BJury
2
Dies funktioniert auch, wenn die Zeichenfolge eine Ganzzahl ist, z. B. "2"
TruthOf42
2
Dies löst eine Ausnahme aus, wenn enumString null ist (hatte gestern ein ähnliches Problem). Verwenden Sie TryParse anstelle von Parse. TryParse prüft auch, ob T ein Aufzählungstyp ist
Justin
Diese Art der Erweiterungsmethode System.Stringscheint eine Verschmutzung des Namespaces zu sein
Herr Anderson,
160

Ich denke, um eine vollständige Antwort zu erhalten, müssen die Leute wissen, wie Aufzählungen intern in .NET funktionieren.

Wie Dinge funktionieren

Eine Aufzählung in .NET ist eine Struktur, die eine Reihe von Werten (Feldern) einem Basistyp zuordnet (Standard ist int). Sie können jedoch tatsächlich den Integraltyp auswählen, dem Ihre Aufzählung zugeordnet ist:

public enum Foo : short

In diesem Fall wird die Aufzählung dem shortDatentyp zugeordnet. Dies bedeutet, dass sie als Short im Speicher gespeichert wird und sich beim Casting und Verwenden als Short verhält.

Wenn Sie es aus IL-Sicht betrachten, sieht eine (normale, int) Aufzählung folgendermaßen 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 Ihre Aufmerksamkeit hier erregen sollte, ist, dass das value__getrennt von den Aufzählungswerten gespeichert wird. Im Fall der Fooobigen Aufzählung ist der Typ von value__int16. Dies bedeutet im Grunde, dass Sie alles, was Sie wollen, in einer Aufzählung speichern können, solange die Typen übereinstimmen .

An dieser Stelle möchte ich darauf hinweisen, dass dies System.Enumein Werttyp ist, was im Grunde bedeutet, dass BarFlag4 Bytes im Speicher und Foo2 Bytes belegt werden - z. B. die Größe des zugrunde liegenden Typs (es ist tatsächlich komplizierter als das, aber Hallo...).

Die Antwort

Wenn Sie also eine Ganzzahl haben, die Sie einer Aufzählung zuordnen möchten, muss die Laufzeit nur zwei Dinge tun: Kopieren Sie die 4 Bytes und nennen Sie sie etwas anderes (den Namen der Aufzählung). Das Kopieren ist implizit, da die Daten als Werttyp gespeichert werden. Dies bedeutet im Grunde, dass Sie bei Verwendung von nicht verwaltetem Code einfach Aufzählungen und Ganzzahlen austauschen können, ohne Daten zu kopieren.

Aus Sicherheitsgründen ist es meiner Meinung nach eine bewährte Methode, zu wissen, dass die zugrunde liegenden Typen identisch oder implizit konvertierbar sind, und sicherzustellen, dass die Aufzählungswerte vorhanden sind (sie werden nicht standardmäßig überprüft!).

Versuchen Sie den folgenden Code, um zu sehen, wie dies 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 Casting e2auch funktioniert! Aus der obigen Compiler-Perspektive ist dies sinnvoll: Das value__Feld wird einfach mit 5 oder 6 gefüllt, und bei Console.WriteLineAufrufen ToString()wird der Name von e1aufgelöst, der Name von e2nicht.

Wenn dies nicht beabsichtigt ist Enum.IsDefined(typeof(MyEnum), 6), überprüfen Sie mit, ob der Wert, den Sie übertragen, einer definierten Aufzählung zugeordnet ist.

Beachten Sie auch, dass ich den zugrunde liegenden Typ der Aufzählung explizit wiedergebe, obwohl der Compiler dies tatsächlich überprüft. Ich mache das, um sicherzustellen, dass ich später keine Überraschungen erleide. Um diese Überraschungen in Aktion zu sehen, können Sie den folgenden Code verwenden (tatsächlich habe ich gesehen, dass dies im Datenbankcode häufig vorkommt):

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
quelle
7
Mir ist klar, dass dies ein alter Beitrag ist, aber wie können Sie diesen Wissensstand in c # erlangen? Ist dies vom Lesen der C # -Spezifikation?
Rolan
20
@ Rolan Ich wünschte manchmal, mehr Leute würden das fragen. :-) Um ehrlich zu sein, weiß ich es nicht wirklich; Ich versuche zu verstehen, wie die Dinge funktionieren, und erhalte Informationen, wo immer ich sie bekommen kann. Ich habe den C # -Standard gelesen, aber ich habe auch regelmäßig Code mit Reflector dekompiliert (ich schaue mir sogar den x86-Assembler-Code viel an) und mache Tonnen kleiner Experimente. In diesem Fall hilft es auch, andere Sprachen zu kennen. Ich mache jetzt seit ungefähr 30 Jahren CS und irgendwann werden bestimmte Dinge "logisch" - z. Eine Aufzählung sollte integrale Typen sein, da sonst Interop unterbrochen wird (oder Ihre Leistung den Bach runtergeht).
Atlaste
9
Ich glaube, der Schlüssel zum richtigen Software-Engineering liegt darin, zu wissen, wie Dinge funktionieren. Für mich bedeutet das, dass Sie, wenn Sie einen Code schreiben, wissen, wie er grob in f.ex übersetzt wird. Prozessoroperationen und Speicherabrufe / -schreibvorgänge. Wenn Sie sich fragen, wie Sie dieses Niveau erreichen können, würde ich vorschlagen, eine Menge kleiner Testfälle zu erstellen, um sie im Laufe der Zeit härter zu machen, das Ergebnis jedes Mal vorherzusagen und sie anschließend zu testen (einschließlich Dekompilierung usw.). Nachdem Sie alle Details und Eigenschaften herausgefunden haben, können Sie überprüfen, ob Sie den (stumpfen) Standard richtig verstanden haben. Zumindest wäre das mein Ansatz.
Atlaste
1
Fantastische Antwort, danke! In Ihrem letzten Codebeispiel wird zur Laufzeit eine Ausnahme ausgelöst, da o ein Objekt ist. Sie können eine int-Variable in einen Short umwandeln, solange sie in den Short-Bereich fällt.
gravidThoughts
@gravidThoughts Danke. Tatsächlich handelt es sich um eine Unboxing-Operation, sodass keine impliziten Konvertierungen wie die von Ihnen beschriebenen durchgeführt werden. Casting ist in C # manchmal verwirrend, wenn Sie die Details nicht kennen ... Wie auch immer, weil int! = short, Wird es werfen (Unboxing schlägt fehl). Wenn Sie dies tun object o = (short)5;, wird es funktionieren, da dann die Typen übereinstimmen. Es geht nicht um die Reichweite, es geht wirklich um den Typ.
Atlaste
121

Nehmen Sie das folgende Beispiel:

int one = 1;
MyEnum e = (MyEnum)one;
abigblackman
quelle
64

Ich verwende diesen Code, um int in meine Aufzählung umzuwandeln:

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

Ich finde es die beste Lösung.

MSkuta
quelle
1
das ist gut. Ich war überrascht, dass es keine Ausnahme gibt, wenn ein ungültiger Wert in eine int-Backed-Enumeration umgewandelt wird.
Orion Elenzil
Dies ist eigentlich nicht so anders als die am besten bewertete Antwort. In dieser Antwort wird auch die Verwendung von Enum.IsDefined erläutert, nachdem Sie die Zeichenfolge in den Enum-Typ umgewandelt haben. Selbst wenn die Zeichenfolge fehlerfrei gegossen wurde, wird Enum.IsDefined sie dennoch abfangen
Don Cheadle
53

Unten finden Sie eine nette Utility-Klasse für 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
quelle
47

Bei numerischen Werten ist dies sicherer, da ein Objekt zurückgegeben wird, egal was passiert:

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
quelle
Funktioniert nicht für Flaggen enum
Seyed Morteza Mousavi
44

Wenn Sie für 4.0 .NET Framework bereit sind , gibt es eine neue Enum.TryParse () -Funktion, die sehr nützlich ist und gut mit dem Attribut [Flags] funktioniert. Siehe Enum.TryParse-Methode (String, TEnum%)

Ryan Russon
quelle
21
Dies ist nützlich, wenn Sie aus einer Zeichenfolge konvertieren. Aber nicht beim Konvertieren von einem int.
CodesInChaos
35

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

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

Beachten Sie, dass dies voraussetzt, dass der zugrunde liegende Typ von enumeine vorzeichenbehaftete 32-Bit-Ganzzahl ist. Wenn es sich um einen anderen numerischen Typ handeln würde, müssten Sie den fest codierten 32 ändern, um die Bits in diesem Typ wiederzugeben (oder ihn programmgesteuert mit ableiten Enum.GetUnderlyingType()).

Evan M.
quelle
1
Wird diese Schleife niemals beendet? flagIterator = 0x00000001, flagIterator = 0x00000002, flagIterator = 0x00000004, ..., flagIterator = 0x40000000, flagIterator = 0x80000000, flagIterator = 0x00000000. Mit anderen Worten, der Wert ist immer niedriger als 0x80000000, weil er nach dem Fall, in dem Bit D31 = 1 ist, auf Null überläuft. Dann bleibt er für immer 0, weil das Verschieben nach links den Wert 0 ergibt 0
Christian Gingras
Toller Fang @christiangingras, danke! Ich habe die Antwort geändert, um dies zu berücksichtigen, und sie sollte berücksichtigen, wann das höchste Bit gesetzt ist (dh 0x80000000 / Int32.MinValue)
Evan M
27

Manchmal haben Sie ein Objekt für den MyEnumTyp. Mögen

var MyEnumType = typeof(MyEnumType);

Dann:

Enum.ToObject(typeof(MyEnum), 3)
LD
quelle
26

Dies ist eine sichere Konvertierungsmethode für die Aufzählung von Flags:

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
quelle
3
Dies kann jetzt mit C # 7.3 verbessert werden, indem auf Enumstatt beschränkt wird struct, was bedeutet, dass wir uns nicht auf die Laufzeitprüfung verlassen müssen!
Scott
20

Geben Sie hier die Bildbeschreibung ein

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

Der Code lautet wie folgt: "Rot" ist die Zeichenfolge und "MyColors" ist die Farbe ENUM mit den Farbkonstanten.

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

Etwas abseits der ursprünglichen Frage, aber ich fand eine Antwort auf die Frage " Stapelüberlauf" . Erstellen Sie eine statische Klasse mit public const intEigenschaften, damit Sie auf einfache Weise eine Reihe verwandter intKonstanten zusammenfassen können, ohne sie intbei der Verwendung umwandeln zu müssen.

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

Natürlich geht ein Teil der Funktionalität des Aufzählungstyps verloren, aber zum Speichern einer Reihe von Datenbank-ID-Konstanten scheint dies eine ziemlich ordentliche Lösung zu sein.

Ted
quelle
5
Aufzählungen ersetzten die Verwendung solcher Ganzzahlkonstanten, da sie mehr Typensicherheit bieten
Paul Richards
1
Paul, dies ist eine Methode zum Sammeln zusammengehöriger int-Konstanten (z. B. Datenbank-ID-Konstanten), damit sie direkt verwendet werden können, ohne dass sie bei jeder Verwendung in int umgewandelt werden müssen. Ihr Typ ist eine Ganzzahl, nicht beispielsweise DatabaseIdsEnum.
Ted
1
Es gibt mindestens eine Situation, in der ich festgestellt habe, dass die Sicherheit vom Typ Enum unbeabsichtigt umgangen werden kann.
Thierry
Aufzählungen stellen aber auch sicher, dass alle Werte eindeutig sind, was diesem Ansatz ebenfalls fehlt
derHugo
15

Dadurch werden Ganzzahlen oder Zeichenfolgen in einer Zielaufzählung mit teilweiser Übereinstimmung in dot.NET 4.0 unter Verwendung von Generika wie in der obigen Dienstprogrammklasse von Tawani analysiert. Ich verwende es, um Befehlszeilen-Switch-Variablen zu konvertieren, die möglicherweise unvollständig sind. Da eine Aufzählung nicht null sein kann, sollten Sie logisch einen Standardwert angeben. Es kann so genannt werden:

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

Hier ist der 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;
                }
            }
        }
    }
}

Zu Ihrer Information : Die Frage betraf Ganzzahlen, die niemand erwähnt hat und die auch explizit in Enum.TryParse () konvertiert werden.

CZahrobsky
quelle
13

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

enum Importance
{}

Importance importance;

if (Enum.TryParse(value, out importance))
{
}
Will Yu
quelle
4
Die Frage fragt speziell nach ganzen Zahlen.
BJury
4
Wird Yu bitte Ihre Antwort bearbeiten, um alle wissen zu lassen, dass Enum.TryParse an einer Zeichenfolge mit dem Wert oder Namen der Enumeration arbeitet (ich konnte nicht widerstehen)
JeremyWeir
1
Jeremy, Weir arbeitet daran (konnte auch nicht widerstehen).
Huysentruitw
11

Das Folgende 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;
        }
Kamran Shahid
quelle
10

In meinem Fall musste ich die Aufzählung von einem WCF-Dienst zurückgeben. Ich brauchte auch einen freundlichen Namen, nicht nur die Aufzählung.ToString ().

Hier ist meine WCF-Klasse.

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

Hier ist die Erweiterungsmethode, die die Beschreibung aus der Aufzählung erhält.

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

Implementierung:

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

Ich weiß nicht mehr, woher ich den Teil dieser Enum-Erweiterung bekomme, aber er stammt von stackoverflow. Das tut mir leid! Aber ich habe dieses genommen und es für Enums mit Flags modifiziert. Für Enums mit Flags habe ich folgendes 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;
Franki1986
quelle
9

Sie sollten eine Art passende Entspannung einbauen, um robuster zu sein.

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

Testfall

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

quelle
Das ist eine schöne Antwort. Es ist eine Schande, dass es im Moment so weit unten auf der Seite ist!
MikeBeaton
8

Verschiedene Möglichkeiten zum und vom Casting 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);


 }
}
Google Mail-Benutzer
quelle
8

Es kann Ihnen helfen, alle Eingabedaten in die vom Benutzer gewünschte Aufzählung zu konvertieren . Angenommen, Sie haben eine Aufzählung wie die folgende, die standardmäßig int ist . Bitte fügen Sie zuerst in Ihrer Aufzählung einen Standardwert hinzu . Dies wird bei Helfern verwendet, wenn keine Übereinstimmung mit dem Eingabewert gefunden wird.

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: Hier versuche ich Wert in int zu analysieren, weil Enum ist standardmäßig int Wenn Sie Aufzählungs wie diese definieren, ist Byte - Typ.

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

Sie müssen das Parsen bei der Hilfsmethode von ändern

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

zu

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

Ich überprüfe meine Methode auf folgende Eingaben

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

Entschuldigung für mein Englisch

reza.cse08
quelle
8

Hier ist eine Erweiterungsmethode, Int32die umgewandelt wird Enum.

Bitweise Flags werden auch dann berücksichtigt, wenn der Wert höher als das maximal mögliche ist. Wenn Sie beispielsweise eine Aufzählung mit den Möglichkeiten 1 , 2 und 4 haben , das int jedoch 9 ist , wird dies als 1 in Abwesenheit einer 8 verstanden . Auf diese Weise können Sie Datenaktualisierungen vor Codeaktualisierungen vornehmen.

   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
quelle
6

die einfache und übersichtliche Möglichkeit, ein int in c # in enum umzuwandeln:

 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
quelle
6

Sie verwenden einfach die explizite Konvertierung. Cast int to enum oder 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
quelle
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
quelle
3

Du magst einfach unten:

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

So stellen Sie sicher, dass Sie nur die richtigen Werte umwandeln und ansonsten eine Ausnahme auslösen können:

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

Beachten Sie, dass die Verwendung von IsDefined kostspielig ist und sogar mehr als nur das Casting. Daher hängt es von Ihrer Implementierung ab, ob Sie IsDefined verwenden oder nicht.

Mselmi Ali
quelle
3

Sie können die Erweiterungsmethode verwenden.

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

Verwenden Sie wie unten Code

Aufzählung:

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

Verwendungszweck :

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