Existe-t-il un moyen de convertir un enum
à une liste qui contient toutes les options de l'enum ?
- Comment énumérer une énumération (5 réponses )
Réponses
Trop de publicités?Cela renverra un IEnumerable<SomeEnum>
de toutes les valeurs d'un Enum.
Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>();
Si vous voulez que ce soit un List<SomeEnum>
il suffit d'ajouter .ToList()
après .Cast<SomeEnum>()
.
Pour utiliser la fonction Cast sur un tableau, vous devez disposer de l'attribut System.Linq
dans votre section d'utilisation.
La réponse courte est : utiliser :
(SomeEnum[])Enum.GetValues(typeof(SomeEnum))
Si vous avez besoin de cela pour une variable locale, c'est var allSomeEnumValues = (SomeEnum[])Enum.GetValues(typeof(SomeEnum));
.
Pourquoi la syntaxe est comme ça ? !
Le site static
méthode GetValues
a été introduit à l'époque de la version 1.0 de .NET. Il renvoie un tableau unidimensionnel de type runtime SomeEnum[]
. Mais comme il s'agit d'une méthode non générique (la générique n'a pas été introduite avant .NET 2.0), elle ne peut pas déclarer son type de retour (type de retour au moment de la compilation) en tant que tel.
Les tableaux de .NET ont une sorte de covariance, mais parce que SomeEnum
sera un type de valeur et comme la covariance des types de tableaux ne fonctionne pas avec les types de valeurs, ils n'ont même pas pu déclarer le type de retour en tant que object[]
ou Enum[]
. (Ceci est différent de e.g. cette surcharge de GetCustomAttributes
à partir de .NET 1.0 qui a un type de retour au moment de la compilation object[]
mais renvoie en fait un tableau de type SomeAttribute[]
où SomeAttribute
est nécessairement un type de référence).
Pour cette raison, la méthode .NET 1.0 devait déclarer son type de retour comme étant System.Array
. Mais je vous garantis que c'est un SomeEnum[]
.
Chaque fois que vous appelez GetValues
avec le même type d'enum, elle devra allouer un nouveau tableau et copier les valeurs dans le nouveau tableau. En effet, les tableaux peuvent être écrits (modifiés) par le "consommateur" de la méthode, qui doit donc créer un nouveau tableau pour s'assurer que les valeurs restent inchangées. .NET 1.0 ne disposait pas de bonnes collections en lecture seule.
Si vous avez besoin de la liste de toutes les valeurs à plusieurs endroits différents, pensez à appeler GetValues
une seule fois et mettre en cache le résultat dans un wrapper en lecture seule, par exemple comme ceci :
public static readonly ReadOnlyCollection<SomeEnum> AllSomeEnumValues
= Array.AsReadOnly((SomeEnum[])Enum.GetValues(typeof(SomeEnum)));
Vous pouvez alors utiliser AllSomeEnumValues
plusieurs fois, et la même collection peut être réutilisée en toute sécurité.
Pourquoi est-ce mauvais d'utiliser .Cast<SomeEnum>()
?
Beaucoup d'autres réponses utilisent .Cast<SomeEnum>()
. Le problème, c'est qu'elle utilise la fonction non générique IEnumerable
mise en œuvre de la Array
classe. Ce site devrait a impliqué la mise en boîte de chacune des valeurs dans une System.Object
puis en utilisant l'option Cast<>
pour débloquer toutes ces valeurs à nouveau. Heureusement, la méthode .Cast<>
semble vérifier le type d'exécution de sa méthode IEnumerable
(le paramètre this
) avant de commencer à itérer dans la collection, donc ce n'est pas si mal après tout. Il s'avère que .Cast<>
laisse passer la même instance de tableau.
Si vous le suivez en .ToArray()
ou .ToList()
comme dans :
Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>().ToList() // DON'T do this
vous avez un autre problème : vous créez une nouvelle collection (tableau) lorsque vous appelez GetValues
et ensuite créer encore une nouvelle collection ( List<>
) avec le .ToList()
appel. Il s'agit donc d'une allocation (supplémentaire) redondante d'une collection entière pour contenir les valeurs.
Voici la méthode que j'aime, en utilisant 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 = ((IEnumerable<EnumModel>)Enum.GetValues(typeof(MyEnum))).Select(c => new EnumModel() { Value = (int)c, Name = c.ToString() }).ToList();
}
J'espère que cela vous aidera
- Réponses précédentes
- Plus de réponses