Int in Enumeration in C# umwandeln
Frage
Wie kann ein int
zu einem geworfen werden enum
in C#?
Lösung
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:
Ab Nummer kannst du auch
YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);
Andere Tipps
Wirf es einfach:
MyEnum e = (MyEnum)3;
Sie können mithilfe von überprüfen, ob es in Reichweite ist Enum.IsDefined:
if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }
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);
}
Verwendung:
Color colorEnum = "Red".ToEnum<Color>();
ODER
string color = "Red";
var colorEnum = color.ToEnum<Color>();
Ich denke, um eine vollständige Antwort zu erhalten, müssen die Leute wissen, wie Aufzählungen in .NET intern funktionieren.
Wie Dinge funktionieren
Eine Enumeration in .NET ist eine Struktur, die eine Reihe von Werten (Feldern) einem Basistyp zuordnet (der Standardwert ist int
).Sie können jedoch tatsächlich den Integraltyp auswählen, dem Ihre Aufzählung zugeordnet wird:
public enum Foo : short
In diesem Fall wird die Enumeration dem zugeordnet short
Datentyp, was bedeutet, dass er als Short im Speicher gespeichert wird und sich wie ein Short verhält, wenn Sie ihn umwandeln und verwenden.
Wenn man es aus IL-Sicht betrachtet, sieht eine (normale, int) Aufzählung so 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 hier Ihre Aufmerksamkeit erregen sollte, ist, dass die value__
wird getrennt von den Enum-Werten gespeichert.Im Fall der Aufzählung Foo
oben, die Art von value__
ist int16.Das bedeutet im Grunde, dass Sie in einer Enumeration alles speichern können, was Sie wollen. solange die Typen übereinstimmen.
Darauf möchte ich an dieser Stelle hinweisen System.Enum
ist ein Werttyp, was im Grunde das bedeutet BarFlag
wird 4 Bytes im Speicher beanspruchen und Foo
nimmt 2 ein – z.B.die Größe des zugrunde liegenden Typs (eigentlich ist es komplizierter, aber hey ...).
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 benennen Sie sie anders (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.
Um die Sicherheit zu gewährleisten, halte ich es für eine bewährte Vorgehensweise wissen, dass die zugrunde liegenden Typen gleich oder implizit konvertierbar sind und um sicherzustellen, dass die Enum-Werte vorhanden sind (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 Casting zu e2
Funktioniert auch!Aus der oben genannten Compiler-Perspektive macht dies Sinn:Die value__
Das Feld wird einfach mit entweder 5 oder 6 und wann gefüllt Console.WriteLine
Anrufe ToString()
, der Name von e1
wird aufgelöst, während der Name von e2
ist nicht.
Wenn das nicht Ihre Absicht ist, verwenden Sie Enum.IsDefined(typeof(MyEnum), 6)
um zu überprüfen, ob der Wert, den Sie umwandeln, einer definierten Enumeration zugeordnet ist.
Beachten Sie auch, dass ich den zugrunde liegenden Typ der Aufzählung explizit anspreche, auch wenn der Compiler dies tatsächlich überprüft.Ich mache das, 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 im 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();
}
Nehmen Sie das folgende Beispiel:
int one = 1;
MyEnum e = (MyEnum)one;
Ich verwende diesen Code, um int in meine Enumeration umzuwandeln:
if (typeof(YourEnum).IsEnumDefined(valueToCast)) return (YourEnum)valueToCast;
else { //handle it here, if its not defined }
Ich finde es die beste Lösung.
Unten finden Sie eine schöne 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;
}
}
Bei numerischen Werten ist dies sicherer, da auf jeden Fall ein Objekt zurückgegeben wird:
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;
}
}
Wenn Sie bereit für 4.0 sind .NETZ Framework, es gibt ein neues Enum.TryParse() Funktion, die sehr nützlich ist und gut mit dem [Flags]-Attribut zusammenarbeitet.Sehen Enum.TryParse-Methode (String, TEnum%)
Wenn Sie über eine Ganzzahl verfügen, die als Bitmaske fungiert und einen oder mehrere Werte in einer [Flags]-Enumeration darstellen könnte, können Sie diesen Code verwenden, um die einzelnen Flag-Werte in eine 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 davon ausgeht, dass der zugrunde liegende Typ der enum
ist eine vorzeichenbehaftete 32-Bit-Ganzzahl.Wenn es ein anderer numerischer Typ wäre, müssten Sie die fest codierte 32 ändern, um die Bits in diesem Typ widerzuspiegeln (oder sie programmgesteuert mit ableiten). Enum.GetUnderlyingType()
)
Manchmal hat man etwas dagegen MyEnum
Typ.Wie
var MyEnumType = typeof(MyEnumType);
Dann:
Enum.ToObject(typeof(MyEnum), 3)
Dies ist eine sichere Konvertierungsmethode, die die Aufzählung von Flags berücksichtigt:
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;
}
Um einen String in ENUM oder int in eine ENUM-Konstante umzuwandeln, müssen wir die Funktion Enum.Parse verwenden.Hier ist ein YouTube-Video https://www.youtube.com/watch?v=4nhx4VwdRDk was tatsächlich mit string demonstriert wird und das Gleiche gilt für int.
Der Code sieht wie unten gezeigt aus, wobei „red“ die Zeichenfolge und „MyColors“ die Farbe ENUM ist, die die Farbkonstanten enthält.
MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");
Ich komme etwas von der ursprünglichen Frage ab, aber ich habe es gefunden eine Antwort auf die Frage zum Stapelüberlauf Int-Wert aus Enum abrufen nützlich.Erstellen Sie eine statische Klasse mit public const int
Eigenschaften, sodass Sie ganz einfach eine Reihe verwandter Eigenschaften zusammenstellen können int
Konstanten und müssen sie dann nicht in sie umwandeln int
wenn Sie sie verwenden.
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;
}
Offensichtlich gehen einige der Enum-Typ-Funktionen verloren, aber für das Speichern einer Reihe von Datenbank-ID-Konstanten scheint es eine recht ordentliche Lösung zu sein.
Dadurch werden Ganzzahlen oder Zeichenfolgen in eine Zielenum mit teilweiser Übereinstimmung in dot.NET 4.0 analysiert, wobei Generika wie in Tawanis Dienstprogrammklasse oben verwendet werden.Ich verwende es, um Befehlszeilen-Switch-Variablen zu konvertieren, die möglicherweise unvollständig sind.Da eine Enumeration nicht null sein darf, sollten Sie logischerweise einen Standardwert angeben.Es kann so heißen:
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, von denen niemand erwähnt hat, dass sie auch explizit in Enum.TryParse() konvertiert werden.
Aus einer Zeichenfolge:(Enum.Parse ist veraltet, verwenden Sie Enum.TryParse)
enum Importance
{}
Importance importance;
if (Enum.TryParse(value, out importance))
{
}
Im Folgenden finden Sie 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;
}
In meinem Fall musste ich die Enumeration von einem WCF-Dienst zurückgeben.Ich brauchte auch einen benutzerfreundlichen Namen, nicht nur enum.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>();
Verschiedene Besetzungsmöglichkeiten hin und her 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);
}
}
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 Aufzählungen mit Flags modifiziert.Für Aufzählungen mit Flags habe ich Folgendes getan:
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;
Es kann Ihnen helfen, alle Eingabedaten in die vom Benutzer gewünschten Daten umzuwandeln Aufzählung.Angenommen, Sie haben standardmäßig eine Enumeration wie unten int.Bitte fügen Sie eine hinzu Standard Wert an erster Stelle Ihrer Aufzählung.Wird bei der Hilfsmethode 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;
}
}
Hinweis: Hier versuche ich, den Wert in int zu analysieren, da enum standardmäßig aktiviert ist intWenn Sie eine Aufzählung wie folgt definieren, ist das so Byte Typ.
public enum MediaType : byte
{
Default,
Audio,
Video,
Image
}
Sie müssen die Analyse 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
Hier ist eine Erweiterungsmethode, die umwandelt Int32
Zu Enum
.
Es berücksichtigt bitweise Flags, auch wenn der Wert höher als der maximal mögliche Wert ist.Zum Beispiel, wenn Sie eine Aufzählung mit Möglichkeiten haben 1, 2, Und 4, aber das int ist 9, es versteht das als 1 in Abwesenheit eines 8.Dadurch können Sie Datenaktualisierungen vor Codeaktualisierungen durchführen.
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);
}
Die einfache und klare Möglichkeit, in C# ein Int in eine Aufzählung 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));
}
}
Sie verwenden einfach Explizite Konvertierung Wandeln Sie int in enum oder enum in int um
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
}
}