3898 Stimmen

Wie kann ich int in enum umwandeln?

Wie kann ein int an eine enum in C#?

4664voto

FlySwat Punkte 165766

Von einem int:

YourEnum foo = (YourEnum)yourInt;

Aus einer Zeichenkette:

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

Aktualisierung:

Von der Nummer aus können Sie auch

YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);

1 Stimmen

So korrekt sollte es sein: YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString) OR YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourInt) -- Wie zutreffend.

44 Stimmen

@FlySwat, was wäre, wenn YourEnum ist dynamisch und wird nur zur Laufzeit bekannt sein, und was ich möchte, ist eine Konvertierung in Enum ?

2 Stimmen

@Shimmy. Wenn die Aufzählung nur zur Laufzeit bekannt ist, sollten Sie sie dynamisch halten. Typsicherheit (strong typing) kann ohnehin nur vom Compiler garantiert werden. Sie können ein Objekt zur Laufzeit nicht stark typisieren. Dem kommt man am nächsten, wenn man Generika verwendet, aber der generische Typ muss zur Kompilierzeit bekannt sein. T ToEnum<T>(int x) { return (T)x; } aber es gibt keinen wirklichen Vorteil gegenüber dem direkten Gießen.

1167voto

Matt Hamilton Punkte 193704

Werfen Sie es einfach:

MyEnum e = (MyEnum)3;

Sie können überprüfen, ob es in Reichweite ist, indem Sie Enum.IsDefined :

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

244 Stimmen

Achten Sie darauf, dass Sie Enum.IsDefined nicht verwenden können, wenn Sie das Attribut Flags verwenden und der Wert eine Kombination von Flags ist, zum Beispiel: Keys.L | Keys.Control

27 Stimmen

Betreffend Enum.IsDefined Aber seien Sie sich bewusst, dass dies gefährlich sein kann: msdn.microsoft.com/de-us/library/ms229025(VS.90).aspx

4 Stimmen

Ich bevorzuge diese Definition: "Gibt an, ob eine Konstante mit einem bestimmten Wert in einer bestimmten Aufzählung existiert" de MSDN

288voto

Abdul Munim Punkte 18167

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

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

Verwendung:

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

OR

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

10 Stimmen

Für die Verarbeitung von Benutzereingaben ist es wahrscheinlich eine gute Idee, die Überladung von Enum.Parse aufzurufen, mit der Sie festlegen können, dass beim Vergleich NICHT zwischen Groß- und Kleinschreibung unterschieden wird (d. h. wenn ein Benutzer "rot" (Kleinbuchstaben) eingibt, würde der obige Code ohne diese Änderung abstürzen).

14 Stimmen

Praktisch, aber die Frage bezieht sich speziell auf ints.

3 Stimmen

Dies funktioniert auch, wenn die Zeichenkette eine ganze Zahl ist, z. B. "2".

221voto

atlaste Punkte 29028

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

Wie etwas funktioniert

Ein Enum in .NET ist eine Struktur, die einen Satz von Werten (Feldern) einem Basistyp zuordnet (der Standard ist int ). Sie können jedoch den Integraltyp wählen, dem Ihre Aufzählung zugeordnet ist:

public enum Foo : short

In diesem Fall wird die Aufzählung auf die Datei short Datentyp, d. h. er wird im Speicher als short gespeichert und verhält sich wie ein short, wenn Sie ihn casten und verwenden.

Aus der Sicht der AWL sieht eine (normale, int) Enum 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 die value__ wird getrennt von den Aufzählungswerten gespeichert. Im Fall der Aufzählung Foo oben, die Art der value__ ist int16. Das bedeutet im Grunde, dass Sie in einer Aufzählung speichern können, was immer Sie wollen, solange die Typen übereinstimmen .

An dieser Stelle möchte ich darauf hinweisen, dass System.Enum ist ein Wertetyp, was im Grunde bedeutet, dass BarFlag belegt 4 Bytes im Speicher und Foo nimmt 2 -- z.B. die Größe des zugrundeliegenden Typs (eigentlich ist es komplizierter als das, aber hey...).

Die Antwort

Wenn Sie also eine Ganzzahl haben, die Sie einer Aufzählung zuordnen wollen, muss die Laufzeitumgebung nur zwei Dinge tun: die 4 Bytes kopieren und einen anderen Namen vergeben (den Namen der Aufzählung). Das Kopieren erfolgt implizit, da die Daten als Werttyp gespeichert werden. Das bedeutet, dass Sie bei Verwendung von nicht verwaltetem Code Enums und Integers einfach austauschen können, ohne Daten zu kopieren.

Um die Sicherheit zu gewährleisten, ist es meiner Meinung nach am besten, wenn wissen, dass die zugrundeliegenden Typen identisch oder implizit konvertierbar sind und um sicherzustellen, dass die Enum-Werte existieren (sie werden standardmäßig nicht überprüft!).

Um zu sehen, wie das funktioniert, probieren Sie den folgenden Code aus:

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 Werfen nach e2 funktioniert auch! Aus der obigen Compiler-Perspektive macht dies Sinn: Die value__ wird einfach mit 5 oder 6 gefüllt, und wenn Console.WriteLine ruft auf. ToString() der Name von e1 aufgelöst wird, während der Name von e2 ist nicht.

Wenn Sie das nicht beabsichtigen, verwenden Sie Enum.IsDefined(typeof(MyEnum), 6) um zu prüfen, ob der Wert, den Sie casten, einer definierten Aufzählung entspricht.

Beachten Sie auch, dass ich den zugrundeliegenden Typ der Aufzählung explizit angebe, auch wenn der Compiler dies tatsächlich überprüft. Ich tue dies, um sicherzustellen, dass ich später keine Überraschungen erlebe. Um diese Überraschungen in Aktion zu sehen, können Sie den folgenden Code verwenden (tatsächlich habe ich das schon oft in Datenbankcode gesehen):

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

9 Stimmen

Mir ist klar, dass dies ein alter Beitrag ist, aber wie erlangt man dieses Niveau an Wissen in C#? Ist dies aus dem Lesen durch die C #-Spezifikation?

30 Stimmen

@Rolan Ich wünschte manchmal, mehr Leute würden das fragen :-) Um ehrlich zu sein, ich weiß es nicht wirklich; ich versuche zu verstehen, wie die Dinge funktionieren und hole mir Informationen, wo immer ich sie bekommen kann. Ich habe den C#-Standard gelesen, aber ich dekompiliere auch regelmäßig Code mit Reflector (ich schaue mir sogar oft den x86-Assembler-Code an) und mache viele kleine Experimente. Auch das Wissen über andere Sprachen ist in diesem Fall hilfreich; ich beschäftige mich jetzt seit etwa 30 Jahren mit CS, und irgendwann werden bestimmte Dinge "logisch" - z. B. sollte ein Enum integrale Typen haben, weil sonst die Interoperabilität nicht mehr gegeben ist (oder die Leistung den Bach runtergeht).

14 Stimmen

Ich glaube, der Schlüssel zu einer guten Softwareentwicklung ist das Wissen, wie etwas funktioniert. Für mich bedeutet das, dass ich, wenn ich einen Code schreibe, weiß, wie er sich z. B. auf Prozessoroperationen und Speicherzugriffe auswirkt. Wenn Sie fragen, wie man dieses Niveau erreichen kann, würde ich vorschlagen, eine Menge kleiner Testfälle zu erstellen, sie immer schwieriger zu machen, jedes Mal zu versuchen, das Ergebnis vorherzusagen, und sie anschließend zu testen (einschließlich Dekompilierung usw.). Nachdem man alle Details und alle Eigenschaften herausgefunden hat, kann man überprüfen, ob man es in der (langweiligen) Norm richtig gemacht hat. Zumindest wäre das mein Ansatz.

144voto

abigblackman Punkte 1361

Nehmen Sie das folgende Beispiel:

int one = 1;
MyEnum e = (MyEnum)one;

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X