Convention de dénomination C # pour enum et propriété correspondante

93

Je me retrouve souvent à implémenter une classe maintenant une sorte de propriété de statut propre en tant qu'énumération: j'ai une énumération Status et une propriété Status de type Status. Comment dois-je résoudre ce conflit de noms?

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 Status était commune à différents types, je la mettrais en dehors de la classe et le problème serait résolu. Mais Status 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 à cette question . Comme ce n'était pas la question principale , cela n'a pas eu beaucoup de visibilité.

EDIT: Filip Ekberg suggère 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 mettre au pluriel le nom du type enum, comme suggéré par Chris S. Selon les directives de MS, cela ne devrait être utilisé que pour les énumérations d'indicateurs. Mais je l'aime de plus en plus. Je l'utilise maintenant aussi pour les énumérations régulières.

Serge Wautier
la source
1
Je ne pense pas qu'il y ait beaucoup de bonnes solutions pour cela si vous voulez avoir l'énumération imbriquée dans votre classe. En fait, je préfère que l'énumération soit séparée, alors cela ne pose pas de problème, mais je peux comprendre votre point de vue philosophique sur le fait de vouloir l'imbriquer.
Craig Shearer

Réponses:

32

J'ajouterai mon 1 euro à la discussion mais ça n'ajoute probablement rien de nouveau.

La solution évidente consiste à faire de Status un Enum imbriqué. La plupart des énumérations .NET (sauf peut-être certaines dans l'espace de noms Windows.Forms) ne sont pas imbriquées et cela rend son utilisation ennuyeuse pour le développeur qui utilise votre API, qui doit préfixer le nom de la 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 au pluriel que vous connaissez probablement déjà (Status est une énumération simple, donc les noms singuliers doivent être utilisés).

State (enum appelé States) est le vocatif, "Status" est le nominatif d'un nom que l'anglais comme la plupart de notre langue a absorbé du latin. Le vocatif est ce que vous nommez un nom pour sa condition et le nominatif est le sujet du verbe.

Donc, en d'autres termes, lorsque la voiture est en mouvement , c'est le verbe - bouger est son statut. Mais la voiture ne démarre pas, son moteur le fait. Il ne démarre pas non plus, le moteur ne le fait pas (vous avez probablement choisi un exemple ici, cela peut donc 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
}

L'état est un nom si généralisé, ne serait-il pas préférable de décrire à quel état il se réfère? Comme je l'ai fait ci-dessus

L'exemple de type, à mon avis, ne fait pas non plus 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 uniquement en avant, 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 n'a pas l'air naturelle.

Chris S
la source
24
Je crois comprendre que les drapeaux doivent être pluralisés, pas de simples énumérations.
Serge Wautier
8
concernant le déplacement des énumérations hors de la classe, je n'ai pas encore compris pourquoi CarState est plus pratique que Car.State. Cependant, je ne comprends pas le côté positif d'obtenir une énumération d'une classe lorsque cette énumération décrit uniquement le comportement de cette classe.
Serge Wautier
J'aurais dû écrire des phrases nominales comme FileOptions, pas seulement des noms, j'ai mis à jour la réponse. Je suppose que classname.Enum est juste une préférence - je ne trouve aucun exemple dans le cadre que je finis par copier.
Chris S
Même si MS dit que le pluriel doit être conservé pour les drapeaux, au fil du temps, j'apprécie de plus en plus ces solutions. Je l'utilise maintenant aussi pour les énumérations. J'ai donc changé d'avis et accepté votre réponse au lieu de celle de Filip.
Serge Wautier
1
Je sais que j'ai 1 an et demi de retard ici, mais public class EngineStatedevrait être public enum EngineStatedans l'exemple, non?
David Murdoch
36

La définition de «Off», «Démarrage» et «Déplacement» est ce que j'appellerais un «État». Et lorsque vous sous-entendez que vous utilisez un "État", c'est votre "Statut". 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 avez vraiment besoin de 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 similitudes, ok, trouvons-les:

Lorsqu'un élément est défini sur un état, il est défini comme le statut "choses"

Exemple: l'état de la voiture est en état de marche, à l'arrêt, etc.

Ce que vous voulez atteindre dans le deuxième exemple est un peu ceci:

myDataReader.Type = DataReader.Database.OleDb

Vous pourriez penser que cela va à l'encontre de 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 serait réutilisable dans votre System.Data espace, et c'est de cela qu'il s'agit.

Un autre cas à examiner avec le "Type" est "Animal" où le Type définit l'espèce.

public class Animal
    {
        public enum Type
        {
            Mammal,
            Reptile,
            JonSkeet
        }

        public Type Species{ get; set; }

    }

Ceci 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 l'espace de nom de votre choix.

Filip Ekberg
la source
1
Je pense que le nom "Statut" n'était qu'un exemple. Qu'en est-il des autres situations, lorsque vous ne pouvez pas compter sur le statut / l'état? Par exemple, un type enum ...
Dan C.
Pourriez-vous nous donner un exemple de scénario pour cela? Je vais essayer d'élargir ma réponse en fonction de cela aussi :)
Filip Ekberg
2
@Filip: l'exemple d'Animal Type montre exactement ce que je voulais dire dans le premier commentaire, c'est-à-dire qu'il s'agit plutôt d'une "reformulation" de l'énumération. L'utilisation de synonymes pour l'énumération et le nom de la propriété rend le code quelque peu déroutant, je pense.
Dan C.
1
Je pense aussi que «espèce» est juste une reformulation de type (pour les animaux dans ce cas).
LegendLength
2
Le simple fait de renommer n'est pas toujours aussi clair - pensez à une classe pour une carte à jouer par exemple, avec un enum Suit et une propriété Suit - renommer en quoi exactement? Maladroit de toute façon.
annakata
9

Je pense que le vrai problème ici est que l'énumération Status est encapsulée dans votre classe, ce qui Car.Statusest ambigu à la fois pour la propriétéStatus et l'énumérationStatus

Mieux encore, mettez votre énumération en dehors de la classe:

public enum Status
{
    Off,
    Starting,
    Moving
}

public class Car
{
    public Status Status
    { ... }
}

METTRE À JOUR

En raison des commentaires ci-dessous, je vais expliquer ma conception ci-dessus.

Je suis du genre à ne pas croire que les énumérations, les classes ou tout autre objet devraient résider dans une autre classe, à moins que ce ne soit totalement privé dans cette classe. Prenons l'exemple ci-dessus, par exemple:

public class Car
{
    public enum Status
    {...}
    ...
    public Status CarStatus { get; set;}
}

Alors que certains commentateurs soutiendraient que l' état n'a pas de sens en dehors de la portée de la voiture de classe, le fait que vous définissez un publique des moyens de propriété que d' autres parties du programme qui va utiliser qu'ENUM:

public Car myCar = new Car();
myCar.CarStatus = Car.Status.Off;

Et que pour moi est une odeur de code. Si je vais regarder ce statut en dehors de Car, je pourrais aussi bien le définir en dehors .

En tant que tel, je vais probablement le renommer comme suit:

public enum CarStatus
{...}

public class Car
{
    ...
    public CarStatus Status { get; set; }
}

Cependant, si cette énumération est utilisée dans et uniquement dans la classe de voiture, alors je suis d'accord pour déclarer l'énumération ici.

Jon Limjap
la source
Cela rendrait Status global, vous voudrez peut-être l'avoir juste dans une zone spécifique. "Statut" pour d'autres types tels que "Humain" peut ne pas avoir "Démarrage". Mais vous devez suivre un modèle.
Filip Ekberg
Non, il est sur place. L'énumération est dans 99% des cas le même mot que vous souhaitez utiliser pour la propriété. Une énumération est juste un drapeau nommé, donc il fait peu de mal à vivre à l'extérieur (contrairement aux classes qui contiennent de la logique)
Quibblesome
Jon, c'est précisément ce que je veux dire: l'énumération Status n'a de sens que pour Car. Des types d'objets totalement différents auront des statuts totalement différents
Serge Wautier
ils seront dans des espaces de noms différents, donc peu importe
Chris S
L'explication selon laquelle vouloir le regarder en dehors de Car a du sens. Mais dans mon cas, j'ai deux classes, ORet CR. Les deux ont leur propre ensemble d'états, il n'est donc pas possible de les définir en dehors de leur propre portée.
deed02392
4

Je sais que ma suggestion va à l'encontre des conventions de dénomination .NET, mais personnellement, je préfixe les énumérations avec «E» et les drapeaux enum avec «F» (similaire à la façon dont nous préfixons les interfaces avec «I»). Je ne comprends vraiment pas pourquoi ce n'est pas la convention. Les Enums / Flags sont un cas particulier comme les Interfaces qui ne changeront jamais leur type. Non seulement cela indique clairement ce que c'est, mais il est très facile de taper dans intellisense puisque 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 sauriez pas si vous ne les recherchez pas. S'ils les préfixaient simplement avec «E», tout ce que vous auriez à faire est de taper sur caractère pour trouver ces classes statiques spéciales.


la source
4

Les haineux de la notation hongroise et de ses variantes soient damnés. J'utilise une convention de suffixe enums avec - attendez - Enum. Par conséquent, je n'ai jamais le problème que vous décrivez, je perds du temps à me demander 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; }

}
nathanchere
la source
9
Sachez cependant que les conventions de Microsoft pour les énumérations de noms indiquent: X N'utilisez PAS de suffixe «Enum» dans les noms de type enum.
DavidRR
2
Parce que les conventions de Microsoft ont fait leurs preuves pour résister à l'épreuve du temps.
nathanchere
2

Je changerais le nom de la propriété en quelque chose comme "CurrentStatus". Rapide et facile :)

TWith2Sucres
la source
1

Je suggère d'ajouter "Option" au nom du type (ou Flag s'il contient des bits indicateurs), c'est-à-dire que le type est Car.StatusOption et la propriété est Car.Status.

Par rapport à la mise en pluralité, cela évite les collisions de dénomination lors de la création de collections de type enum, où vous voudriez normalement mettre au pluriel la propriété de collection , pas le type enum .

Kristian Wedberg
la source
0

Je préfixe généralement les énumérations, par exemple 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 (:

Kieron
la source
1
Cela tuerait en fait la convention de dénomination ayant MyObjectName en face de Status.
Filip Ekberg
l'espacement de noms de la classe devrait être suffisant pour gérer cela de toute façon
annakata