J'ai écrit C # depuis sept ans et je me demande, pourquoi les énumes doivent-elles être de type intégral? Ne serait-il pas agréable de faire quelque chose comme: est-ce une langue la conception em> choix, ou existe-t-il des incompatibilités fondamentales sur un compilateur, CLR ou IL Niveau ? P> Les autres langues sont-elles enums avec des types de chaîne ou complexe (c.-à-d. objet)? Quelles langues? P> (Je suis au courant des solutions de contournement; ma question est, pourquoi em> sont-ils nécessaires?) P> EDIT: "Solutions de contournement" = attributs ou Classes statiques avec constituques :) p> p>
10 Réponses :
Quels sont les avantages, car je ne peux que voir des inconvénients: p>
tostring code> retournera une chaîne différente au nom de l'énumération. C'est-à-dire errorormessage.notfound.tostring () code> sera "Impossible de trouver" au lieu de "NOTOND". LI>
- Inversement, avec
Enum.parse Code>, que ferait-il? Serait-il toujours accepter le nom de la chaîne de l'énumération comme pour les énumérations entier ou fonctionne-t-il avec la chaîne valeur em>? Li>
- Vous ne seriez pas en mesure d'implémenter
[indicateurs] code> car quel serait errorormessage.notfound | Errorormessage.badrequest code> égal dans votre exemple (je sais que cela n'a pas vraiment de sens dans ce cas particulier, et je suppose que vous pourriez simplement dire que [indicateurs] code> n'est pas autorisé sur la chaîne -Les énumérations dépêchées mais qui ressemblent toujours à un inconvénient pour moi) Li>
- tandis que la comparaison
errrmsg == errorormessageage.notfound code> pourrait être implémentée comme une simple comparaison de référence, errsg == "Impossible de trouver" code> devrait être mis en œuvre en tant que Comparaison des chaînes. LI>
ul>
Je ne peux penser à aucun avantage, d'autant plus que c'est si facile de construire votre propre dictionnaire mappage de valeurs d'énumération sur "personnalisé". p>
En ce qui concerne votre première balle, c'est exactement le point que mon ami!
Mais en couple avec mon deuxième point: si tostring code> renvoie "n'a pas pu trouver" Qu'est-ce que
ENUM.PARSE CODE> DO?
Le but d'un énumé est de donner des valeurs plus significatives aux entiers. Vous cherchez quelque chose d'autre à part un énumé. Enums sont compatibles avec les API Windows and com, et une longue histoire sur d'autres plates-formes en plus. P>
Peut-être que vous seriez satisfait des membres du Conseil public d'une structure ou d'une classe. P>
ou peut-être que vous essayez de limiter certaines valeurs de types spécialisées à certaines valeurs de chaîne seulement? Mais comment il est stocké et comment il est affiché peut être deux choses différentes - pourquoi utiliser plus d'espace que nécessaire pour stocker une valeur? P>
Et si vous voulez avoir quelque chose comme celui-là lisible dans un format persisté, faites simplement une méthode d'utilité ou d'extension pour la cracher. P>
Cette réponse est un peu désordonnée car il y a juste tellement de raisons. La comparaison de deux chaînes de validité est beaucoup plus chère que la comparaison de deux entiers. La comparaison des chaînes littérales à des énormes connues pour une vérification de type statique serait un peu déraisonnable. La localisation serait ... bizarre. La compatibilité avec serait cassée. Enums sous forme de drapeaux serait sans signification / brisé. P>
C'est un énumé. C'est ce que fait enums! Ils font partie intégrante! P>
Vous ne pouvez pas avoir static code> et
const code> des membres de C # parce que const est implicitement statique. Mais peut-être que vous n'avez pas voulu dire le mot clé statique.
Peut-être parce que cela n'aurait peut-être pas de sens:
@Jamesbrownisdead - Quoi? O_o
Ne pas vraiment répondre à votre question, mais présenter des alternatives à String Enums.
Oui, c'est probablement la seule autre option en plus d'attribuer une énumération. Bonne pensée, mais c'est une "alternative" à laquelle je faisais référence.
Utilisez peut-être l'attribut de description de System.ComponentModel et écrivez une fonction d'assistance pour récupérer la chaîne associée à partir d'une valeur ENUM? (J'ai vu cela dans une base de code, je travaille avec et sembla une alternative parfaitement raisonnable)
Oui, les solutions de contournement basées sur des attributs sont ce que je faisais appelé quand j'ai dit "alternatives". Si cette solution de contournement est répandue, cela n'indique pas une carence linguistique?
@James: Non, cela n'indique pas une carence linguistique, cela indique un malentendu fondamental des énumérations. Notez le mot racine numer b> là-bas - le type existe spécifiquement i> dans le but de donner un sens sémantique aux nombres arbitraires.
@Aronner: l'énumération a à voir avec comptant i> et lister i> (jeux de) choses; de numerare b> "à compter", pas de "nombre". Voir le MW Définition ou le Wikipedia article.
@Jamesbrownisdead: Ma faute alors de ne pas lire la question de près. J'ai sauté à une "solution" immédiate au problème au lieu d'essayer d'énumérer (haha) pourquoi les énumérations comme caractéristique linguistique dans le CLR ne le permettent pas. Je suis enclin à être d'accord avec Rob Paulsen's Resold -Ilt n'était pas nécessaire jusqu'à maintenant. Les attributs sont un moyen acceptable d'ajouter une signification supplémentaire à travers des métadonnées aux caractéristiques de la langue existantes sans trop de tracas, à l'exception du code de réflexion inesthétique, il faut écrire. Si et quand les concepteurs de langue décident que c # a besoin de Java - comme Enums, je vais bien avec cela comme c'est le cas.
C'est une décision linguistique - par exemple, Java's Enum code> ne correspond pas directement à un
. Il y a beaucoup de belles tours que l'intensure vous donne - vous pouvez les atteindre les bitwises pour les drapeaux, les iTerez-les (en ajoutant ou soustrayant 1), etc. Mais, il y a aussi des peuples yils - le manque de métadonnées supplémentaires, la coulée de tout Int à une valeur non valide, etc. int code>, mais est plutôt une classe réelle
Je pense que la décision a probablement été faite, comme dans la plupart des décisions de conception, car int Enums sont "assez bonnes". Si vous avez besoin de quelque chose de plus complexe, une classe est suffisamment bon marché et facile à construire. P>
Les membres statiques Readonly vous donnent l'effet des énums complexes, mais n'engagez pas les frais généraux à moins que vous n'ayez besoin. P >
static class ErrorMessage { public string Description { get; private set; } public int Ordinal { get; private set; } private ComplexEnum() { } public static readonly NotFound = new ErrorMessage() { Ordinal = 0, Description = "Could not find" }; public static readonly BadRequest = new ErrorMessage() { Ordinal = 1, Description = "Malformed Request" }; }
Vous ne devez pas itérer sur Enums avec une addition / sous-traitance entier, car les énumérums ne sont pas garantis de manière séquentielle et vous pouvez facilement définir une énorme valeur non valide. Utilisez Enum.getvalues () code> à la place.
@Robert - ce n'est pas entièrement précis. Les valeurs indéfinies sont i> valables jusqu'à ce que c # est concerné. Il appartient à la callee de gérer un cas indéfini. > "L'ensemble de valeurs ... n'est pas limité par ses membres Enum." > "[A] NY Valeur du type sous-jacent ... est une valeur valide distincte ..." msdn.microsoft.com/en-us/library/aa664601 (v = vs.71) .aspx
Votre commentaire ne fait que renforcer mon point. Bien je vais reformuler. Évitez d'itération sur Enums avec une addition entière / soustraction. Ce n'est pas parce que vous ne pouvez pas dire que vous devriez (et comment savez-vous où commencer ou arrêter). Si vous voulez savoir et / ou itérer sur toutes les valeurs dans une énumération, utilisez Enum.getvalues () code>
@Robert - Nous arrivons à l'argument de 2 côtés différents. Je souligne qu'il n'y a pas de "démarrage ou d'arrêt" - ce sont toutes des valeurs valides. C'est la responsabilité de la callee i> de gérer toutes les valeurs sous-jacentes - et non de la responsabilité de l'appelant de passer uniquement des valeurs définies. Cela étant dit, je vais accepter que c'est rare de veut i> de passer une valeur indéfinie (sauf indication), donc Enum.getvalues code> est plus souvent approprié.
Vous dites que c'est "un bon tour" de pouvoir itération via le type sous-jacent, et c'est ce que je suis en désaccord - c'est une mauvaise pratique. Quand itération i>, le code doit commencer quelque part et mettre fin à quelque part (autre). Pour C # Int Enums, c'est 4294967295 VALEURS POSSIBLES Sauf si vous avez codé votre boucle avec la connaissance de ce que sont les valeurs les plus petites et les plus grandes (mauvais), ce qui suppose également que toutes les valeurs sont séquentielles (mauvais). Code qui a fait cela échouerait n'importe quel examen de code que j'ai jamais fait. La vérification de la validité des paramètres de Callee est la meilleure pratique, mais je n'ai jamais dit ni voulu impliquer que ce n'était pas le cas.
L'avantage principal des énormes intégrés est qu'ils ne prennent pas beaucoup de place en mémoire. Une instance d'un système Système par défaut.Int32 - Backed Enum prend seulement 4 octets de mémoire et peut être comparé rapidement à d'autres instances de cette énumération. P>
Dans construite, les énumjets à chaîne seraient des types de référence qui nécessitent que chaque instance soit attribuée sur le tas et les comparaisons impliquer de vérifier chaque caractère dans une chaîne. Vous pouvez probablement minimiser certaines des questions avec une certaine créativité dans le runtime et avec des compilateurs, mais vous avez toujours rencontré des problèmes similaires lorsque vous essayez de stocker efficacement l'ENum dans une base de données ou un autre magasin externe. P>
Bien que ce ne soit pas faux en soi, je doute que le stockage soit / était une considération. Un tas de références à la même chaîne internée en mémoire est, pour toutes les intentions, identiques à une bande de valeurs entières, et juste aussi bon marché à comparer.
Strictement parler, la représentation intrinsèque d'une énumération n'a pas d'importance, car par définition, ils sont des types énumérés. Ce que cela signifie que
public enum PrimaryColor { Red, Blue, Yellow }
La vraie réponse Pourquoi: Il n'y a jamais eu de raison convaincante de rendre les énums plus compliqués qu'eux. Si vous avez besoin d'une simple liste de valeurs fermée - ils sont. P>
in .NET, Enums ont reçu l'avantage supplémentaire de la représentation interne code> <-> Le mot clé ENUM est utilisé pour déclarer un
énumération, un type distinct qui
consiste en un ensemble de constantes nommées
appelé la liste énumératrice. p>
blockQuote>
ref: MSDN p>
Votre question est avec le mécanisme de stockage choisi, un entier. Ceci est juste un détail de mise en œuvre. Nous ne faisons que regarder en dessous des couvertures de ce type simple afin de maintenir la compatibilité binaire. Enums aurait autrement une utilité très limitée. P>
Q: Alors, pourquoi les énumes utilisent-t-elle un stockage entier? Comme d'autres ont souligné: p>
* Aucun de ceux-ci n'est spécifique à .NET, et il semble que les concepteurs CLR ne se sentent apparemment pas obligés de changer ou d'ajouter de l'or. P>
Maintenant que cela ne veut pas dire que votre syntaxe n'est pas entièrement peu attrayante. Mais l'effort de mettre en œuvre cette fonctionnalité dans le CLR et tous les compilateurs, justifiés? Pour tout le travail qui passe à cela, a-t-il vraiment acheté tout ce que vous ne pouviez pas déjà atteindre (avec des cours)? Mon sentiment d'intestin est non, il n'y a pas de véritable avantage. (Il y a un message par Eric Lippert Je voulais créer un lien vers, Mais je ne pouvais pas le trouver) p>
Vous pouvez écrire 10 lignes de code pour implémenter dans l'espace utilisateur ce que vous essayez d'obtenir sans tout le mal de tête de changement d'un compilateur. Votre code d'espace utilisateur est facilement maintenu au fil du temps - bien que peut-être pas aussi joli que s'il soit intégré, mais à la fin de la journée, c'est la même chose. Vous pouvez même avoir envie d'avoir une fantaisie avec un Modèle de génération de code T4 Si vous devez conserver de nombreuses valeurs d'enum-esques personnalisées dans votre projet. P>
Alors, Enums sont aussi compliqués que nécessaire. P>
la chaîne utilisée pour les définir code>. Ce petit changement ajoute quelques descentes en version de la version, mais s'améliore sur Enums en C ++. P>
[indicateurs] code> Style Enums) Li>
Bien que cela compte également comme une "alternative", vous pouvez toujours faire mieux que simplement un groupe de constitus: La seule capture ici est que, comme n'importe quelle valeur de valeur, celle-ci A une valeur par défaut, qui aura En général, Java - comme Advanced Enums traverse la ligne entre Enums réels et sucre syntaxique pour une hiérarchie de classe scellée. Si un tel sucre est une bonne idée ou non est arguable. P> p> s == null code>. Mais ce n'est pas vraiment différent de Java Enums, qui peuvent être eux-mêmes, ce qui peut être
null code> (Types de référence). P>
On dirait que votre problème réel n'est pas que vous souhaitez une énumération non intégrale, mais que vous voulez un moyen de proposer facilement un "texte lisible par l'homme" pour une énumération donnée, qui peut différer du nom utilisé dans le code. En pratique, je trouve que la solution correcte consiste à gérer correctement l'internationalisation, car les chances sont, la chaîne "lisible par l'homme" que vous souhaitez revenir va varier par les paramètres régionaux.
Je ne vois pas ce que sont les avantages, les identificateurs de l'énumement devraient suffire. Il suffit de renommer "rien de" à "ne pouvant pas oublier"
[Description ("Impossible de trouver")] code> fonctionne assez bien.