Je me retrouve souvent à implémenter une classe maintenant une sorte de propriété de statut en tant qu'enum: j'ai une énumération de statut et une propriété de statut de type Status. Comment dois-je résoudre ce conflit de nom?
public class Car
{
public enum Status
{
Off,
Starting,
Moving
};
Status status = Status.Off;
public Status Status // <===== Won't compile =====
{
get { return status; }
set { status = value; DoSomething(); }
}
}
Si l'énumération de statut était commune à différents types, je la mettrais en dehors de la classe et le problème serait résolu. Mais le statut ne s'applique qu'à Car, il n'est donc pas logique de déclarer l'énumération en dehors de la classe.
Quelle convention de dénomination utilisez-vous dans ce cas?
NB: Cette question a été partiellement débattue dans les commentaires d'une réponse de cette question . Comme ce n'était pas la question principale , elle n'a pas eu beaucoup de visibilité.
EDIT: Filip Ekberg propose une excellente solution de contournement de l'OMI pour le cas spécifique du "Statut". Pourtant, je serais intéressant de lire sur les solutions où le nom de l'énumération/propriété est différent, comme dans la réponse de Michael Prewecki .
EDIT2 (mai 2010): Ma solution préférée est de pluraliser le nom du type d'énumération, comme suggéré par Chris S. Selon les directives de MS, cela ne devrait être utilisé que pour les énumérations d'indicateur. Mais j'en suis venu à l'apprécier de plus en plus. Je l'utilise maintenant également pour les énumérations régulières.
J'ajouterai mon 1 euro à la discussion, mais il n'ajoute probablement rien de nouveau.
La solution évidente consiste à retirer le statut de l'énumération imbriquée. La plupart des énumérations .NET (à l'exception peut-être de certains dans l'espace de noms Windows.Forms) ne sont pas imbriquées et il est ennuyeux à utiliser pour le développeur consommant votre API, devant avoir le préfixe du nom de classe.
Une chose qui n'a pas été mentionnée est que les énumérations d'indicateurs selon les directives MSDN devraient être des noms pluralisés que vous connaissez probablement déjà (Le statut est une énumération simple, il faut donc utiliser des noms singuliers).
État (enum appelé États) est le vocatif, "Status" est le nominatif d'un nom que l'anglais comme la plupart de notre langue a absorbé du latin. Vocatif est ce que vous nommez un nom pour son état et nominatif est le sujet du verbe.
En d'autres termes, lorsque la voiture se déplace , c'est le verbe - se déplacer est son statut. Mais la voiture ne s'arrête pas, son moteur le fait. Il ne démarre pas non plus, le moteur le fait (vous avez probablement choisi un exemple ici, donc cela pourrait ne pas être pertinent).
public class Car
{
VehicleState _vehicleState= VehicleState.Stationary;
public VehicleState VehicleState
{
get { return _vehicleState; }
set { _vehicleState = value; DoSomething(); }
}
}
public enum VehicleState
{
Stationary, Idle, Moving
}
État est un nom si généralisé ne vaudrait-il pas mieux décrire de quel état il s'agit? Comme je l'ai fait ci-dessus
L'exemple de type également à mon avis ne fait pas référence au type de lecteur, mais à sa base de données. Je préférerais que vous décriviez le produit de base de données du lecteur qui n'est pas nécessairement pertinent pour le type de lecteur (par exemple, le type de lecteur peut être transmis uniquement, mis en cache, etc.). Alors
reader.Database = Databases.Oracle;
En réalité, cela ne se produit jamais car ils sont implémentés en tant que pilotes et chaîne d'héritage au lieu d'utiliser des énumérations, c'est pourquoi la ligne ci-dessus ne semble pas naturelle.
La définition de "Off", "Starting" et "Moving" est ce que j'appellerais un "État". Et lorsque vous sous-entendez que vous utilisez un "État", c'est votre "État". Alors!
public class Car
{
public enum State
{
Off,
Starting,
Moving
};
State state = State.Off;
public State Status
{
get { return state ; }
set { state= value; DoSomething(); }
}
}
Si nous prenons un autre exemple de celui indiqué où vous souhaitez utiliser le mot "Type" comme dans ce cas:
public class DataReader
{
public enum Type
{
Sql,
Oracle,
OleDb
}
public Type Type { get; set; } // <===== Won't compile =====
}
Vous devez vraiment voir qu'il y a une différence entre les énumérations et les énumérations, non? Mais lorsque vous créez un framework ou que vous parlez d'architecture, vous devez vous concentrer sur les simillarités, ok permet de les trouver:
Quand quelque chose est réglé sur un état, il est défini comme le statut "choses"
Exemple: l'état de la voiture est en état de marche, en état d'arrêt, etc.
Ce que vous voulez réaliser dans le deuxième exemple est un peu ceci:
myDataReader.Type = DataReader.Database.OleDb
Vous pourriez penser que cela dit contre ce que j'ai prêché aux autres, que vous devez suivre une norme. Mais, vous suivez une norme! Le cas SQL est également un cas spécifique et nécessite donc une solution quelque peu spécifique.
Cependant, l'énumération sera réutilisable dans votre System.Data
l'espace, et c'est de cela qu'il s'agit.
Un autre cas à examiner avec le "Type" est "Animal" où le Type définit les Espèces.
public class Animal
{
public enum Type
{
Mammal,
Reptile,
JonSkeet
}
public Type Species{ get; set; }
}
Cela suit un modèle, vous n'avez pas spécifiquement besoin de "connaître" l'objet pour cela et vous ne spécifiez pas "AnimalType" ou "DataReaderType", vous pouvez réutiliser les énumérations dans votre espace de noms de choix.
Je pense que le vrai problème ici est que le statut enum est encapsulé dans votre classe, de telle sorte que Car.Status
est ambigu à la fois pour la propriété Status
et l'énumération Status
Mieux encore, mettez votre énumération en dehors de la classe:
public enum Status
{
Off,
Starting,
Moving
}
public class Car
{
public Status Status
{ ... }
}
MISE À JOUR
En raison des commentaires ci-dessous, je vais expliquer ma conception ci-dessus.
Je suis quelqu'un qui ne croit pas que les énumérations ou les classes ou tout autre objet devraient résider à l'intérieur une autre classe, à moins qu'il ne soit totalement privé au sein de cette classe. Prenons l'exemple ci-dessus, par exemple:
public class Car
{
public enum Status
{...}
...
public Status CarStatus { get; set;}
}
Alors que certains commentateurs soutiennent que Status n'a aucune signification en dehors du champ d'application de la classe Car, le fait que vous définissez une propriété public signifie qu'il existe d'autres parties du programme qui = va utilisez cette énumération:
public Car myCar = new Car();
myCar.CarStatus = Car.Status.Off;
Et ça pour moi, c'est une odeur de code. Si je regarde cet état extérieur de Car
, je ferais aussi bien de le définir extérieur.
En tant que tel, je vais probablement le renommer comme:
public enum CarStatus
{...}
public class Car
{
...
public CarStatus Status { get; set; }
}
Cependant, si cette énumération sera utilisée dans et seulement dans la classe de voiture, alors je suis d'accord avec déclarer l'énumération là.
Les haineux de la notation hongroise et ses variantes soient damnés. J'utilise une convention de suffixe des énumérations avec - attendez - Enum
. Par conséquent, je n'ai jamais le problème que vous décrivez, perdez du temps à vous soucier de comment les appeler et le code est lisible et auto-descriptif pour démarrer.
public class Car
{
public enum StatusEnum
{
Off,
Starting,
Moving
};
public StatusEnum Status { get; set; }
}
Je sais que ma suggestion va à l'encontre des conventions de dénomination .NET, mais je préfixe personnellement les énumérations avec "E" et les indicateurs d'énumération avec "F" (de la même manière que nous préfixons les interfaces avec "I"). Je ne comprends vraiment pas pourquoi ce n'est pas la convention. Les énumérations/indicateurs sont un cas spécial comme les interfaces qui ne changeront jamais leur type. Non seulement cela clarifie ce que c'est, mais il est très facile de taper intellisense car le préfixe filtrera la plupart des autres types/variables/etc, et vous n'aurez pas ces conflits de noms.
Et cela résoudrait également un autre problème où, pour des exemples dans WPF, ils utilisent des classes statiques comme des énumérations (par exemple FontWeights) qui ont des instances de types prédéfinies mais vous ne savez pas si vous ne le recherchez pas. S'ils les préfixaient juste avec 'E', tout ce que vous auriez à faire serait de taper sur le caractère pour trouver ces classes statiques spéciales.
Je changerais le nom de la propriété en quelque chose comme "CurrentStatus". Rapide et facile :)
Je suggère d'ajouter "Option" au nom du type (ou Flag s'il contient des indicateurs de bit), c'est-à-dire que type est Car.StatusOption et la propriété est Car.Status.
Par rapport à la pluralisation, cela évite les collisions de noms lors de la création de collections de type enum, où vous voudriez normalement pluraliser la collection propriété, pas l'énum type.
Je préfixe généralement les énumérations, par ex. CarStatus. Je suppose que tout dépend de l'équipe avec laquelle vous travaillez (s'ils ont des règles/processus pour ce genre de choses) et de l'utilisation des objets. Juste mes 2 cents (: