Convenzione di denominazione C # per enum e proprietà di corrispondenza


93

Spesso mi trovo a implementare una classe che mantiene una sorta di proprietà status come enum: ho una proprietà Status enum e ONE Status di tipo Status. Come dovrei risolvere questo conflitto di nomi?

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(); }
  }
}

Se l'enumerazione dello stato fosse comune a tipi diversi, lo metterei fuori dalla classe e il problema sarebbe risolto. Ma Status si applica solo a Car, quindi non ha senso dichiarare l'enumerazione al di fuori della classe.

Quale convenzione di denominazione usi in questo caso?

NB: Questa domanda è stata parzialmente discussa nei commenti di una risposta a questa domanda . Dato che non era la domanda principale , non ha avuto molta visibilità.

EDIT: Filip Ekberg suggerisce un'eccellente soluzione alternativa IMO per il caso specifico di "Status". Tuttavia, sarebbe interessante leggere le soluzioni in cui il nome dell'enumerazione / proprietà è diverso, come nella risposta di Michael Prewecki .

EDIT2 (maggio 2010): la mia soluzione preferita è quella di pluralizzare il nome del tipo di enumerazione, come suggerito da Chris S. Secondo le linee guida MS, questo dovrebbe essere usato solo per le enumerazioni flag. Ma mi piace sempre di più. Ora lo uso anche per enumerazioni regolari.


1
Non penso che ci siano molte buone soluzioni per questo se vuoi che enum sia annidato nella tua classe. In realtà preferisco avere l'enumerazione separata, quindi non presenta un problema, ma posso vedere filosoficamente il tuo punto sul volerlo annidare.
Craig Shearer

Risposte:


32

Aggiungerò il mio 1 euro alla discussione ma probabilmente non aggiungerò nulla di nuovo.

La soluzione più ovvia è spostare Status fuori dall'essere un Enum annidato. La maggior parte delle enumerazioni .NET (tranne forse alcune nello spazio dei nomi Windows.Forms) non sono nidificate e ne rende fastidioso l'utilizzo per lo sviluppatore che utilizza l'API, dovendo anteporre il nome della classe.

Una cosa che non è stata menzionata è che le enumerazioni dei flag secondo le linee guida MSDN dovrebbero essere sostantivi pluralizzati che probabilmente già conosci (lo stato è un enum semplice, quindi i nomi singolari dovrebbero essere usati).

State (enum chiamato States) è il vocativo, "Status" è il nominativo di un sostantivo che l'inglese come la maggior parte della nostra lingua ha assorbito dal latino. Vocativo è ciò che chiami un sostantivo per la sua condizione e nominativo è il soggetto del verbo.

Quindi, in altre parole, quando l'auto è in movimento , questo è il verbo: muoversi è il suo status. Ma l'auto non si spegne, il suo motore sì. Né si avvia, il motore sì (probabilmente hai scelto un esempio qui, quindi potrebbe essere irrilevante).

public class Car
{
  VehicleState _vehicleState= VehicleState.Stationary;

  public VehicleState VehicleState 
  {
    get { return _vehicleState; }
    set { _vehicleState = value; DoSomething(); }
  }
}

public enum VehicleState
{
    Stationary, Idle, Moving
}

Stato è un nome così generalizzato, non sarebbe meglio descrivere a quale stato si riferisce? Come ho fatto sopra

L'esempio di tipo anche a mio avviso non si riferisce al tipo di lettore, ma al suo database. Lo preferirei se descrivessi il prodotto del database del lettore che non è necessariamente rilevante per il tipo di lettore (ad esempio, il tipo di lettore potrebbe essere solo in avanti, in cache e così via). Così

reader.Database = Databases.Oracle;

In realtà questo non accade mai poiché sono implementati come driver e una catena di ereditarietà invece di utilizzare enumerazioni, motivo per cui la riga sopra non sembra naturale.


24
La mia comprensione è che i flag dovrebbero essere pluralizzati, non semplici enumerazioni.
Serge Wautier

8
per quanto riguarda lo spostamento di enumerazioni fuori dalla classe, devo ancora capire perché CarState sia più conveniente di Car.State. Tuttavia, non capisco il lato positivo di ottenere un'enumerazione da una classe quando questa enum descrive solo il comportamento di questa classe.
Serge Wautier

Avrei dovuto scrivere frasi nominali come FileOptions non solo sostantivi, ho aggiornato la risposta. Suppongo che classname.Enum sia solo una preferenza: non riesco a trovare alcun esempio nel framework che ciò che finisco per copiare.
Chris S,

Anche se MS dice che il plurale dovrebbe essere mantenuto per le bandiere, nel tempo, mi sono piaciute sempre di più le soluzioni. Ora lo uso anche per le enumerazioni. Quindi ho cambiato idea e ho accettato la tua risposta invece di quella di Filip.
Serge Wautier

1
So di essere in ritardo di 1 anno e mezzo qui, ma public class EngineStatedovrei essere public enum EngineStatenell'esempio, giusto?
David Murdoch

36

La definizione di "Off", "Starting" e "Moving" è ciò che chiamerei uno "Stato". E quando stai insinuando che stai usando uno "Stato", è il tuo "Stato". Così!

public class Car
{
  public enum State
  {
    Off,
    Starting,
    Moving
  };

  State state = State.Off;

  public State Status
  {
    get { return state ; }
    set { state= value; DoSomething(); }
  }
}

Se prendiamo un altro esempio da quello indicato in cui desideri utilizzare la parola "Tipo", in questo caso:

public class DataReader
{
    public enum Type
    {
        Sql,
        Oracle,
        OleDb
    }

    public Type Type { get; set; } // <===== Won't compile =====

}

Hai davvero bisogno di vedere che c'è una differenza tra enumerazioni ed enumerazioni, giusto? Ma quando crei un framework o parli di architettura devi concentrarti sulle somiglianze, ok cerchiamole:

Quando qualcosa è impostato su uno Stato, viene definito come lo Stato delle "cose"

Esempio: lo stato dell'auto è in stato di marcia, stato fermo e così via.

Quello che vuoi ottenere nel secondo esempio è in qualche modo questo:

myDataReader.Type = DataReader.Database.OleDb

Potresti pensare che questo dica contro ciò che ho predicato agli altri, che devi seguire uno standard. Ma stai seguendo uno standard! Il caso Sql è anche un caso specifico e quindi necessita di una soluzione un po 'specifica.

Tuttavia, l'enumerazione sarebbe riutilizzabile all'interno del tuo file System.Data spazio, ed è di questo che si tratta.

Un altro caso da considerare con il "Tipo" è "Animale" dove Tipo definisce la specie.

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

        public Type Species{ get; set; }

    }

Questo sta seguendo uno schema, non hai bisogno di "conoscere" specificatamente l'Oggetto per questo e non stai specificando "AnimalType" o "DataReaderType", puoi riutilizzare le enumerazioni nel tuo spazio dei nomi preferito.


1
Credo che il nome "Stato" fosse solo un esempio. Che dire di altre situazioni, in cui non puoi fare affidamento su Stato / Stato? Ad esempio un tipo enumerazione ...
Dan C.

Potrebbe fornire uno scenario di esempio per questo? Cercherò di espandere la mia risposta anche in base a quello :)
Filip Ekberg

2
@Filip: l'esempio di Animal Type indica esattamente cosa intendevo nel primo commento, ovvero si tratta praticamente di una "riformulazione" dell'enumerazione. L'uso dei sinonimi per l'enumerazione e il nome della proprietà rende il codice un po 'confuso, credo.
Dan C.

1
Penso anche che "specie" sia solo una riformulazione del tipo (per gli animali in questo caso).
LegendLength

2
La semplice ridenominazione non è sempre così pulita - pensa ad una classe per una carta da gioco, ad esempio, con un seme enumerato e un seme di proprietà - rinominare esattamente in cosa? Goffo in ogni caso.
annakata

9

Penso che il vero problema qui sia che l'enum Status è incapsulato all'interno della tua classe, in modo che Car.Statussia ambiguo sia per la proprietà Statusche per l'enumStatus

Meglio ancora, metti il ​​tuo enum fuori dalla classe:

public enum Status
{
    Off,
    Starting,
    Moving
}

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

AGGIORNARE

A causa dei commenti qui sotto, spiegherò il mio design sopra.

Sono uno che non crede che enumerazioni o classi o qualsiasi altro oggetto debba risiedere all'interno di un'altra classe, a meno che non sia totalmente privato all'interno di quella classe. Prendi l'esempio sopra, ad esempio:

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

Mentre alcuni commentatori sostengono che Stato non ha alcun significato al di fuori del campo di applicazione della classe Car, il fatto che si sta impostando un pubblico mezzi di proprietà che ci sono altre parti del programma che farà l'uso che enum:

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

E questo per me è un odore di codice. Se guarderò a quello stato al di fuori di Car, potrei anche definirlo al di fuori .

Come tale, probabilmente lo rinominerò come:

public enum CarStatus
{...}

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

Tuttavia, se tale enumerazione verrà utilizzata all'interno e solo all'interno della classe auto, allora mi va bene dichiarare l'enumerazione lì.


Ciò renderebbe lo stato globale, potresti volerlo avere solo all'interno di un'area specifica. "Stato" per altri tipi come "Umano" potrebbe non avere "Avvio". Ma dovresti seguire uno schema.
Filip Ekberg,

No, è perfetto. L'enumerazione è nel 99% dei casi la stessa parola che si desidera utilizzare per la proprietà. Un enum è solo una bandiera con nome, quindi non fa molto male a vivere fuori (a differenza delle classi che contengono logica)
Quibblesome

Jon, questo è precisamente il mio punto: l'enumerazione Status è significativa solo per quanto riguarda l'Auto. Tipi di oggetti completamente diversi avranno stati completamente diversi
Serge Wautier il

saranno comunque in spazi dei nomi diversi, quindi non importa
Chris S,

La spiegazione secondo cui volerlo guardare fuori da Car ha senso. Ma nel mio caso ho due classi, ORe CR. Entrambi hanno il proprio insieme di stati, quindi non è un'opzione per definirli al di fuori del proprio ambito.
02392

4

So che il mio suggerimento va contro le convenzioni di denominazione .NET, ma personalmente prefisso le enumerazioni con "E" e le enumerazioni con "F" (simile a come prefisso Interfacce con "I"). Davvero non capisco perché questa non sia la convenzione. Le enumerazioni / flag sono un caso speciale come le interfacce che non cambieranno mai il loro tipo. Non solo rende chiaro di cosa si tratta, è molto facile digitare intellisense poiché il prefisso filtrerà la maggior parte degli altri tipi / variabili / ecc. E non avrai questi conflitti di denominazione.

E ciò risolverebbe anche un altro problema in cui per esempi in WPF si usano classi statiche come enumerazioni (ad esempio FontWeights) che hanno istanze di tipi predefinite ma non lo sapresti se non le cerchi. Se li precedessero semplicemente con "E", tutto ciò che dovresti fare è digitare sul carattere per trovare queste classi statiche speciali.


4

Al diavolo chi odia la notazione ungherese e le sue varianti. Uso una convenzione di suffisso delle enumerazioni con - aspetta - Enum. Di conseguenza non ho mai il problema che descrivi, perdo tempo a preoccuparmi di come chiamarli e il codice è leggibile e auto-descrittivo per l'avvio.

public class Car
{
  public enum StatusEnum
  {
    Off,
    Starting,
    Moving
  };

  public StatusEnum Status { get; set; }

}

9
Tenere presente, tuttavia, che le convenzioni di Microsoft per le enumerazioni dei nomi dicono: X NON utilizzare un suffisso "Enum" nei nomi dei tipi di
DavidRR

2
Perché le convenzioni di Microsoft hanno dimostrato di resistere alla prova del tempo.
nathanchere

2

Modificherei il nome della proprietà in qualcosa come "CurrentStatus". Veloce e facile :)


1

Suggerisco di aggiungere "Opzione" al nome del tipo (o Flag se contiene flag di bit), cioè il tipo è Car.StatusOption e la proprietà è Car.Status.

Rispetto al pluralismo, questo evita le collisioni di denominazione quando si creano raccolte del tipo enum, dove normalmente si desidera pluralizzare la proprietà della raccolta , non il tipo enum .


0

Di solito ho prefisso le enumerazioni, ad esempio CarStatus. Suppongo che tutto dipenda dal team con cui lavori (se hanno regole / processi per quel genere di cose) e dall'utilizzo degli oggetti. Solo i miei 2 centesimi (:


1
Ciò effettivamente ucciderebbe la convenzione di denominazione con MyObjectName davanti a Status.
Filip Ekberg,

il Namespacing della classe dovrebbe essere sufficiente per affrontare questo comunque
annakata
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.