Gibt es eine Möglichkeit zur Konvertierung eines enum
zu einer Liste, die alle Optionen der Aufzählung enthält?
- Wie man eine Aufzählung durchführt (33 Antworten )
Antworten
Zu viele Anzeigen?Dies führt zu einer IEnumerable<SomeEnum>
aller Werte einer Enum.
Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>();
Wenn Sie wollen, dass das ein List<SomeEnum>
fügen Sie einfach hinzu .ToList()
nach .Cast<SomeEnum>()
.
Um die Cast-Funktion auf ein Array anzuwenden, müssen Sie die System.Linq
in Ihrem Verwendungsbereich.
Die kurze Antwort lautet: nutzen:
(SomeEnum[])Enum.GetValues(typeof(SomeEnum))
Wenn Sie das für eine lokale Variable brauchen, ist es var allSomeEnumValues = (SomeEnum[])Enum.GetValues(typeof(SomeEnum));
.
Warum ist die Syntax so?!
El static
Methode GetValues
wurde bereits in den alten .NET 1.0 Tagen eingeführt. Sie gibt ein eindimensionales Array vom Laufzeittyp SomeEnum[]
. Da es sich aber um eine nicht-generische Methode handelt (Generika wurden erst mit .NET 2.0 eingeführt), kann sie ihren Rückgabetyp (Rückgabetyp zur Kompilierzeit) nicht als solchen deklarieren.
.NET-Arrays haben eine Art von Kovarianz, aber weil SomeEnum
wird ein Werttyp und da die Array-Typ-Kovarianz nicht mit Werttypen funktioniert, konnten sie nicht einmal den Rückgabetyp als object[]
o Enum[]
. (Dies ist ein Unterschied zu z. B. diese Überlast an GetCustomAttributes
von .NET 1.0 die zur Kompilierzeit den Rückgabetyp object[]
gibt aber tatsächlich ein Array vom Typ SomeAttribute[]
donde SomeAttribute
ist notwendigerweise ein Referenztyp).
Aus diesem Grund musste die .NET 1.0-Methode ihren Rückgabetyp wie folgt deklarieren System.Array
. Aber ich garantiere Ihnen, es ist ein SomeEnum[]
.
Jedes Mal, wenn Sie anrufen GetValues
wieder mit demselben Aufzählungstyp, muss es ein neues Array zuweisen und die Werte in das neue Array kopieren. Das liegt daran, dass Arrays durch den "Verbraucher" der Methode verändert werden können, so dass ein neues Array erstellt werden muss, um sicherzustellen, dass die Werte unverändert bleiben. In .NET 1.0 gab es keine guten schreibgeschützten Sammlungen.
Wenn Sie die Liste aller Werte an vielen verschiedenen Stellen benötigen, sollten Sie den Aufruf GetValues
nur einmal zu verwenden und das Ergebnis in einem schreibgeschützten Wrapper zwischenzuspeichern, zum Beispiel so:
public static readonly ReadOnlyCollection<SomeEnum> AllSomeEnumValues
= Array.AsReadOnly((SomeEnum[])Enum.GetValues(typeof(SomeEnum)));
Dann können Sie AllSomeEnumValues
und dieselbe Sammlung kann sicher wiederverwendet werden.
Warum ist es schlecht, die .Cast<SomeEnum>()
?
Viele andere Antworten verwenden .Cast<SomeEnum>()
. Das Problem dabei ist, dass es die nicht-generische IEnumerable
Umsetzung der Array
Klasse. Diese debe jeden der Werte in ein Feld mit der Bezeichnung System.Object
und dann mit Hilfe des Feldes Cast<>
Methode, um alle diese Werte wieder zu entpacken. Glücklicherweise ist die .Cast<>
Methode scheint den Laufzeittyp ihrer IEnumerable
Parameter (der this
Parameter), bevor es mit der Iteration durch die Sammlung beginnt, also ist es doch nicht so schlimm. Es stellt sich heraus .Cast<>
lässt die gleiche Array-Instanz durch.
Wenn Sie es verfolgen, indem Sie .ToArray()
o .ToList()
, wie in:
Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>().ToList() // DON'T do this
haben Sie ein weiteres Problem: Sie erstellen eine neue Sammlung (Array), wenn Sie GetValues
und erstellen Sie dann eine neue Sammlung ( List<>
) mit dem .ToList()
anrufen. Das ist also eine (zusätzliche) redundante Zuweisung einer ganzen Sammlung, um die Werte zu speichern.
Update: Seit .NET 5.0 (ab 2020) sind die obigen Informationen veraltet; es gibt endlich eine generische Methode (Generics wurden mit .NET Framework 2.0 aus dem Jahr 2005 eingeführt), so dass Sie jetzt einfach verwenden sollten:
Enum.GetValues<SomeEnum>()
deren Rückgabeparameter stark typisiert ist (als SomeEnum[]
).
Hier ist der Weg, den ich liebe, mit LINQ:
public class EnumModel
{
public int Value { get; set; }
public string Name { get; set; }
}
public enum MyEnum
{
Name1=1,
Name2=2,
Name3=3
}
public class Test
{
List<EnumModel> enums = ((MyEnum[])Enum.GetValues(typeof(MyEnum))).Select(c => new EnumModel() { Value = (int)c, Name = c.ToString() }).ToList();
// A list of Names only, does away with the need of EnumModel
List<string> MyNames = ((MyEnum[])Enum.GetValues(typeof(MyEnum))).Select(c => c.ToString()).ToList();
// A list of Values only, does away with the need of EnumModel
List<int> myValues = ((MyEnum[])Enum.GetValues(typeof(MyEnum))).Select(c => (int)c).ToList();
// A dictionnary of <string,int>
Dictionary<string,int> myDic = ((MyEnum[])Enum.GetValues(typeof(MyEnum))).ToDictionary(k => k.ToString(), v => (int)v);
}
Ich hoffe, es hilft
- See previous answers
- Weitere Antworten anzeigen