73 votes

Pourquoi le compilateur c# ne permet pas les enums vides ?

J'ai accidentellement défini un enum aujourd'hui que contenait pas de valeurs. Comme celui-ci par exemple:

public enum MyConfusingEnum{}

Le compilateur a été assez heureux pour me laisser le définir et le code intégré avec succès.

Maintenant, évidemment je ne peux pas l'utiliser dans le sens traditionnel du terme, puisque le code,..

var mySadCompiler = MyConfusingEnum;

ne spécifiez pas de valeur, mais curieusement j'ai été en mesure de dire,..

var myRoundTheHousesZeroState = Activator.CreateInstance<MyConfusingEnum>();

qui, comme je l'ai déjà fait allusion, est un type de valeur de MyConfusingEnum avec la valeur 0;

Ma question est pourquoi le compilateur permettre une définition vide et quels sont les scénarios où il pourrait être utile?

91voto

Eric Lippert Points 300275

Tout d'abord, il aurait pu le faire beaucoup plus facilement:

MyConfusingEnum x1 = 0;
MyConfusingEnum x2 = default(MyConfusingEnum);
MyConfusingEnum x3 = new MyConfusingEnum();
MyConfusingEnum x4 = (MyConfusingEnum) 123;

tous les ci-dessus fonctionnent tout aussi bien. (Vous pourriez être surpris de voir que les premières œuvres; voir la section spécifications sur énumération implicite des conversions pour plus de détails.)

Ma question est pourquoi le compilateur permettre une définition vide

Je vais commencer par répondre à votre question par une question. Souhaitez-vous également que le compilateur rejeter?

class C {}
interface I {}
struct S {}

Pourquoi ou pourquoi pas?

Pour plus directement pas de réponse à votre question: "pourquoi le monde est-il pas différent de ce qu'il est?" des questions difficiles à répondre. Au lieu de répondre à cette question impossible, je vais répondre à la question "supposons que faire vider les énumérations, une erreur avait été lancé à l'équipe de conception; comment auriez-vous réagi à cette hauteur?" Cette question est encore hypothétiques , mais au moins, il en est une que je peux répondre.

La question est alors de savoir si le coût de la fonction est justifié par ses prestations.

Dans l'ordre de travailler le langage doit être pensé, conçu, spécifié, mis en oeuvre, testé, documenté et expédiés aux clients. C'est un "produire une erreur", de sorte que le message d'erreur doit être écrit et traduit dans une douzaine de langues, ainsi que la documentation. Les cinq minutes, il m'aurait pris pour mettre en œuvre la fonctionnalité de traduire en nombre d'heures de travail par beaucoup de gens qui sont payés plutôt beaucoup.

Cependant, qui n'est effectivement pas le coût. Le coût d'opportunité est le coût. Les Budgets sont finis, les fonctionnalités ne sont pas libres, et par conséquent, toute fonction qui est mise en place de certains autres fonctionnalité doit être coupé; la fonctionnalité de C# aimeriez-vous avoir été coupé pour obtenir cette fonctionnalité? Le perdu l' avantage de ne pas être capable de faire une meilleure fonctionnalité est le coût d'opportunité.

Je note aussi que votre proposition de fonctionnalité a zéro avantage évident pour la personne, ce qui serait difficile à vendre pour le comité de conception. Peut-être il ya une convaincante des avantages que je ne vois pas; si oui, quel est-il?

existe-il des scénarios où il pourrait être utile?

Aucun viennent à l'esprit. "Rejetant les programmes qui ne sont pas évidemment utile" n'est pas un objectif de conception de C#.

17voto

Alexei Levenkov Points 49945

Vous pouvez mettre en valeur des sous-jacents de type entier (je pense que int par défaut) pour l'enum - donc, (MyConfusingEnum)42 maintenant sera de type enum.

Je ne pense pas que c'est une bonne idée en général, mais il pourrait y avoir des cas où "enum" les valeurs sont à venir à partir de source externe et le code, tout semble plus agréable avec enum.

Exemple (en supposant que le code incapsulates certains "int etat" dans Enum:

enum ExternalDeviceState {};

ExternalDeviceState GetState(){ ... return (ExternalDeviceState )intState;}
bool IsDeviceStillOk(ExternalDeviceState currentState) { .... }

Spécification, en effet, permettre à vide enum:

14.1 Enum déclarations

Une déclaration d'enum déclare un nouveau type enum. Une déclaration d'enum commence avec le mot-clé enum, et définit le nom, l'accessibilité, type sous-jacent, et les membres de l'enum.

enum-declaration:
   attributesopt   enum-modifiersopt   enum   identifier
        enum-base(opt)   enum-body   ;(opt)

enum-base:
:   integral-type

enum-body:
  {   enum-member-declarations(opt)   }  
  {   enum-member-declarations   ,   }

Notez que enum-member-declarations(opt) est explicitement marqué comme variante, où rien n'est à l'intérieur d' {}.

14voto

Stijn Points 6427

Activator.CreateInstance<MyConfusingEnum>(); est le même que new MyConfusingEnum(). (docs)

Appeler le constructeur d'un enum vous donne 0 de la valeur.

En raison d'une décision de conception, un enum peut avoir n'importe quelle valeur qui est valide pour le type de dossier (habituellement int), il n'a pas à être une valeur définie dans le protocole enum.

Pour la raison de cette décision de conception, je peux vous aider à trouver cette réponse sur une question intitulée "Pourquoi ne coulée int valides valeur d'enum PAS jeter l'exception?"

@AlexeiLevenkov a fourni à la spécification qui permet à un vide enum, on peut deviner que la raison pour cela est que depuis tout support type de valeur est valide, un vide enum est autorisé.

7voto

Panos Theof Points 402

Existe-t-il des scénarios où cela pourrait être utile?

Comme d'autres l'ont déjà mentionné, vous pouvez affecter à cette énumération toute valeur autorisée par le type sous-jacent par une conversion simple. De cette façon, vous pouvez appliquer la vérification de type, dans les situations où un int créerait une confusion. Par exemple:

 public enum Argb : int {}

public void SetColor(Argb a) { ....
 

ou vous voulez avoir des méthodes d'extension sans utiliser le type de données int, avec elles

 public static Color GetColor(this Argb value) {
    return new Color( (int)value );
}
 

3voto

my_greets Points 161

Existe-il des scénarios où il pourrait être utile?

J'ai vécu l'un dans le monde Java.

Dans le cas des énumérations, vous savez toutes les valeurs possibles au moment de la compilation.

Cependant, il y a un temps avant le temps de compilation dans laquelle on ne peut pas connaître toutes les valeurs (encore) ou en qui vous n'avez tout simplement pas l'intention de mettre en œuvre toutes les valeurs, encore.

Dans le cadre de la conception d'une API, j'ai mis en place une énumération sans valeurs pour permettre le référencement des autres interfaces. J'ai ajouté des valeurs plus tard.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X