Représentation sous forme de chaîne d'un Enum
J'ai l'énumération suivante:
public enum AuthenticationMethod
{
FORMS = 1,
WINDOWSAUTHENTICATION = 2,
SINGLESIGNON = 3
}
Le problème, toutefois, est que j'ai besoin du mot "FORMES" quand je demande pour AuthenticationMethod.FORMES et pas l'id 1.
J'ai trouvé la solution suivante pour résoudre ce problème (lien):
D'abord, je dois 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; }
}
}
Alors je peux ajouter cet attribut à mon agent recenseur:
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 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 que j'ai les outils pour obtenir une valeur de chaîne pour un agent recenseur.
Je peux alors l'utiliser comme ceci:
string valueOfAuthenticationMethod = StringEnum.GetStringValue(AuthenticationMethod.FORMS);
Bon, maintenant, tous ces travaux comme un charme, mais je trouve qu'il a beaucoup de travail. Je me demandais si il ya une meilleure solution.
J'ai aussi essayé quelque chose avec un dictionnaire et des propriétés statiques mais ce n'était pas mieux non plus.
- Nice! Je peux l'utiliser pour traduire les valeurs de l'enum de chaînes localisées.
- Tandis que vous pouvez trouver cette longue haleine, c'est en fait une assez souple de chemin à faire pour d'autres choses. Comme un de mes collègues l'ont souligné, cela pourrait être utilisé dans de nombreux cas, de remplacer Enum Aides que la carte de base de données les codes pour les valeurs de l'enum etc...
- C'est une "Énumération", pas un "agent Recenseur".
- MSDN reccoments suffixe classes d'attributs avec "Attribut" suffixe. Donc "classe StringValueAttribute" 😉
- Je suis d'accord avec @BenAlabaster c'est tout à fait flexible. Aussi, vous pouvez faire ce une méthode d'extension en ajoutant simplement des
this
en face de laEnum
dans votre méthode statique. Ensuite, vous pouvez faireAuthenticationMethod.Forms.GetStringValue();
- Cette approche utilise la réflexion pour lire les valeurs d'attribut et il est très lent si vous devez appeler GetStringValue() plusieurs fois dans mon expérience. Le type-safe-enum modèle est plus rapide.
- Si vous allez vers le bas de l'attribut de la route, plutôt que de rouler votre propre, vous pouvez utiliser
System.ComponentModel.DescriptionAttribute
. - Pourquoi allez-vous à travers tous les ennuis lorsque vous pouvez simplement appeler
.ToString()
sur l'enum pour obtenir la chaîne de caractères "FORMES"?
Vous devez vous connecter pour publier un commentaire.
Essayer type-safe-enum modèle.
Mise à jour
Explicite (ou implicite) type de conversion peut être fait par
l'ajout d'un champ statique avec la cartographie
de remplissage de cette cartographie en instance constructeur
et l'ajout de utilisateur-type défini par l'opérateur de conversion
private static readonly Dictionary<string, AuthenticationMethod> instance
variable? Et de donner des précisions sur la structure. Je ne suis pas sûr si vous pouvez le faire cet ingénieux...ISerializable
, votre classe doit inclure une spéciale constructeur, qui serait briser le scellé/singleton nature du code. Je suis aussi en train d'essayer d'utiliser cetteTypeSafeEnum
sur une propriété UserControl - comme ce<uc:MyUC AuthMethod="FORMS" />
- j'ai donc dû mettre en œuvre unTypeConverter
et qui semble être à l'origine d'une foule d'autres problèmes, l'un d'eux étant que le constructeur statique ne pas avoir couru avant le TypeConverter tentatives de faire des conversions. (Solution: il suffit de stocker l'accessoire comme une chaîne de caractères et de voter lorsque requis)switch
est cependant pas de problème, comme vous pouvez le mettre en œuvre ce genre de choses dans le type-safe-enum class pour en faire la promotion à une smart enum.Enum.GetValues()
? La seule chose que je peux penser à est de la réflexion dans un statiqueEnumerate()
fonction.Utiliser la méthode
comme dans (à Supposer
Shipper
est défini Enum)Il y a un tas d'autres méthodes statiques de la classe Enum utile de l'examiner de trop...
Shipper.FederalExpress.ToString()
. J'ai essayé en C# 4.0 et le résultat est le même que le protocole Enum.GetNameShipper.FederalExpress.ToString()
, il suffit de mettre"FederalExpress"
?x.toString()
travail? Je n'ai pas essayer car il est plus que temps depuis que j'ai écrit la dernière ligne de C#. si cela ne fonctionne pas, puis-je obtenir votre point de vue.ToString()
sur une variable retourne le nom du type. C'est une des raisons pourquoi vous remplacerToString()
sur d'autres déclaré types comme une question d'habitude, pour s'assurer que le débogueur affiche quelque chose d'utile (au lieu de simplement le nom du type) lorsque l'on regarde le contenu des collections et ces.Vous pouvez référencer le nom, plutôt que de la valeur en utilisant les méthodes ToString()
La documentation est ici:
http://msdn.microsoft.com/en-us/library/16c1xs4z.aspx
...et si vous avez le nom de votre enums Pascal Cas (comme je le fais - comme ThisIsMyEnumValue = 1, etc.) ensuite, vous pouvez utiliser un très simple regex pour imprimer la forme conviviale:
qui peut facilement être appelé à partir de n'importe quelle chaîne:
Sorties:
Qui sauve courir tout le chemin autour de la maisons de créer des attributs personnalisés et de les attacher à vos énumérations ou en utilisant des tables d'épouser une valeur d'enum avec une chaîne conviviale et le meilleur de tous c'est l'auto gestion et peut être utilisé sur n'importe Pascal Cas de la chaîne qui est infiniment plus réutilisable. Bien sûr, elle ne vous permet pas d'avoir une différents nom convivial que votre enum qui votre solution n'fournir.
J'aime votre solution originale, bien que pour des scénarios plus complexes si. Vous pouvez prendre votre solution d'un cran, et faire de votre GetStringValue une méthode d'extension de votre enum et puis vous n'auriez pas besoin de faire référence à elle comme StringEnum.GetStringValue...
Vous pouvez ensuite accéder facilement directement à partir de votre enum exemple:
"(?!^)([^A-Z])([A-Z])", "$1 $2"
. DoncHereIsATEST
devientHere Is ATEST
.Malheureusement réflexion pour obtenir des attributs sur les enums est assez lente:
Voir cette question: Quelqu'un connait un moyen rapide pour obtenir des attributs personnalisés sur une valeur d'enum?
La
.ToString()
est assez lent sur les énumérations trop.Vous pouvez écrire les méthodes d'extension pour les enums si:
Ce n'est pas grand, mais être rapide et ne nécessitent pas de réflexion pour les attributs nom du champ ou.
C#6 Mise À Jour
Si vous pouvez utiliser C#6, puis le nouveau
nameof
opérateur travaille pour les énumérations, de sortenameof(MyEnum.WINDOWSAUTHENTICATION)
seront convertis en"WINDOWSAUTHENTICATION"
à moment de la compilation, faisant d'elle le moyen le plus rapide pour obtenir enum noms.Noter que cela permettra de convertir de l'explicite enum pour un inline constante, de sorte qu'il ne fonctionne pas pour les énumérations que vous avez dans une variable. Donc:
Mais...
nameof()
ne fonctionne que si vous savez l'enum instance à l'avance. c'est à dire dansvar enumVal = MyEnum.Value;
la valeur retournée parnameof(enumVal)
sera "enumVal", pas de "Valeur". C'est une fonctionnalité de compilateur, pas d'exécution.nameof(MyEnum.Value)
deviendra"Value"
au moment de la compilation, il n'y a pas d'instance deMyEnum
.StringEnum.GetStringValue(AuthenticationMethod.FORMS)
- dans ce contextenameof(AuthenticationMethod.FORMS)
est plus rapide. J'ai été assez explicite dans la réponse que ce qui était strictement un moment de la compilation, de l'optimisation, mais je vais ajouter des précisions.- Je utiliser une méthode d'extension:
Maintenant décorer le
enum
avec:Lorsque vous appelez
AuthenticationMethod.FORMS.ToDescription()
vous obtiendrez"FORMS"
.using System.ComponentModel;
Aussi, cette méthode ne fonctionne que si vous voulez la Chaîne de valeur pour être le même que l'énumération du nom. L'OP voulait une valeur différente.AuthenticationMethod.FORMS.ToDescription()
?Suffit d'utiliser la
ToString()
méthodeDe référence de la chaîne
Tomato
, il suffit d'utiliser.ToString()
valeur différente de la conviviale de la valeur dont vous avez besoin.any fruit = any.Tomato;
string tomato = fruit.ToString();
- Je utiliser l'attribut de Description du Système.ComponentModel espace de noms. Tout simplement décorer l'enum et ensuite utiliser ce code pour récupérer:
Comme un exemple:
Ce code bien approvisionne pour les énumérations où vous n'avez pas besoin d'un "nom Convivial" et sera de retour juste le .ToString() de l'enum.
Solution très simple à ce avec des .Net 4.0 et ci-dessus. Aucun autre code n'est nécessaire.
Pour obtenir la chaîne de caractères sur la juste utilisation:
ou
La valeur sera "Actif" ou "Archivé".
Pour voir les différents formats de chaîne (le "f" à partir de ci-dessus) lors de l'appel de
Enum.ToString
voir ce L'Énumération Des Chaînes De Format pageJ'aime vraiment Jakub Šturc réponse, mais c'est l'inconvénient est que vous ne pouvez pas l'utiliser avec un interrupteur de cas. Voici une version légèrement modifiée de sa réponse qui peut être utilisé avec une instruction switch:
De sorte que vous obtenez tous les avantages de Jakub Šturc réponse, en plus on peut l'utiliser avec une instruction switch comme suit:
public static int nextAvailable { get; private set; }
puis dans le constructeurthis.Value = nextAvailable++;
=
opérateur pour permettre à interrupteur pour travaux? Je l'ai fait en VB et vous pouvez maintenant l'utiliser dansselect case
déclaration.- Je utiliser une combinaison de plusieurs des suggestions ci-dessus, combiné avec la mise en cache. Maintenant, j'ai eu l'idée de code que j'ai trouvé quelque part sur le net, mais je ne puis me rappeler où je l'ai eu ou le trouver. Donc si jamais quelqu'un trouve quelque chose qui lui ressemble, s'il vous plaît commentaire de l'attribution.
De toute façon, l'utilisation implique le type de convertisseurs, donc si vous êtes à la liaison à l'INTERFACE utilisateur il fonctionne. Vous pouvez étendre avec Jakub du modèle rapide de recherche de code par l'initialisation du convertisseur de type dans les méthodes statiques.
L'utilisation de base devrait ressembler à ceci
Le code de la coutume enum type de convertisseur suit:
}
Dans votre question, vous n'avez jamais dit que vous avez réellement besoin de la valeur numérique de l'enum n'importe où.
Si vous n'avez pas seulement besoin d'un enum de type chaîne de caractères (ce qui n'est pas un type intégral ne peut donc pas être une base de enum) en voici une:
vous pouvez utiliser la même syntaxe que les enum de référence
Il sera un peu plus lent qu'avec des valeurs numériques (de la comparaison de chaînes au lieu de chiffres), mais sur le côté positif, il n'est pas en utilisant la réflexion (lent) pour accéder à la chaîne.
Comment j'ai résolu ce problème comme une extension de la méthode:
Enum:
D'utilisation (où o.OrderType est une propriété du même nom que l'enum):
Qui me donne une chaîne de "Nouvelle Carte" ou "Recharger" à la place de la valeur d'enum NewCard et Recharge.
Mise à jour: Visitant cette page, 8 ans plus tard, après de ne pas toucher à C# pour un long moment, comme dirait ma réponse est non plus la meilleure solution. J'aime vraiment le convertisseur solution à égalité avec les attributs des fonctions.
Si vous lisez ceci, assurez-vous également de vérifier d'autres réponses.
(indice: ils sont au-dessus de celui-ci)
Comme la plupart d'entre vous, j'ai vraiment aimé l'sélectionnés réponse par Jakub Šturc, mais j'ai vraiment hate de copier-coller le code, et essayer de le faire aussi peu que je peux.
J'ai donc décidé que je voulais un EnumBase classe à partir de laquelle la plupart des fonctionnalités est héritée/intégrés, en laissant de me concentrer sur le contenu plutôt que de comportement.
Le principal problème avec cette approche est basée sur le fait que, bien que les valeurs de l'Enum sont de type-safe cas, l'interaction est à la Statique de la mise en œuvre d'Enum type de Classe.
Donc, avec un peu d'aide de médicaments génériques de la magie, je pense que j'ai enfin eu le bon mélange.
J'espère que quelqu'un le trouve aussi utile que j'ai fait.
Je vais commencer par Jakub l'exemple, mais l'utilisation de l'héritage et les génériques:
Et ici, c'est la classe de base:
Je suis d'accord avec Keith, mais je ne peux pas voter (encore).
- Je utiliser une méthode statique et swith déclaration à retourner exactement ce que je veux. Dans la base de données j'magasin de type tinyint et mon code n'utilise la réelle enum, afin que les chaînes sont pour l'INTERFACE utilisateur exigences. Après de nombreux tests, cela a entraîné la meilleure performance et plus de contrôle sur la sortie.
Toutefois, selon certains témoignages, ce qui conduit à un possible entretien cauchemar et du code de l'odorat. J'essaie de garder un oeil pour les énumérations, qui sont longues et beaucoup d'énumérations, ou ceux qui changent fréquemment. Sinon, cela a été une excellente solution pour moi.
Si vous êtes venu ici à la recherche de mettre en œuvre un simple "Enum", mais dont les valeurs sont des chaînes de caractères au lieu d'entiers, voici la solution la plus simple:
Mise en œuvre:
static readonly
.Quand je suis confronté à ce problème, il ya un couple de questions que j'essaie de trouver les réponses à la première:
La façon la plus simple de le faire est avec
Enum.GetValue
(et de soutien en aller-retour à l'aide deEnum.Parse
). Il est aussi souvent utile de développer unTypeConverter
, comme Steve Mitcham suggère, à l'appui de l'INTERFACE utilisateur de liaison. (Il n'est pas nécessaire de construire unTypeConverter
lorsque vous êtes à l'aide de feuilles de propriété, qui est une des belles choses au sujet de feuilles de propriétés. Si dieu sait qu'ils ont leurs propres problèmes.)En général, si les réponses aux questions ci-dessus suggèrent que ne va pas au travail, ma prochaine étape est de créer et de remplir un statique
Dictionary<MyEnum, string>
, ou peut-être unDictionary<Type, Dictionary<int, string>>
. J'ai tendance à sauter les intermédiaires décorez-le-code-avec-les attributs de l'étape parce que l'on se distribuent suivant est le besoin de changer l'amicale des valeurs après le déploiement (souvent, mais pas toujours, en raison de la localisation).Je voulais poster ce qu'un commentaire pour le post cité ci-dessous, mais ne pouvait pas parce que je n'ai pas assez rep - donc merci de ne pas voter. Le code contient une erreur et je voulais le montrer à des individus tentent d'utiliser cette solution:
devrait être
Brillant!
Ma variante
Code ressemble un peu moche, mais les usages de cette structure sont assez presentative.
Aussi, je pense que, si beaucoup de ces énumérations nécessaire, la génération de code (par exemple, T4) peuvent être utilisées.
Option 1:
et puis
Option 2:
Si vous pensez à ce sujet le problème que nous essayons de résoudre, ce n'est pas un enum qui nous est nécessaire à tous. Nous avons besoin d'un objet qui permet à un certain nombre de valeurs à associer avec d'autres personnes; en d'autres termes, de définir une classe.
Jakub Šturc est de type sécurisé enum modèle est la meilleure option que je vois ici.
Regarder:
pour moi, l'approche pragmatique est de classe à l'intérieur de la classe, de l'échantillon:
Ici est encore une autre façon d'accomplir la tâche d'associer des chaînes de caractères avec les énumérations:
Cette méthode est appelée comme ceci:
Vous pouvez grouper les énumérations dans leur propre structure. Depuis cette méthode utilise le type enum, vous pouvez utiliser Intellisense pour afficher la liste des enums lors de la prise de la
GetString()
appel.Vous pouvez éventuellement utiliser le nouvel opérateur sur le
DATABASE
struct. Ne pas l'utiliser signifie que les chaînesList
n'est pas alloué jusqu'à ce que la premièreGetString()
l'appel est fait.Beaucoup de réponses ici, mais dans mon cas, ne résout pas ce que je voulais sortir d'une "chaîne " enum", qui a été:
1,2 & 4 peut effectivement être résolu avec un C# Typedef d'une chaîne de caractères (depuis les chaînes sont commutables en c#)
3 peut être résolu par static const cordes. Donc, si vous avez les mêmes besoins, c'est l'approche la plus simple:
Cela permet par exemple:
et
Où CreateType peut être appelée avec une chaîne ou d'un type. Toutefois l'inconvénient est que n'importe quelle chaîne est automatiquement valide enum, cela pourrait être modifiés, mais alors, il faudrait sorte de fonction init...ou peut-être en faire ils cast explicite interne?
Maintenant, si un int valeur a été important pour vous (peut-être pour la comparaison de la vitesse), vous pourrait utiliser quelques idées de Jakub Šturc fantastique répondre et de faire quelque chose d'un peu fou, c'est mon coup de poignard à elle:
mais bien sûr, "Types de bob = 4;" n'aurait aucun sens, à moins d'avoir initialisé en premier qui serait sorte de vaincre le point...
Mais en théorie TypeA == TypeB serait plus rapide...
Si je comprends correctement, vous pouvez simplement utiliser .ToString() pour récupérer le nom de l'enum de la valeur (en Supposant que c'est déjà présentée comme la Enum);
Si vous avez eu le nu int (disons à partir d'une base de données ou quelque chose), vous pouvez le jeter à l'enum.
Les deux méthodes ci-dessous, vous aurez l'enum nom.
Gardez à l'esprit, la seconde technique suppose que vous utilisez ints et votre index est basé sur 1 (et non 0). La fonction getnames a également est assez lourd en comparaison, la production de l'ensemble à chaque fois qu'il appelle.
Comme vous pouvez le voir dans la première technique, .ToString() est appelée implicitement.
Ces deux sont déjà mentionnés dans les réponses, bien sûr, je suis juste essayer de clarifier les différences entre eux.
vieux post, mais...
La réponse à cette peut-être en fait très simple. Utilisation Enum.ToString() fonction
Il y a 6 surcharges de cette fonction, vous pouvez utiliser le protocole Enum.Tostring("F") ou Enum.ToString() pour renvoyer la valeur de la chaîne. Pas besoin de s'embêter avec quoi que ce soit d'autre. Voici une travail de Démonstration
Noter que cette solution peut ne pas fonctionner pour tous les compilateurs (cette démo ne fonctionne pas comme prévu) mais au moins il travaille pour le dernier compilateur.
basé sur la MSDN: http://msdn.microsoft.com/en-us/library/cc138362.aspx
str sera le noms des champs
Bien, après lecture de l'ensemble de la ci-dessus j'ai l'impression que les gars ont plus compliqué la question de la transformation des agents recenseurs dans les chaînes.
J'ai aimé l'idée d'avoir des attributs sur énuméré les domaines, mais je pense que les attributs sont principalement utilisés pour les Méta-données, mais dans votre cas je pense que tous vous avez besoin est une sorte de localisation.
Maintenant, si on essaie d'appeler la méthode ci-dessus, nous pouvons l'appeler de cette façon
Tout ce que vous devez faire est de simplement créer un fichier de ressources contenant tous les énumérateur valeurs et les chaînes correspondantes
Ce qui est vraiment très agréable, c'est que ce sera très utile si vous avez besoin de votre demande à être localisé, puisque tout ce que vous devez faire est de simplement créer un autre fichier de ressources avec une nouvelle langue! et Voe-la!
Quand je suis dans une situation comme celle que je vous propose la solution ci-dessous.
Et comme une classe de consommateurs qui vous pourriez avoir
Et à l'aide d'un dictionnaire bidirectionnel:
Sur cette base (https://stackoverflow.com/a/255638/986160) en supposant que les clés seront associés avec des valeurs uniques dans le dictionnaire et similaire à (https://stackoverflow.com/a/255630/986160) mais un peu plus élégante. Ce dictionnaire est également énumérable et vous pouvez faire l'aller-retour ints à cordes. Aussi, vous n'avez pas à avoir une chaîne dans votre base de code, à l'exception de cette classe.
Utilisation objet d'Enum.Parse(System.Type enumType, chaîne de valeur, bool ignoreCase); l'ai eu à partir http://blogs.msdn.com/b/tims/archive/2004/04/02/106310.aspx
Ma réponse, en travaillant sur @user29964 's réponse (qui est de loin le plus simple et le plus proche d'un Enum) est
utilisation
Exemple
ce sera de retour
"vi,grade"
L'approche que j'ai trouvé pour l'internationalisation des Énumérations ou de l'obtention de texte d'Énumérations par les différents fichiers de Ressources est de créer un attribut de la classe en héritant DescriptionAttribute classe
Créer une autre classe Statique qui fournira les méthodes d'extension pour GetString et GetStrings.
Et sur les éléments de votre Enum vous pouvez écrire :
Où Les Ressources.ResourceNames.AdviceCreateAdviceExternaPrioritymemberhigh &
Les ressources.ResourceNames.AdviceCreateAdviceExternaPrioritymemberroutine sont des constantes dans le fichier de ressources ou vous pouvez dire les chaînes de caractères dont les valeurs peuvent être disponibles dans différentes cultures.
Si vous êtes à la mise en œuvre de votre application web dans l'architecture MVC puis créer une propriété
et dans votre .cshtml fichier, vous pouvez simplement lier enum pour votre dropdownlist comme :
Merci
Ratnesh
Je suis avec Harvey, mais n'utilisez pas de const. Je suis capable de mélanger et assortir string, int, que ce soit.
Puis plus tard ...
const
modificateur d'accès parce que c'est un moment de la compilation, de la valeur et je peux donc les utiliser dansswitch
consolidés. À l'aide de votre code peut fonctionner pour certaines situations, mais vous ne pouvez pas utiliser vos valeurs dans unswitch
.Je sais très bien que cette question a déjà été répondu et que l'OP est déjà heureux avec la accepté de répondre. Mais j'ai trouvé le plus de réponses, y compris les acceptée, pour être un peu plus compliqué.
J'ai un projet qui m'a donné ce genre de situation et j'ai pu le réaliser de cette façon.
Tout d'abord, vous devez tenir compte de la coque arrière de votre enum noms:
Puis, cette extension:
Grâce à cela, vous pouvez transformer votre chaque enum nom de sa représentation sous forme de chaîne avec chaque mot séparé par un espace. Ex:
SingleSignOn
pour devenirSSO
. Votre solution ne fonctionne pas.sorties sont:
"FORMES"
"WINDOWSAUTHENTICATION"
"SINGLESIGNON"