J'ai l'énumération suivante:
public enum AuthenticationMethod
{
FORMS = 1,
WINDOWSAUTHENTICATION = 2,
SINGLESIGNON = 3
}
Le problème est cependant que j'ai besoin du mot "FORMULAIRES" lorsque je demande AuthenticationMethod.FORMS et non l'ID 1.
J'ai trouvé la solution suivante à ce problème ( lien ):
Je dois d'abord créer un attribut personnalisé appelé "StringValue":
public class StringValue : System.Attribute
{
private readonly string _value;
public StringValue(string value)
{
_value = value;
}
public string Value
{
get { return _value; }
}
}
Ensuite, je peux ajouter cet attribut à mon énumérateur:
public enum AuthenticationMethod
{
[StringValue("FORMS")]
FORMS = 1,
[StringValue("WINDOWS")]
WINDOWSAUTHENTICATION = 2,
[StringValue("SSO")]
SINGLESIGNON = 3
}
Et bien sûr, j'ai besoin de quelque chose pour récupérer cette StringValue:
public static class StringEnum
{
public static string GetStringValue(Enum value)
{
string output = null;
Type type = value.GetType();
//Check first in our cached results...
//Look for our 'StringValueAttribute'
//in the field's custom attributes
FieldInfo fi = type.GetField(value.ToString());
StringValue[] attrs =
fi.GetCustomAttributes(typeof(StringValue),
false) as StringValue[];
if (attrs.Length > 0)
{
output = attrs[0].Value;
}
return output;
}
}
Bon maintenant j'ai les outils pour obtenir une valeur de chaîne pour un énumérateur. Je peux ensuite l'utiliser comme ceci:
string valueOfAuthenticationMethod = StringEnum.GetStringValue(AuthenticationMethod.FORMS);
Bon maintenant, tout cela fonctionne comme un charme, mais je trouve que c'est beaucoup de travail. Je me demandais s'il y avait une meilleure solution pour cela.
J'ai également essayé quelque chose avec un dictionnaire et des propriétés statiques, mais ce n'était pas mieux non plus.
this
devant laEnum
dans votre méthode statique. Ensuite, vous pouvez le faireAuthenticationMethod.Forms.GetStringValue();
Réponses:
Essayez un modèle d' énumération de type sécurisé .
La conversion de type mise à jour explicite (ou implicite) peut être effectuée par
ajout d'un champ statique avec mappage
remplir ce mappage dans le constructeur d'instance
et ajout d' un opérateur de conversion de type défini par l'utilisateur
la source
Utiliser la méthode
comme dans (Supposer
Shipper
est un Enum défini)Il existe un tas d'autres méthodes statiques sur la classe Enum qui méritent également d'être étudiées ...
la source
Vous pouvez référencer le nom plutôt que la valeur en utilisant ToString ()
La documentation est ici:
http://msdn.microsoft.com/en-us/library/16c1xs4z.aspx
... et si vous nommez vos énumérations en cas Pascal (comme je le fais - comme ThisIsMyEnumValue = 1 etc.), vous pouvez utiliser une expression régulière très simple pour imprimer le formulaire convivial:
qui peut facilement être appelé à partir de n'importe quelle chaîne:
Les sorties:
Cela évite de courir tout autour des maisons en créant des attributs personnalisés et en les attachant à vos énumérations ou en utilisant des tables de recherche pour épouser une valeur d'énumération avec une chaîne conviviale et, mieux encore, elle est autogérée et peut être utilisée sur n'importe quelle chaîne de cas Pascal infiniment infinie plus réutilisable. Bien sûr, cela ne vous permet pas d'avoir un nom convivial différent de votre énumération que votre solution fournit.
J'aime bien votre solution d'origine pour les scénarios plus complexes. Vous pourriez pousser votre solution un peu plus loin et faire de votre GetStringValue une méthode d'extension de votre énumération, puis vous n'auriez pas besoin de la référencer comme StringEnum.GetStringValue ...
Vous pouvez ensuite y accéder facilement directement depuis votre instance d'énumération:
la source
"(?!^)([^A-Z])([A-Z])", "$1 $2"
. AinsiHereIsATEST
devientHere Is ATEST
.Malheureusement, la réflexion pour obtenir des attributs sur les énumérations est assez lente:
Voir cette question: Quelqu'un connaît-il un moyen rapide d'accéder à des attributs personnalisés sur une valeur d'énumération?
Le
.ToString()
est également assez lent sur les énumérations.Vous pouvez cependant écrire des méthodes d'extension pour les énumérations:
Ce n'est pas génial, mais sera rapide et ne nécessitera pas de réflexion pour les attributs ou le nom du champ.
Mise à jour C # 6
Si vous pouvez utiliser C # 6, le nouvel
nameof
opérateur fonctionne pour les énumérations, ilnameof(MyEnum.WINDOWSAUTHENTICATION)
sera donc converti en"WINDOWSAUTHENTICATION"
au moment de la compilation , ce qui en fait le moyen le plus rapide pour obtenir les noms d'énumérations.Notez que cela convertira l'énumération explicite en une constante intégrée, donc cela ne fonctionne pas pour les énumérations que vous avez dans une variable. Donc:
Mais...
la source
J'utilise une méthode d'extension:
Décorez maintenant le
enum
avec:Quand vous appelez
AuthenticationMethod.FORMS.ToDescription()
vous obtiendrez"FORMS"
.la source
using System.ComponentModel;
également, cette méthode ne fonctionne que si vous souhaitez que la valeur de chaîne soit la même que le nom de l'énumération. OP voulait une valeur différente.AuthenticationMethod.FORMS.ToDescription()
?Utilisez simplement la
ToString()
méthodePour référencer la chaîne
Tomato
, utilisez simplementla source
.ToString()
valeur différente de la valeur conviviale dont vous avez besoin.any fruit = any.Tomato;
string tomato = fruit.ToString();
Solution très simple à cela avec .Net 4.0 et supérieur. Aucun autre code n'est nécessaire.
Pour obtenir la chaîne, utilisez simplement:
ou
La valeur sera "Actif" ou "Archivé".
Pour voir les différents formats de chaîne (le "f" ci-dessus) lors de l'appel,
Enum.ToString
consultez cette page Chaînes de format d'énumérationla source
J'utilise l'attribut Description de l'espace de noms System.ComponentModel. Décorez simplement l'énumération, puis utilisez ce code pour le récupérer:
Par exemple:
Ce code répond parfaitement aux énumérations où vous n'avez pas besoin d'un "nom convivial" et renverra uniquement le .ToString () de l'énumération.
la source
J'aime vraiment la réponse de Jakub Šturc, mais son inconvénient est que vous ne pouvez pas l'utiliser avec une instruction switch-case. Voici une version légèrement modifiée de sa réponse qui peut être utilisée avec une instruction switch:
Ainsi, vous bénéficiez de tous les avantages de la réponse de Jakub Šturc, et nous pouvons l'utiliser avec une instruction switch comme ceci:
la source
public static int nextAvailable { get; private set; }
alors dans le constructeurthis.Value = nextAvailable++;
=
opérateur pour permettre au commutateur de fonctionner? Je l'ai fait en VB et je peux maintenant l'utiliser dans uneselect case
déclaration.J'utilise une combinaison de plusieurs des suggestions ci-dessus, combinée avec une mise en cache. Maintenant, j'ai eu l'idée d'un code que j'ai trouvé quelque part sur le net, mais je ne me souviens pas où je l'ai trouvé ou je l'ai trouvé. Donc, si quelqu'un trouve quelque chose de similaire, veuillez commenter l'attribution.
Quoi qu'il en soit, l'utilisation implique les convertisseurs de type, donc si vous vous connectez à l'interface utilisateur, cela «fonctionne». Vous pouvez étendre le modèle de Jakub pour une recherche de code rapide en initialisant le convertisseur de type dans les méthodes statiques.
L'utilisation de base ressemblerait à ceci
Le code du convertisseur de type d'énumération personnalisé suit:
}
la source
Dans votre question, vous n'avez jamais dit que vous aviez besoin de la valeur numérique de l'énumération n'importe où.
Si vous n'avez pas besoin d'une énumération de type chaîne (qui n'est pas un type intégral et ne peut donc pas être une base d'énumération), voici un moyen:
vous pouvez utiliser la même syntaxe que enum pour le référencer
Ce sera un peu plus lent qu'avec des valeurs numériques (en comparant des chaînes au lieu de nombres) mais du côté positif, il n'utilise pas la réflexion (lente) pour accéder à la chaîne.
la source
Comment j'ai résolu cela comme une méthode d'extension:
Enum:
Utilisation (où o.OrderType est une propriété du même nom que l'énumération):
Ce qui me donne une chaîne de "New Card" ou "Reload" au lieu de la valeur enum réelle NewCard et Refill.
la source
Mise à jour: Visiter cette page, 8 ans plus tard, après ne pas avoir appuyé longtemps sur C #, semble que ma réponse ne soit plus la meilleure solution. J'aime vraiment la solution de convertisseur liée aux fonctions d'attribut.
Si vous lisez ceci, assurez-vous de vérifier également les autres réponses.
(indice: ils sont au-dessus de celui-ci)
Comme la plupart d'entre vous, j'ai bien aimé la réponse choisie par Jakub Šturc , mais je déteste aussi vraiment copier-coller du code et essayer de le faire le moins possible.
J'ai donc décidé que je voulais une classe EnumBase dont la plupart des fonctionnalités sont héritées / intégrées, me laissant me concentrer sur le contenu plutôt que sur le comportement.
Le problème principal de cette approche est basé sur le fait que, bien que les valeurs Enum soient des instances de type sécurisé, l'interaction se fait avec l'implémentation statique du type Enum Class. Donc, avec un peu d'aide de la magie des génériques, je pense que j'ai finalement obtenu le bon mix. J'espère que quelqu'un trouvera cela aussi utile que moi.
Je vais commencer par l'exemple de Jakub, mais en utilisant l'héritage et les génériques:
Et voici la classe de base:
la source
Je suis d'accord avec Keith, mais je ne peux pas (encore) voter.
J'utilise une méthode statique et une instruction swith pour retourner exactement ce que je veux. Dans la base de données, je stocke tinyint et mon code utilise uniquement l'énumération réelle, donc les chaînes sont pour les exigences de l'interface utilisateur. Après de nombreux tests, cela a donné les meilleures performances et le plus de contrôle sur la sortie.
Cependant, selon certains comptes, cela conduit à un éventuel cauchemar de maintenance et à une odeur de code. J'essaie de garder un œil sur les énumérations qui sont longues et nombreuses, ou celles qui changent fréquemment. Sinon, cela a été une excellente solution pour moi.
la source
Si vous êtes venu ici pour mettre en œuvre un simple "Enum" mais dont les valeurs sont des chaînes au lieu des entiers, voici la solution la plus simple:
La mise en oeuvre:
la source
static readonly
.Lorsque je suis confronté à ce problème, il y a quelques questions auxquelles j'essaie de trouver les réponses en premier:
La façon la plus simple de le faire est d'
Enum.GetValue
utiliser (et de prendre en charge l'aller-retour en utilisantEnum.Parse
). Il est également souvent utile de créer unTypeConverter
, comme le suggère Steve Mitcham, pour prendre en charge la liaison d'interface utilisateur. (Il n'est pas nécessaire d'en créer unTypeConverter
lorsque vous utilisez des feuilles de propriétés, ce qui est une bonne chose à propos des feuilles de propriétés. Bien que Lord sache qu'ils ont leurs propres problèmes.)En général, si les réponses aux questions ci-dessus suggèrent que cela ne fonctionnera pas, ma prochaine étape consiste à créer et à remplir un statique
Dictionary<MyEnum, string>
, ou éventuellement unDictionary<Type, Dictionary<int, string>>
. J'ai tendance à ignorer l'étape intermédiaire de décorer le code avec des attributs, car ce qui arrive généralement le lendemain, c'est la nécessité de modifier les valeurs conviviales après le déploiement (souvent, mais pas toujours, en raison de la localisation).la source
Je voulais poster ceci en tant que commentaire à l'article cité ci-dessous, mais je ne pouvais pas parce que je n'ai pas assez de représentants - alors s'il vous plaît, ne votez pas. Le code contenait une erreur et je tenais à le signaler aux personnes essayant d'utiliser cette solution:
devrait être
Brillant!
la source
Ma variante
Le code a l'air un peu moche, mais les utilisations de cette structure sont assez représentatives.
De plus, je pense que si un grand nombre de ces énumérations sont requises, la génération de code (par exemple T4) pourrait être utilisée.
la source
Option 1:
et alors
Option 2:
la source
Si vous pensez au problème que nous essayons de résoudre, ce n'est pas du tout une énumération dont nous avons besoin. Nous avons besoin d'un objet qui permette d'associer un certain nombre de valeurs; en d'autres termes, pour définir une classe.
Le modèle d'énumération de type sûr de Jakub Šturc est la meilleure option que je vois ici.
Regarde ça:
la source
pour moi, l'approche pragmatique est classe dans classe, échantillon:
la source
J'ai créé une classe de base pour créer des énumérations sous forme de chaînes dans .NET. Il s'agit d'un seul fichier C # que vous pouvez copier et coller dans vos projets, ou installer via le package NuGet nommé StringEnum . GitHub Repo
<completitionlist>
. (Fonctionne à la fois en C # et en VB)Installation:
.Net Standard 1.0
afin qu'il s'exécute sur.Net Core
> = 1.0,.Net Framework
> = 4.5,Mono
> = 4.6, etc.la source
Voici encore une autre façon d'accomplir la tâche d'associer des chaînes à des énumérations:
Cette méthode est appelée comme ceci:
Vous pouvez regrouper les énumérations liées dans leur propre structure. Comme cette méthode utilise le type enum, vous pouvez utiliser Intellisense pour afficher la liste des énumérations lors de l'
GetString()
appel.Vous pouvez éventuellement utiliser le nouvel opérateur sur la
DATABASE
structure. Ne pas l'utiliser signifie que les cordesList
ne sont pas allouées avant le premierGetString()
appel.la source
Beaucoup de bonnes réponses ici, mais dans mon cas, je n'ai pas résolu ce que je voulais d'une "énumération de chaînes", qui était:
1,2 et 4 peuvent en fait être résolus avec un typedef C # d'une chaîne (puisque les chaînes sont commutables en c #)
3 peut être résolu par des chaînes de const statique. Donc, si vous avez les mêmes besoins, voici l'approche la plus simple:
Cela permet par exemple:
et
Où CreateType peut être appelé avec une chaîne ou un type. Cependant l'inconvénient est que toute chaîne est automatiquement une énumération valide , cela pourrait être modifié, mais cela nécessiterait une sorte de fonction init ... ou pourrait-elle les rendre explicitement castées en interne?
Maintenant, si une valeur int était importante pour vous (peut-être pour la vitesse de comparaison), vous pourriez utiliser quelques idées de Jakub Šturc réponse fantastique et faire quelque chose d'un peu fou, c'est mon coup de couteau:
mais bien sûr "Types bob = 4;" n'aurait aucun sens à moins que vous ne les ayez initialisés en premier, ce qui irait à l'encontre du but ...
Mais en théorie, TypeA == TypeB serait plus rapide ...
la source
Si je vous comprends bien, vous pouvez simplement utiliser .ToString () pour récupérer le nom de l'énumération à partir de la valeur (en supposant qu'il est déjà converti en énumération); Si vous aviez l'intégralité nue (disons à partir d'une base de données ou quelque chose), vous pouvez d'abord le convertir en énumération. Les deux méthodes ci-dessous vous obtiendront le nom de l'énumération.
N'oubliez pas cependant que la deuxième technique suppose que vous utilisez des entiers et que votre index est basé sur 1 (et non sur 0). La fonction GetNames est également assez lourde en comparaison, vous générez un tableau entier à chaque appel. Comme vous pouvez le voir dans la première technique, .ToString () est en fait appelé implicitement. Les deux sont déjà mentionnés dans les réponses bien sûr, j'essaie juste de clarifier les différences entre eux.
la source
ancien poste mais ...
La réponse à cela peut en fait être très simple. Utilisation Enum.ToString () fonction
Il y a 6 surcharges de cette fonction, vous pouvez utiliser Enum.Tostring ("F") ou Enum.ToString () pour renvoyer la valeur de chaîne. Pas besoin de s'embêter avec autre chose. Voici une démo fonctionnelle
Notez que cette solution peut ne pas fonctionner pour tous les compilateurs ( cette démo ne fonctionne pas comme prévu ) mais au moins elle fonctionne pour le dernier compilateur.
la source
basé sur le MSDN: http://msdn.microsoft.com/en-us/library/cc138362.aspx
str sera le nom des champs
la source
Eh bien, après avoir lu tout ce qui précède, je pense que les gars ont trop compliqué le problème de la transformation des énumérateurs en chaînes. J'ai aimé l'idée d'avoir des attributs sur des champs énumérés mais je pense que les attributs sont principalement utilisés pour les métadonnées, mais dans votre cas, je pense que tout ce dont vous avez besoin est une sorte de localisation.
Maintenant, si nous essayons d'appeler la méthode ci-dessus, nous pouvons l'appeler de cette façon
Il vous suffit de créer un fichier de ressources contenant toutes les valeurs de l'énumérateur et les chaînes correspondantes
Ce qui est vraiment très bien à ce sujet, c'est qu'il sera très utile si vous avez besoin que votre application soit localisée, car il vous suffit de créer un autre fichier de ressources avec votre nouvelle langue! et Voe-la!
la source
Lorsque je suis dans une telle situation, je propose la solution ci-dessous.
Et en tant que classe consommatrice, vous pourriez avoir
Et en utilisant un dictionnaire bidirectionnel: basé sur cela ( https://stackoverflow.com/a/255638/986160 ) en supposant que les clés seront associées à des valeurs uniques dans le dictionnaire et similaires à ( https://stackoverflow.com/a / 255630/986160 ) mais un peu plus élégant. Ce dictionnaire est également énumérable et vous pouvez aller et venir des entiers aux chaînes. De plus, vous n'avez pas besoin d'avoir de chaîne dans votre base de code à l'exception de cette classe.
la source
Pour les jeux d'énumérations de chaînes plus importants, les exemples répertoriés peuvent devenir fastidieux. Si vous voulez une liste de codes d'état ou une liste d'autres énumérations basées sur des chaînes, un système d'attributs est ennuyeux à utiliser et une classe statique avec des instances d'elle-même est ennuyeuse à configurer. Pour ma propre solution, j'utilise le modèle T4 pour faciliter la création d'énumérations basées sur des chaînes. Le résultat est similaire au fonctionnement de la classe HttpMethod.
Vous pouvez l'utiliser comme ceci:
Vous commencez avec un fichier Enum.tt.
Ensuite, vous ajoutez dans votre fichier StringEnum.ttinclude.
Enfin, vous recompilez votre fichier Enum.tt et la sortie ressemble à ceci:
la source