Comment pouvez-vous énumérer un enum
en C #?
Par exemple, le code suivant ne compile pas:
public enum Suit
{
Spades,
Hearts,
Clubs,
Diamonds
}
public void EnumerateAllSuitsDemoMethod()
{
foreach (Suit suit in Suit)
{
DoSomething(suit);
}
}
Et cela donne l'erreur de compilation suivante:
«Suit» est un «type» mais est utilisé comme une «variable»
Il échoue sur le Suit
mot - clé, le second.
Réponses:
Remarque : le transtypage en
(Suit[])
n'est pas strictement nécessaire, mais il rend le code 0,5 ns plus rapide .la source
enum.GetValues
. Vous devez utiliser la réflexion dans ce cas.enum E {A = 0, B = 0}
.Enum.GetValues
entraîne le renvoi de deux valeurs, bien qu'elles soient identiques.E.A == E.B
est vrai, il n'y a donc pas de distinction. Si vous voulez des noms individuels, alors vous devriez chercherEnum.GetNames
.Distinct
extension de Linq (depuis .NET 3.5), doncforeach (var suit in ((Suit[])Enum.GetValues(typeof(Suit))).Distinct()) { }
.var
pour le type. Le compilateur crée la variable anObject
au lieu de l'énumération. Répertoriez explicitement le type d'énumération.Il me semble que vous voulez vraiment imprimer les noms de chaque énumération plutôt que les valeurs. Dans ce cas, cela
Enum.GetNames()
semble être la bonne approche.Soit dit en passant, l'incrémentation de la valeur n'est pas un bon moyen d'énumérer les valeurs d'une énumération. Vous devriez le faire à la place.
J'utiliserais à la
Enum.GetValues(typeof(Suit))
place.la source
Enum.GetValues(typeof(Suits)).OfType<Suits>().ToArray()
. Dans ce cas, je peux parcourir un tableau d'Suits
éléments d'énumération, pas des chaînes.Suits suit in Enum.GetValues(typeof(Suits))
?J'ai fait quelques extensions pour une utilisation facile de l'énumération. Peut-être que quelqu'un peut l'utiliser ...
L'énumération elle-même doit être décorée avec l' attribut FlagsAttribute :
la source
Certaines versions du framework .NET ne prennent pas en charge
Enum.GetValues
. Voici une bonne solution de contournement d' Ideas 2.0: Enum.GetValues dans Compact Framework :Comme pour tout code impliquant une réflexion , vous devez prendre des mesures pour vous assurer qu'il ne s'exécute qu'une seule fois et que les résultats sont mis en cache.
la source
return type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)).Cast<Enum>();
Utilisation
Cast<T>
:Voilà
IEnumerable<Suit>
.la source
from
clause et leforeach
déclarant d'en-tête.Je pense que c'est plus efficace que les autres suggestions car il
GetValues()
n'est pas appelé à chaque fois que vous avez une boucle. Il est également plus concis. Et vous obtenez une erreur de compilation, pas une exception d'exécution si ceSuit
n'est pas unenum
.EnumLoop
a cette définition complètement générique:la source
EnumLoop
un type qui n'est pas une énumération, il se compilera correctement, mais lèvera une exception au moment de l'exécution.Vous n'obtiendrez pas
Enum.GetValues()
dans Silverlight .Article de blog original par Einar Ingebrigtsen :
la source
where T: Enum
Ma solution fonctionne dans .NET Compact Framework (3.5) et prend en charge la vérification de type au moment de la compilation :
T valueType = new T()
, je serais heureux de voir une solution.Un appel ressemblerait à ceci:
la source
T valueType = default(T)
?new()
T
. En outre, vous n'avez pas besoinnew T()
du tout, vous pouvez sélectionner uniquement les champs statiques et le faire.GetValue(null)
. Voir la réponse d'Aubrey.where T: Enum
Je pense que vous pouvez utiliser
la source
la source
Je pense que la mise en cache du tableau l'accélérerait considérablement. Il semble que vous obteniez un nouveau tableau (par réflexion) à chaque fois. Plutôt:
C'est au moins un peu plus rapide, ja?
la source
Trois façons:
Enum.GetValues(type)
// Depuis .NET 1.1, pas dans Silverlight ou .NET Compact Frameworktype.GetEnumValues()
// Uniquement sur .NET 4 et supérieurtype.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null))
// Fonctionne partoutJe ne sais pas pourquoi a
GetEnumValues
été introduit sur les instances de type. Ce n'est pas du tout très lisible pour moi.Avoir une classe d'aide comme
Enum<T>
c'est ce qui est le plus lisible et mémorable pour moi:Vous appelez maintenant:
On peut également utiliser une sorte de mise en cache si les performances sont importantes, mais je ne m'attends pas à ce que ce soit un problème du tout.
la source
En combinant les meilleures réponses, j'ai créé une extension très simple:
C'est propre, simple et, par le commentaire de @ Jeppe-Stig-Nielsen, rapide.
la source
where T: Enum
Il existe deux façons d'itérer un
Enum
:Le premier vous donnera des valeurs sous forme sur un tableau de **
object
** s, et le second vous donnera des valeurs sous forme d'un tableau de **String
** s.Utilisez-le en
foreach
boucle comme ci-dessous:la source
J'utilise ToString (), puis je scinde et analyse le tableau Spit dans des drapeaux.
la source
Je ne pense pas que ce soit mieux, ni même bon. Je ne fais qu'énoncer une autre solution.
Si les valeurs enum vont strictement de 0 à n - 1, une alternative générique est:
Si les valeurs d'énumération sont contiguës et que vous pouvez fournir le premier et le dernier élément de l'énumération, alors:
Mais ce n'est pas une énumération stricte, juste une boucle. La deuxième méthode est cependant beaucoup plus rapide que toute autre approche ...
la source
Si vous avez besoin d'une vérification de la vitesse et du type lors de la génération et de l'exécution, cette méthode d'assistance est meilleure que l'utilisation de LINQ pour convertir chaque élément:
Et vous pouvez l'utiliser comme ci-dessous:
Bien sûr, vous pouvez revenir
IEnumerable<T>
, mais cela ne vous achète rien ici.la source
where T: Enum
Voici un exemple pratique de création d'options de sélection pour un DDL :
la source
(La réponse actuellement acceptée a un casting que je ne pense pas nécessaire (bien que je puisse me tromper).)
la source
Cette question apparaît dans le chapitre 10 de « C # étape par étape 2013 »
L'auteur utilise une double boucle for pour parcourir une paire d'énumérateurs (pour créer un jeu complet de cartes):
Dans ce cas,
Suit
etValue
sont les deux énumérations:et
PlayingCard
est un objet de carte avec un définiSuit
etValue
:la source
Je sais que c'est un peu compliqué, mais si vous êtes fan de one-liners, en voici un:
la source
Et si vous savez que le type sera un
enum
, mais vous ne savez pas quel est le type exact au moment de la compilation?La méthode
getListOfEnum
utilise la réflexion pour prendre n'importe quel type d'énumération et renvoie uneIEnumerable
de toutes les valeurs d'énumération.Usage:
la source
Un moyen simple et générique de convertir une énumération en quelque chose que vous pouvez interagir:
Et alors:
la source
Dictionary
n'est pas une bonne idée: si vous avez unEnum
commeenum E { A = 0, B = 0 }
, la valeur 0 est ajoutée 2 fois générant unArgumentException
(vous ne pouvez pas ajouter la mêmeKey
sur uneDictionary
2 fois ou plus!).Dictionary<,>
depuis une méthode nomméeToList
? Et pourquoi ne pas revenirDictionary<T, string>
?Ajoutez une méthode
public static IEnumerable<T> GetValues<T>()
à votre classe, comme:Appelez et passez votre énumération. Vous pouvez maintenant le parcourir en utilisant
foreach
:la source
enum
les types sont appelés "types d'énumération" non pas parce qu'ils sont des conteneurs qui "énumèrent" les valeurs (ce qu'ils ne sont pas), mais parce qu'ils sont définis en énumérant les valeurs possibles pour une variable de ce type.(En fait, c'est un peu plus compliqué que cela - les types enum sont considérés comme ayant un type entier "sous-jacent", ce qui signifie que chaque valeur enum correspond à une valeur entière (ceci est généralement implicite, mais peut être spécifié manuellement). C # a été conçu de manière à pouvoir bourrer n'importe quel entier de ce type dans la variable enum, même s'il ne s'agit pas d'une valeur "nommée".)
La méthode System.Enum.GetNames peut être utilisée pour récupérer un tableau de chaînes qui sont les noms des valeurs d'énumération, comme son nom l'indique.
EDIT: aurait dû suggérer la méthode System.Enum.GetValues à la place. Oops.
la source
GetNames
méthode renvoie, en effet, un tableau de chaînes, mais l'OP nécessite un énumérateur à travers les valeurs.J'ai essayé de nombreuses façons et obtenu le résultat de ce code:
Pour obtenir une liste d'int à partir d'une énumération, utilisez ce qui suit. Ça marche!
la source
Vous pouvez également vous lier directement aux membres statiques publics de l'énumération en utilisant la réflexion:
la source
Si tu as:
Cette:
Sortira:
la source
LINQ Generic Way:
Usage:
la source