c# cast<> cast - Besetzung in C #





10 Answers

Besetzt es einfach:

MyEnum e = (MyEnum)3;

Sie können mit Enum.IsDefined überprüfen, ob es sich im Bereich Enum.IsDefined :

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

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




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

Wie Dinge funktionieren

Eine Enumeration in .NET ist eine Struktur, die einen Satz von Werten (Feldern) einem Basistyp zuordnet (der Standardwert ist int ). Sie können jedoch tatsächlich den ganzzahligen Typ auswählen, dem Ihr Enum zugeordnet ist:

public enum Foo : short

In diesem Fall wird die Enumeration dem short Datentyp zugeordnet. Dies bedeutet, dass sie als Kurzform im Speicher abgelegt wird und sich bei der Besetzung und Verwendung als Kurzform verhält.

Wenn Sie es aus Sicht der IL betrachten, sieht ein (normales, int) Enum 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 Sie hier beachten sollte, ist, dass der value__ getrennt von den Aufzählungswerten gespeichert wird. Im Fall des obigen value__ Foo ist der Typ von value__ . Dies bedeutet im Wesentlichen, dass Sie in einer Aufzählung speichern können, was Sie möchten, solange die Typen übereinstimmen .

An dieser Stelle möchte ich darauf hinweisen, dass es sich bei System.Enum um einen System.Enum handelt, was bedeutet, dass BarFlag 4 Bytes im Speicher und Foo 2 BarFlag , z. B. die Größe des zugrunde liegenden Typs (eigentlich mehr) komplizierter als das, aber hey ...).

Die Antwort

Wenn Sie also eine ganze Zahl haben, die Sie einer Enumenzuordnung zuordnen möchten, muss die Laufzeitumgebung nur zwei Dinge tun: Kopieren Sie die 4 Bytes und nennen Sie sie einen anderen Namen (den Namen der Enumeration). Das Kopieren ist implizit, da die Daten als Werttyp gespeichert werden. Dies bedeutet im Wesentlichen, dass Sie bei Verwendung von nicht verwaltetem Code einfach Enumerationen und Ganzzahlen austauschen können, ohne Daten zu kopieren.

Um es sicher zu machen, denke ich, ist es eine bewährte Methode, zu wissen, dass die zugrunde liegenden Typen gleich oder implizit konvertierbar sind, und um sicherzustellen, dass die Aufzählungswerte vorhanden sind (sie werden standardmäßig nicht geprüft!).

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

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 auch funktioniert! Aus der Sicht des Compilers ist dies sinnvoll: value__ Feld value__ wird einfach entweder mit 5 oder 6 gefüllt. Wenn Console.WriteLine ToString() , wird der Name von e1 aufgelöst, der Name von e2 jedoch nicht.

Wenn Sie dies nicht beabsichtigt haben, verwenden Sie Enum.IsDefined(typeof(MyEnum), 6) , um zu prüfen, ob der Wert, den Sie Maps in eine definierte Enum.IsDefined(typeof(MyEnum), 6) .

Beachten Sie auch, dass ich den zugrunde liegenden Typ der Enumeration explizit verstehe, obwohl der Compiler dies tatsächlich überprüft. Ich tue das, um sicherzustellen, dass ich auf der Straße keine Überraschungen mehr sehe. Um diese Überraschungen in Aktion zu sehen, können Sie den folgenden Code verwenden (eigentlich 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();
}



Ich verwende dieses Stück Code, um int in mein 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.




Bei numerischen Werten ist dies sicherer, da ein Objekt in jedem Fall 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 eine Ganzzahl haben, die als Bitmaske fungiert und einen oder mehrere Werte in einer [Flags] -Zahlung darstellen kann, können Sie diesen Code verwenden, um die einzelnen Flag-Werte in eine Liste zu parsen:

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



Dies ist eine sichere Konvertierungsmethode für Flags, die eine Aufzählung unterstützt:

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



Ein wenig weg von der ursprünglichen Frage, aber ich fand eine Antwort auf die -Frage . Erstellen Sie eine statische Klasse mit public const int Eigenschaften. So können Sie leicht eine Reihe verwandter int Konstanten zusammenstellen und müssen sie bei der Verwendung nicht in int konvertieren.

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 geht ein Teil der Enum-Typ-Funktionalität verloren, aber um eine Reihe von Datenbank-ID-Konstanten zu speichern, scheint dies eine ziemlich aufgeräumte Lösung zu sein.




Von einer Zeichenfolge: (Enum.Parse ist nicht mehr aktuell, verwenden Sie Enum.TryParse)

enum Importance
{}

Importance importance;

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



In meinem Fall musste ich die Aufzählung von einem WCF-Dienst zurücksenden. 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 von 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>();



Ich weiß nicht mehr, wo ich den Teil dieser Enumerationserweiterung bekomme, aber er stammt von . Das tut mir leid! Aber ich nahm dieses hier und modifizierte es mit Flaggen. 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;



Related