C # -Namenskonvention für Aufzählung und übereinstimmende Eigenschaft

93

Ich implementiere häufig eine Klasse, die eine eigene Statuseigenschaft als Aufzählung verwaltet: Ich habe eine Statusaufzählung und EINE Statuseigenschaft vom Statustyp. Wie soll ich diesen Namenskonflikt lösen?

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

Wenn die Statusaufzählung verschiedenen Typen gemeinsam wäre, würde ich sie außerhalb der Klasse platzieren und das Problem wäre gelöst. Der Status gilt jedoch nur für das Auto, daher ist es nicht sinnvoll, die Aufzählung außerhalb der Klasse anzugeben.

Welche Namenskonvention verwenden Sie in diesem Fall?

NB: Diese Frage wurde teilweise in Kommentaren einer Antwort auf diese Frage diskutiert . Da es nicht die Hauptfrage war , wurde es nicht viel sichtbar.

BEARBEITEN: Filip Ekberg schlägt eine hervorragende IMO-Problemumgehung für den speziellen Fall von 'Status' vor. Es wäre jedoch interessant, über Lösungen zu lesen, bei denen der Name der Aufzählung / Eigenschaft anders ist, wie in der Antwort von Michael Prewecki .

EDIT2 (Mai 2010): Meine Lieblingslösung besteht darin, den Namen des Aufzählungstyps zu pluralisieren, wie von Chris S. vorgeschlagen. Gemäß den MS-Richtlinien sollte dies nur für Flaggenaufzählungen verwendet werden. Aber ich habe es immer mehr gemocht. Ich benutze es jetzt auch für reguläre Aufzählungen.

Serge Wautier
quelle
1
Ich denke nicht, dass es dafür viele gute Lösungen gibt, wenn Sie die Aufzählung in Ihrer Klasse verschachteln möchten. Eigentlich ziehe ich es vor, die Aufzählung getrennt zu haben, dann stellt sie kein Problem dar, aber ich kann Ihren Standpunkt philosophisch darin sehen, sie verschachteln zu wollen.
Craig Shearer

Antworten:

32

Ich werde meine 1 Euro zur Diskussion hinzufügen, aber es wird wahrscheinlich nichts Neues hinzugefügt.

Die naheliegende Lösung besteht darin, Status aus einer verschachtelten Aufzählung zu entfernen. Die meisten .NET-Enums (außer möglicherweise einige im Windows.Forms-Namespace) sind nicht verschachtelt, und es ist ärgerlich, sie für Entwickler zu verwenden, die Ihre API verwenden und dem Klassennamen ein Präfix voranstellen müssen.

Eine Sache, die nicht erwähnt wurde, ist, dass Flaggen-Enums gemäß den MSDN-Richtlinien pluralisierte Substantive sein sollten , die Sie wahrscheinlich bereits kennen (Status ist eine einfache Enumeration, daher sollten singuläre Substantive verwendet werden).

State (Enum genannt States) ist der Vokativ, "Status" ist der Nominativ eines Substantivs, das die Engländer wie die meisten unserer Sprachen aus dem Lateinischen aufgenommen haben. Vokativ ist das, was Sie ein Substantiv für seinen Zustand nennen, und Nominativ ist das Thema des Verbs.

Mit anderen Worten, wenn sich das Auto bewegt , ist das das Verb - Bewegen ist sein Status. Aber das Auto geht nicht aus, der Motor schon. Es startet auch nicht, der Motor nicht (Sie haben hier wahrscheinlich ein Beispiel ausgewählt, sodass dies möglicherweise irrelevant ist).

public class Car
{
  VehicleState _vehicleState= VehicleState.Stationary;

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

public enum VehicleState
{
    Stationary, Idle, Moving
}

Staat ist so ein verallgemeinertes Substantiv. Wäre es nicht besser zu beschreiben, auf welchen Zustand es sich bezieht? Wie ich es oben getan habe

Das Typbeispiel bezieht sich auch aus meiner Sicht nicht auf den Lesertyp, sondern auf dessen Datenbank. Ich würde es vorziehen, wenn Sie das Datenbankprodukt des Lesers beschreiben würden, das für den Lesertyp nicht unbedingt relevant ist (z. B. könnte der Lesertyp nur vorwärts, zwischengespeichert usw. sein). So

reader.Database = Databases.Oracle;

In Wirklichkeit passiert dies nie, da sie als Treiber und Vererbungskette implementiert sind, anstatt Aufzählungen zu verwenden, weshalb die obige Zeile nicht natürlich aussieht.

Chris S.
quelle
24
Mein Verständnis ist, dass Flags pluralisiert werden sollten, nicht einfache Aufzählungen.
Serge Wautier
8
In Bezug auf das Verschieben von Enums aus der Klasse muss ich noch verstehen, warum CarState bequemer ist als Car.State. Ich verstehe jedoch nicht die positive Seite, eine Aufzählung aus einer Klasse herauszuholen, wenn diese Aufzählung nur das Verhalten dieser Klasse beschreibt.
Serge Wautier
Ich hätte Nominalphrasen wie FileOptions schreiben sollen, nicht nur Substantive, ich habe die Antwort aktualisiert. Ich nehme an, classname.Enum ist nur eine Präferenz - ich kann keine Beispiele im Framework finden, die ich am Ende kopiere.
Chris S
Obwohl MS sagt, dass der Plural für Flaggen beibehalten werden sollte, mag ich diese Lösungen im Laufe der Zeit immer mehr. Ich benutze es jetzt auch für Aufzählungen. Daher habe ich meine Meinung geändert und Ihre Antwort anstelle der von Filip akzeptiert.
Serge Wautier
1
Ich weiß, dass ich 1 1/2 Jahre zu spät hier bin, public class EngineStatesollte aber public enum EngineStateim Beispiel sein, oder?
David Murdoch
36

Die Definition von "Aus", "Starten" und "Verschieben" würde ich als "Zustand" bezeichnen. Und wenn Sie implizieren, dass Sie einen "Status" verwenden, ist dies Ihr "Status". So!

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

  State state = State.Off;

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

Wenn wir ein anderes Beispiel aus dem angegebenen nehmen, in dem Sie das Wort "Typ" verwenden möchten, wie in diesem Fall:

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

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

}

Sie müssen wirklich sehen, dass es einen Unterschied zwischen Aufzählungen und Aufzählungen gibt, oder? Wenn Sie jedoch ein Framework erstellen oder über Architektur sprechen, müssen Sie sich auf die Ähnlichkeiten konzentrieren. OK, lassen Sie uns sie finden:

Wenn etwas auf einen Status gesetzt ist, wird es als "Dinge" -Status definiert

Beispiel: Der Status des Fahrzeugs befindet sich im Betriebszustand, im Stoppzustand usw.

Was Sie im zweiten Beispiel erreichen möchten, ist Folgendes:

myDataReader.Type = DataReader.Database.OleDb

Sie könnten denken, dass dies gegen das sagt, worüber ich anderen gepredigt habe, dass Sie einem Standard folgen müssen. Aber Sie folgen einem Standard! Der SQL-Fall ist ebenfalls ein spezifischer Fall und benötigt daher eine etwas spezifische Lösung.

Die Aufzählung kann jedoch in Ihrem System.DataRaum wiederverwendet werden, und darum geht es in den Mustern.

Ein weiterer Fall, der mit dem "Typ" betrachtet werden muss, ist "Tier", wobei der Typ die Art definiert.

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

        public Type Species{ get; set; }

    }

Dies folgt einem Muster, Sie müssen das Objekt dafür nicht "kennen" und Sie geben nicht "AnimalType" oder "DataReaderType" an. Sie können die Aufzählungen in dem Namespace Ihrer Wahl wiederverwenden.

Filip Ekberg
quelle
1
Ich glaube, der Name "Status" war nur ein Beispiel. Was ist mit anderen Situationen, in denen Sie sich nicht auf Status / Status verlassen können? ZB eine Typaufzählung ...
Dan C.
Könnten Sie bitte ein Beispielszenario dafür angeben? Ich werde versuchen, meine Antwort auch danach zu erweitern :)
Filip Ekberg
2
@Filip: Das Animal Type-Beispiel zeigt genau, was ich im ersten Kommentar gemeint habe, dh dies ist so ziemlich eine "Umformulierung" der Aufzählung. Die Verwendung von Synonymen für die Aufzählung und den Eigenschaftsnamen macht den Code meiner Meinung nach etwas verwirrend.
Dan C.
1
Ich denke auch, dass "Spezies" nur eine Umformulierung des Typs ist (in diesem Fall für Tiere).
LegendLength
2
Das einfache Umbenennen ist nicht immer so sauber - denken Sie beispielsweise an eine Klasse für eine Spielkarte mit einem Aufzählungsanzug und einem Eigenschaftsanzug - umbenennen in was genau? So oder so ungeschickt.
Annakata
9

Ich denke, das eigentliche Problem hierbei ist, dass der Aufzählungsstatus in Ihrer Klasse gekapselt ist, sodass Car.Statuser sowohl für die Eigenschaft Statusals auch für die Aufzählung nicht eindeutig istStatus

Besser noch, stellen Sie Ihre Aufzählung außerhalb der Klasse:

public enum Status
{
    Off,
    Starting,
    Moving
}

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

AKTUALISIEREN

Aufgrund der Kommentare unten werde ich mein Design oben erklären.

Ich bin einer, der nicht glaubt, dass sich Aufzählungen oder Klassen oder andere Objekte in einer anderen Klasse befinden sollten, es sei denn, es ist innerhalb dieser Klasse völlig privat. Nehmen Sie zum Beispiel das obige Beispiel:

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

Während einige Kommentatoren würden als Status argumentieren hat keine Bedeutung außerhalb des Anwendungsbereichs der Klasse Auto, die Tatsache , dass Sie ein setzen öffentliche Eigenschaft bedeutet , dass es auch andere Teile des Programms sind , die werden , dass ENUM verwenden:

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

Und das ist für mich ein Code-Geruch. Wenn ich diesen Status außerhalb von betrachte Car, kann ich ihn auch außerhalb definieren .

Als solches werde ich es wahrscheinlich einfach umbenennen als:

public enum CarStatus
{...}

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

Wenn diese Aufzählung jedoch innerhalb und nur innerhalb der Fahrzeugklasse verwendet wird, kann ich die Aufzählung dort gut deklarieren.

Jon Limjap
quelle
Das würde den Status global machen. Vielleicht möchten Sie ihn nur in einem bestimmten Bereich haben. "Status" für andere Typen wie "Mensch" hat möglicherweise nicht "Starten". Aber Sie sollten einem Muster folgen.
Filip Ekberg
Nein, er ist genau richtig. Die Aufzählung ist in 99% der Fälle das gleiche Wort, das Sie für die Eigenschaft verwenden möchten. Eine Aufzählung ist nur eine benannte Flagge, so dass es wenig schadet, draußen zu leben (im Gegensatz zu Klassen, die Logik enthalten)
Quibblesome
Jon, das ist genau mein Punkt: Die Statusaufzählung ist nur für das Auto von Bedeutung. Völlig unterschiedliche Arten von Objekten haben völlig unterschiedliche Status
Serge Wautier
Sie werden jedoch in verschiedenen Namespaces sein, also spielt es keine Rolle
Chris S
Die Erklärung, dass es sinnvoll ist, es außerhalb von Car zu betrachten. Aber in meinem Fall habe ich zwei Klassen ORund CR. Beide haben ihre eigenen Zustände, daher ist es keine Option, sie außerhalb ihres eigenen Bereichs zu definieren.
deed02392
4

Ich weiß, dass mein Vorschlag gegen die .NET-Namenskonventionen verstößt, aber ich persönlich stelle Enums mit 'E' und Enum-Flags mit 'F' voran (ähnlich wie wir Interfaces mit 'I' voranstellen). Ich verstehe wirklich nicht, warum dies nicht die Konvention ist. Enums / Flags sind ein Sonderfall wie Interfaces, die ihren Typ niemals ändern. Es macht nicht nur deutlich, was es ist, es ist auch sehr einfach, Intellisense einzugeben, da das Präfix die meisten anderen Typen / Variablen / usw. filtert und Sie diese Namenskonflikte nicht haben.

Und das würde auch ein anderes Problem lösen, bei dem für Beispiele in WPF statische Klassen wie Aufzählungen (z. B. FontWeights) verwendet werden, die vordefinierte Instanzen von Typen haben, aber Sie würden nicht wissen, wenn Sie nicht danach suchen. Wenn ihnen nur 'E' vorangestellt wird, müssen Sie nur ein Zeichen eingeben, um diese speziellen statischen Klassen zu finden.


quelle
4

Hasser der ungarischen Notation und ihrer Varianten sind verdammt. Ich verwende eine Konvention zum Suffixieren von Aufzählungen mit - warte darauf - Enum. Ich habe folglich nie das Problem, das Sie beschreiben, verschwende Zeit damit, mir Gedanken darüber zu machen, wie ich sie nennen soll, und der Code ist lesbar und selbstbeschreibend, um zu booten.

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

  public StatusEnum Status { get; set; }

}
nathanchere
quelle
9
Beachten Sie jedoch, dass in den Microsoft-Konventionen für Namensaufzählungen Folgendes angegeben ist : X Verwenden Sie in Aufzählungstypnamen
DavidRR
2
Denn die Konventionen von Microsoft haben sich bewährt.
Nathanchere
2

Ich würde den Namen der Eigenschaft in "CurrentStatus" ändern. Schnell und einfach :)

TWith2Sugars
quelle
1

Ich schlage vor, dem Typnamen "Option" hinzuzufügen (oder Flag, wenn es Bitflags enthält), dh Typ ist Car.StatusOption und Eigenschaft ist Car.Status.

Im Vergleich zu pluralizing, Namensgebung Dies vermeidet Kollisionen , wenn Sammlungen des Aufzählungstypen zu schaffen, in denen Sie normalerweise die Sammlung pluralize wollen Eigenschaft , nicht der Aufzählungstyp .

Kristian Wedberg
quelle
0

Normalerweise stelle ich die Aufzählungen voran, z. B. CarStatus. Ich nehme an, es hängt alles vom Team ab, mit dem Sie arbeiten (ob es Regeln / Prozesse für solche Dinge gibt) und von der Verwendung der Objekte. Nur meine 2 Cent (:

Kieron
quelle
1
Das würde tatsächlich die Namenskonvention zerstören, wenn MyObjectName vor Status steht.
Filip Ekberg
Der Namensraum aus der Klasse sollte ohnehin ausreichen, um damit
fertig zu