Frage

Wie kann ein int zu einem geworfen werden enum in C#?

War es hilfreich?

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

enter image description here

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           
        }
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top