Convención de nomenclatura de C # para la enumeración y la propiedad coincidente

93

A menudo me encuentro implementando una clase que mantiene algún tipo de propiedad de estado propia como una enumeración: tengo una enumeración de estado y una propiedad de estado del tipo de estado. ¿Cómo debo resolver este conflicto de nombres?

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 la enumeración de estado fuera común a diferentes tipos, la pondría fuera de la clase y el problema se resolvería. Pero el estado se aplica solo a Car, por lo que no tiene sentido declarar la enumeración fuera de la clase.

¿Qué convención de nomenclatura usa en este caso?

NB: Esta pregunta se debatió parcialmente en los comentarios de una respuesta a esta pregunta . Como no era la pregunta principal , no tuvo mucha visibilidad.

EDITAR: Filip Ekberg sugiere una excelente solución alternativa de la OMI para el caso específico de 'Estado'. Sin embargo, sería interesante leer sobre soluciones donde el nombre de la enumeración / propiedad es diferente, como en la respuesta de Michael Prewecki .

EDIT2 (mayo de 2010): Mi solución favorita es pluralizar el nombre del tipo de enumeración, como sugirió Chris S. De acuerdo con las pautas de MS, esto debe usarse solo para enumeraciones de banderas. Pero me gusta cada vez más. Ahora también lo uso para enumeraciones regulares.

Serge Wautier
fuente
1
No creo que haya muchas buenas soluciones para esto si desea tener la enumeración anidada dentro de su clase. De hecho, prefiero tener la enumeración separada, entonces no presenta un problema, pero puedo ver su punto filosófico acerca de querer anidarlo.
Craig Shearer

Respuestas:

32

Agregaré mi euro a la discusión, pero probablemente no agregue nada nuevo.

La solución obvia es hacer que Status deje de ser un Enum anidado. La mayoría de las enumeraciones .NET (excepto posiblemente algunas en el espacio de nombres Windows.Forms) no están anidadas y hace que sea molesto de usar para el desarrollador que consume su API, teniendo que prefijar el nombre de la clase.

Una cosa que no se ha mencionado es que las enumeraciones de banderas de acuerdo con las pautas de MSDN deben ser sustantivos en plural. que probablemente ya conozca (el estado es una enumeración simple, por lo que se deben usar sustantivos en singular).

State (enum llamado States) es el vocativo, "Status" es el nominativo de un sustantivo que el inglés, como la mayor parte de nuestro idioma, absorbió del latín. Vocativo es lo que se le da a un sustantivo por su condición y nominativo es el sujeto del verbo.

Entonces, en otras palabras, cuando el automóvil está en movimiento , ese es el verbo: moverse es su estado. Pero el coche no se apaga, su motor sí. Tampoco arranca, el motor sí (probablemente eligió un ejemplo aquí, por lo que esto podría ser irrelevante).

public class Car
{
  VehicleState _vehicleState= VehicleState.Stationary;

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

public enum VehicleState
{
    Stationary, Idle, Moving
}

El estado es un sustantivo tan generalizado, ¿no sería mejor describir a qué estado se refiere? Como hice arriba

El ejemplo de tipo también en mi opinión no se refiere al tipo de lector, sino a su base de datos. Preferiría que estuviera describiendo el producto de la base de datos del lector que no es necesariamente relevante para el tipo de lector (por ejemplo, el tipo de lector puede ser solo hacia adelante, en caché, etc.). Entonces

reader.Database = Databases.Oracle;

En realidad, esto nunca sucede, ya que se implementan como controladores y una cadena de herencia en lugar de usar enumeraciones, por lo que la línea anterior no parece natural.

Chris S
fuente
24
Tengo entendido que las banderas deben estar pluralizadas, no simples enumeraciones.
Serge Wautier
8
con respecto a mover enumeraciones fuera de la clase, todavía tengo que entender por qué CarState es más conveniente que Car.State. Sin embargo, no entiendo el lado positivo de obtener una enumeración de una clase cuando esta enumeración describe el comportamiento de esta clase únicamente.
Serge Wautier
Debería haber escrito frases nominales como FileOptions, no solo sustantivos, he actualizado la respuesta. Supongo que classname.Enum es solo una preferencia: no puedo encontrar ningún ejemplo en el marco que termine copiando.
Chris S
A pesar de que MS dice que se debe mantener el plural para las banderas, con el tiempo, me gustan cada vez más esas soluciones. Ahora también lo uso para enumeraciones. Por eso cambié de opinión y acepté tu respuesta en lugar de la de Filip.
Serge Wautier
1
Sé que llego 1 año y medio tarde aquí, pero public class EngineStatedebería estar public enum EngineStateen el ejemplo, ¿verdad?
David Murdoch
36

La definición de "Apagado", "Comenzando" y "Moviéndose" es lo que yo llamaría un "Estado". Y cuando está insinuando que está utilizando un "Estado", es su "Estado". ¡Entonces!

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

  State state = State.Off;

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

Si tomamos otro ejemplo del indicado en el que le gustaría usar la palabra "Tipo", como en este caso:

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

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

}

Realmente necesitas ver que hay una diferencia entre enumeraciones y enumeraciones, ¿verdad? Pero cuando creas un marco o hablas de arquitectura necesitas enfocarte en las similitudes, bueno, encontrémoslas:

Cuando algo se establece en un estado, se define como el estado de "cosas"

Ejemplo: el estado del automóvil está en estado de funcionamiento, estado detenido, etc.

Lo que quiere lograr en el segundo ejemplo es algo así:

myDataReader.Type = DataReader.Database.OleDb

Podrías pensar que esto dice en contra de lo que he estado predicando a otros, que debes seguir un estándar. ¡Pero estás siguiendo un estándar! El caso Sql también es un caso específico y, por lo tanto, necesita una solución algo específica.

Sin embargo, la enumeración sería reutilizable dentro de su System.Dataespacio, y de eso se tratan los patrones.

Otro caso para mirar con el "Tipo" es "Animal" donde Tipo define la Especie.

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

        public Type Species{ get; set; }

    }

Esto sigue un patrón, no necesita "conocer" específicamente el Objeto para esto y no está especificando "AnimalType" o "DataReaderType", puede reutilizar las enumeraciones en el espacio de nombres que elija.

Filip Ekberg
fuente
1
Creo que el nombre de "Estado" fue solo un ejemplo. ¿Qué pasa con otras situaciones, cuando no puede confiar en el estado / estado? Por ejemplo, una enumeración de tipo ...
Dan C.
¿Podría proporcionar un escenario de ejemplo para eso? Intentaré ampliar mi respuesta de acuerdo con eso también :)
Filip Ekberg
2
@Filip: la muestra Animal Type señala exactamente lo que quise decir en el primer comentario, es decir, esto es prácticamente una "nueva redacción" de la enumeración. El uso de sinónimos para la enumeración y el nombre de la propiedad hace que el código sea algo confuso, creo.
Dan C.
1
También creo que 'especie' es solo una nueva redacción del tipo (para animales en este caso).
LegendLength
2
El simple cambio de nombre no siempre es tan limpio; piense en una clase para un naipe, por ejemplo, con un traje enum y un traje de propiedad. ¿Cambiar el nombre a qué exactamente? Torpe de cualquier manera.
Annakata
9

Creo que el verdadero problema aquí es que el estado de la enumeración está encapsulado dentro de su clase, por lo que Car.Statuses ambiguo tanto para la propiedadStatus como para la enumeraciónStatus

Mejor aún, ponga su enumeración fuera de la clase:

public enum Status
{
    Off,
    Starting,
    Moving
}

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

ACTUALIZAR

Debido a los comentarios a continuación, explicaré mi diseño arriba.

Soy de los que no cree que las enumeraciones o clases o cualquier otro objeto deba residir dentro de otra clase, a menos que sea totalmente privado dentro de esa clase. Tome el ejemplo anterior, por ejemplo:

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

Si bien algunos comentaristas argumentarían que Status no tiene ningún significado fuera del alcance de la clase Car, el hecho de que esté configurando una propiedad pública significa que hay otras partes del programa que usarán esa enumeración:

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

Y eso para mí es un olor a código. Si voy a mirar ese estado fuera de Car, también podría definirlo fuera .

Como tal, probablemente lo renombraré como:

public enum CarStatus
{...}

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

Sin embargo, si esa enumeración se usará dentro y solo dentro de la clase de automóvil, entonces estoy de acuerdo con declarar la enumeración allí.

Jon Limjap
fuente
Eso haría que Status sea global, es posible que desee tenerlo solo dentro de un área específica. Es posible que "Estado" para otros tipos, como "Humanos", no tenga "Iniciando". Pero debes seguir un patrón.
Filip Ekberg
No, él es perfecto. La enumeración es en el 99% de los casos la misma palabra que desea usar para la propiedad. Una enumeración es sólo un indicador llamado por lo que hace poco daño en los que viven fuera (a diferencia de clases que contienen la lógica)
Quibblesome
Jon, este es precisamente mi punto: la enumeración Status es significativa solo con respecto a Car. Tipos de objetos totalmente diferentes tendrán estados totalmente diferentes
Serge Wautier
Sin embargo, estarán en diferentes espacios de nombres, por lo que no importará
Chris S
La explicación de que querer verlo fuera de Car tiene sentido. Pero en mi caso tengo dos clases,OR y CR. Ambos tienen su propio conjunto de estados, por lo que no es una opción definirlos fuera de su propio ámbito.
deed02392
4

Sé que mi sugerencia va en contra de las convenciones de nomenclatura de .NET, pero personalmente prefijo las enumeraciones con 'E' y las banderas de enumeración con 'F' (similar a cómo prefijamos las interfaces con 'I'). Realmente no entiendo por qué esta no es la convención. Enums / Flags son un caso especial como las interfaces que nunca cambiarán su tipo. No solo deja en claro qué es, es muy fácil escribir en intellisense ya que el prefijo filtrará la mayoría de los otros tipos / variables / etc., y no tendrá estos conflictos de nombres.

Y eso también resolvería otro problema en el que, para ejemplos en WPF, usan clases estáticas como enumeraciones (por ejemplo, FontWeights) que tienen instancias predefinidas de tipos, pero no lo sabría si no lo busca. Si simplemente les pusieran el prefijo 'E', todo lo que tendría que hacer es escribir un carácter para encontrar estas clases estáticas especiales.


fuente
4

Malditos sean los que odian la notación húngara y sus variantes. Utilizo una convención de sufijos de enumeraciones con - espera - Enum. En consecuencia, nunca tengo el problema que usted describe, pierdo el tiempo preocupándome por cómo llamarlos y el código es legible y autodescriptivo para arrancar.

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

  public StatusEnum Status { get; set; }

}
Nathanchere
fuente
9
Sin embargo, tenga en cuenta que las convenciones de Microsoft para enumeraciones de nombres dicen: X NO use un sufijo "Enum" en los nombres de tipos de enumeración.
DavidRR
2
Porque se ha demostrado que las convenciones de Microsoft resisten el paso del tiempo.
nathanchere
2

Cambiaría el nombre de la propiedad a algo como "CurrentStatus". Rápido y fácil :)

TWith2Sugars
fuente
1

Sugiero agregar "Opción" al nombre del tipo (o Bandera si contiene indicadores de bits), es decir, el tipo es Car.StatusOption y la propiedad es Car.Status.

En comparación con la pluralización, esto evita las colisiones de nombres al crear colecciones del tipo enum, donde normalmente desearía pluralizar la propiedad de la colección , no el tipo enum .

Kristian Wedberg
fuente
0

Normalmente prefijo las enumeraciones, por ejemplo, CarStatus. Supongo que todo depende del equipo con el que esté trabajando (si tienen reglas / procesos para ese tipo de cosas) y el uso de objetos. Solo mis 2 centavos (:

Kieron
fuente
1
Eso en realidad acabaría con la convención de nomenclatura que tiene MyObjectName delante de Status.
Filip Ekberg
el espacio de nombres de la clase debería ser suficiente para lidiar con esto de todos modos
annakata