enums cast<> - Besetzung in C#




to type (18)

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

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


Verschiedene Möglichkeiten, von und nach 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);


 }
}

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

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

enum Importance
{}

Importance importance;

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

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

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

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

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

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;

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

Hierbei werden Ganzzahlen oder Zeichenfolgen in einer Ziel-Enumeration mit teilweiser Übereinstimmung in dot.NET 4.0 mit Generics wie in der oben genannten Tawani-Utility-Klasse analysiert. Ich verwende es, um Befehlszeilenschaltervariablen 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 aufgerufen 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 war nach ganzen Zahlen, die niemand erwähnt hat, auch explizit in Enum konvertieren.TryParse ()


Von einer Schnur:

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

Von einem int:

YourEnum foo = (YourEnum)yourInt;

Aktualisieren:

Von der Nummer kannst du auch

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

Um eine Zeichenfolge in ENUM oder int in eine ENUM-Konstante zu konvertieren, müssen Sie 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, wobei "rot" die Zeichenfolge und "MyColors" die Farbe ENUM ist, die die Farbkonstanten aufweist.

MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");

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

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.


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


Nehmen Sie das folgende Beispiel:

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

Zusätzlich zu den anderen bisherigen Antworten gibt es hier ein nicht offensichtliches Beispiel, bei dem static_cast nicht ausreicht, um reinterpret_cast benötigen. Angenommen, es gibt eine Funktion, die in einem Ausgabeparameter Zeiger auf Objekte verschiedener Klassen (die keine gemeinsame Basisklasse haben) zurückgibt. Ein reales Beispiel für eine solche Funktion ist CoCreateInstance() (siehe den letzten Parameter, der in Wirklichkeit void** ). Angenommen, Sie fordern eine bestimmte Objektklasse von dieser Funktion an, so dass Sie den Typ des Zeigers im Voraus wissen (was Sie häufig für COM-Objekte tun). In diesem Fall können Sie mit static_cast keinen Zeiger auf Ihren Zeiger in void** static_cast : Sie benötigen reinterpret_cast<void**>(&yourPointer) .

In Code:

#include <windows.h>
#include <netfw.h>
.....
INetFwPolicy2* pNetFwPolicy2 = nullptr;
HRESULT hr = CoCreateInstance(__uuidof(NetFwPolicy2), nullptr,
    CLSCTX_INPROC_SERVER, __uuidof(INetFwPolicy2),
    //static_cast<void**>(&pNetFwPolicy2) would give a compile error
    reinterpret_cast<void**>(&pNetFwPolicy2) );

static_cast funktioniert jedoch für einfache Zeiger (nicht für Zeiger auf Zeiger), sodass der obige Code umgeschrieben werden kann, um reinterpret_cast (zum Preis einer zusätzlichen Variablen) folgendermaßen zu vermeiden:

#include <windows.h>
#include <netfw.h>
.....
INetFwPolicy2* pNetFwPolicy2 = nullptr;
void* tmp = nullptr;
HRESULT hr = CoCreateInstance(__uuidof(NetFwPolicy2), nullptr,
    CLSCTX_INPROC_SERVER, __uuidof(INetFwPolicy2),
    &tmp );
pNetFwPolicy2 = static_cast<INetFwPolicy2*>(tmp);






c# enums casting