Orden de elementos en clases: campos, propiedades, constructores, métodos

637

¿Existe una directriz oficial de C # para el orden de los elementos en términos de estructura de clases?

Va:

  • Campos publicos
  • Campos privados
  • Propiedades
  • Constructores
  • Métodos
    ?

Tengo curiosidad por saber si hay una regla estricta y rápida sobre el orden de los artículos. Estoy un poco por todas partes. Quiero seguir un estándar particular para poder hacerlo en todas partes.

El verdadero problema es que mis propiedades más complejas terminan pareciéndose mucho a los métodos y se sienten fuera de lugar en la parte superior antes del constructor.

¿Algún consejo / sugerencia?

mmcdole
fuente
77
En realidad, para responder la pregunta real, no, no hay una directriz oficial. StyleCop implementa las pautas desarrolladas para su uso dentro de un grupo particular en Microsoft. Esta no es una directriz oficial, y puede que ni siquiera sea uniforme entre los grupos de Microsoft.
John Saunders
2
Un truco fácil es ver los metadatos de alguna clase compleja en .net (F12 en VS). Llegará a saber cómo se ordena al menos para los miembros publicy protected.
nawfal
19
Esta pregunta no se basa en la opinión, ya que pregunta si hay una directriz oficial. ¡O hay una guía o no la hay!
Simon MᶜKenzie
2
@nawfal Me doy cuenta de que este es un comentario antiguo, me gusta el truco que mencionaste, pero vale la pena mencionar que no se mostrará privateni a los internalmiembros (creo). Buena forma de ver publicy protected, sin embargo. Podemos ver la fuente de las clases de .NET Framework, aquí referenciasource.microsoft.com también
Adam Plocher

Respuestas:

951

De acuerdo con la documentación de las reglas de StyleCop, el orden es el siguiente.

Dentro de una clase, estructura o interfaz: (SA1201 y SA1203)

  • Campos constantes
  • Campos
  • Constructores
  • Finalizadores (Destructores)
  • Delegados
  • Eventos
  • Enumeraciones
  • Interfaces ( implementaciones de interfaz )
  • Propiedades
  • Indexadores
  • Métodos
  • Estructuras
  • Clases

Dentro de cada uno de estos grupos ordenar por acceso: (SA1202)

  • público
  • interno
  • interno protegido
  • protegido
  • privado

Dentro de cada uno de los grupos de acceso, ordenar por estático, luego no estático: (SA1204)

  • estático
  • no estático

Dentro de cada uno de los grupos de campos estáticos / no estáticos, ordene solo lectura, luego no solo lectura: (SA1214 y SA1215)

  • solo lectura
  • no solo lectura

Una lista desenrollada tiene 130 líneas de largo, así que no la desenrollaré aquí. La parte de métodos desenrollada es:

  • métodos estáticos públicos
  • métodos públicos
  • métodos estáticos internos
  • métodos internos
  • métodos estáticos internos protegidos
  • métodos internos protegidos
  • métodos estáticos protegidos
  • métodos protegidos
  • métodos estáticos privados
  • métodos privados

La documentación señala que si el orden prescrito no es adecuado, por ejemplo, se están implementando varias interfaces y los métodos y propiedades de la interfaz se deben agrupar, use una clase parcial para agrupar los métodos y propiedades relacionados.

Jonathan Wright
fuente
31
Me gustaría agradecerle por tomar el esfuerzo en esta publicación. Estoy tratando de hacer que StyleCop sea un estándar (incluso para ser coherente y facilitar la búsqueda de cosas) y esto es valioso.
Kenny Mann
47
Personalmente, me resulta molesto ordenar los métodos estáticos. Puedo ver el argumento de los métodos públicos estáticos primero, pero normalmente quiero métodos estáticos privados después de los miembros. Son utilidades después de todo.
Jonathan Wright
18
Me gustó el consejo parcial de clase
Keith Sirmons
10
Solo una nota sobre clases parciales. Dado que durante el tiempo de compilación todos los parciales se compilan en un solo tipo, siempre trataría de asegurar una buena razón para crear esa sobrecarga adicional. La razón principal para las clases parciales es extender el código fuente de generación automática o cuando se trabaja en proyectos grandes para permitir que varios desarrolladores trabajen en la misma clase pero en archivos separados.
No
44
@ FrançoisWahl ¿La sobrecarga asociada con el compilador combina clases parciales en un solo tipo tan grande?
dav_i
38

En lugar de agrupar por visibilidad o por tipo de elemento (campo, propiedad, método, etc.), ¿qué tal agrupar por funcionalidad?

Ryan Lundy
fuente
3
Si "ordenar" con las recomendaciones de StyleCop es un tipo de funcionalidad. Hay una buena razón por la cual algunos métodos son públicos y otros privados. El código es realmente mejor legible: si abro el archivo .cs de una clase, inmediatamente veo los métodos públicos que son "más importantes" que los privados (para el tipo que está usando esa clase)
hfrmobile
75
Si tiene tantos métodos, propiedades, etc. en su clase que necesita agruparlos por sección, ¿tal vez sea una señal de que la clase está haciendo demasiado?
Ryan Lundy
10
Incluso si la clase es pequeña, ¿no tendría sentido agrupar los métodos públicos con sus correspondientes métodos privados que solo son llamados por este método público?
Markus Meyer
11
+1 si el método público Foo () llama a un InternalFoo protegido / privado (), entonces es mejor que el segundo método esté justo debajo de DoFoo () en la fuente, no en algún lugar más abajo entre otros métodos protegidos / privados.
Anders Forsgren
6060
la agrupación por funcionalidad se llama clase
MrDosu
26

Esta es una pregunta antigua pero aún muy relevante, así que agregaré esto: ¿Qué es lo primero que busca cuando abre un archivo de clase que puede o no haber leído antes? ¿Campos? Propiedades? Me he dado cuenta por experiencia de que casi siempre voy en busca de los constructores, porque lo más básico para entender es cómo se construye este objeto.

Por lo tanto, comencé a poner a los constructores primero en los archivos de clase, y el resultado ha sido psicológicamente muy positivo. La recomendación estándar de colocar a los constructores después de un montón de otras cosas se siente disonante.

La próxima característica de constructor primario en C # 6 proporciona evidencia de que el lugar natural para un constructor está en la parte superior de una clase; de ​​hecho, los constructores primarios se especifican incluso antes del paréntesis abierto.

Es curioso la diferencia que hace un reordenamiento como este. Me recuerda cómo usingsolían ordenarse las declaraciones, primero con los espacios de nombres del Sistema. El comando "Organizar usos" de Visual Studio utilizó este orden. Ahora los usings se ordenan alfabéticamente, sin un tratamiento especial para los espacios de nombres del Sistema. El resultado simplemente se siente más simple y limpio.

brillante
fuente
2
La inicialización / construcción de la clase es, en mi opinión, complicada. Los campos se inicializan antes de que se ejecuten los constructores explícitos, por lo que, más allá de su argumento de colocar esencialmente a los miembros en el orden en que se usan / crean, los campos inicializados serían antes de los constructores declarados explícitamente. Los campos estáticos inicializados y los constructores estáticos lo hacen aún más interesante.
David Culp
1
En realidad, el orden en que tienden a ser buscados por los humanos, la noción de la programación literaria de que el código primero debe ser legible por los humanos.
brillante
1
Tenga en cuenta que los constructores principales se eliminaron de los planes para C # 6: stackoverflow.com/a/26915809/5085211
fuglede
44
9 de cada 10 veces, estoy buscando la interfaz pública, por eso pongo primero a todos los miembros públicos, seguidos por los internos, seguidos por los protegidos y, finalmente, por los privados.
Matt Davis
15

No sé acerca de un idioma o estándar de la industria, pero tiendo a poner las cosas en este orden con cada sección envuelta en una # región:

utilizando declaraciones

Espacio de nombres

Clase

Miembros privados

Propiedades publicas

Constructores

Métodos públicos

Métodos privados

Wayne
fuente
Así es exactamente como lo hago también. Excepto entre miembros de la clase y privados, tengo constantes públicas y enumeraciones, etc.
deegee
Sí, prefiero mantener las propiedades públicas después de los métodos privados. Otras personas prefieren poner el constructor antes que las propiedades públicas ... pero en mi cabeza prefiero tener valores / constructores / comportamientos, en ese orden. Entonces "valores" se divide como constantes / privateMembers / properties y así. Por lo general, no uso regiones, a excepción de algunos modelos de vista grande ... bueno, los modelos de vista WPF son algo especiales, y, en este caso, generalmente coloco los campos privados de respaldo justo antes de cada propiedad pública. En este caso, el conjunto de campo privado más el miembro público es la misma unidad
zameb
15

Recomendaría usar los estándares de codificación de IDesign o los que figuran en el sitio web de Brad Abram . Esos son los dos mejores que he encontrado.

Brad diría ...

El miembro de las clases se debe ordenar alfabéticamente y agrupar en secciones (campos, constructores, propiedades, eventos, métodos, implementaciones de interfaz privada, tipos anidados)

Elijah Manor
fuente
3
Ese enlace parece conducir a la página de inicio de IDesign en estos días. Parece que los estándares de codificación están ocultos detrás de un enlace de descarga enviado por correo electrónico en estos días #justsaying
Liam
Las pautas deben tener fundamentos. La razón de esto es: 1. para que comprenda, 2. para que pueda aplicar el juicio en casos límite, sutiles, ambiguos, imprevistos o conflictivos, 3. para que pueda ajustar cuando las condiciones cambien y alguna directriz ya no se aplique.
Pablo H
6

Como se mencionó anteriormente, no hay nada en el lenguaje C # que dicte el diseño, yo personalmente uso regiones, y hago algo así para una clase promedio.

public class myClass
{
#region Private Members

#endregion
#region Public Properties

#endregion

#region Constructors

#endregion
#region Public Methods

#endregion
}

Tiene sentido para mí de todos modos

Mitchel Sellers
fuente
19
Esto es para decir (solo para información) que stylecop recomienda no usar regiones (SA1124 DoNotUseRegions)
Gerwald
1
@zwcloud Claro, en un archivo con 5538 líneas, las regiones son necesarias, pero eso no significa que debas usar regiones en archivos normales.
Ghost4Man
1
@Gerwald: Creo que StyleCop es solo para personas que usan StyleCop. Es uno de muchos estándares
zameb
1
@zameb: Diría que las reglas de StyleCop son una de las pautas de codificación más comunes para C #. Al codificar en cualquier idioma, siempre trato de encontrar el conjunto más común de pautas de codificación y seguirlas.
Gerwald
5

De StyleCop

campos privados, campos públicos, constructores, propiedades, métodos públicos, métodos privados.

Como StyleCop es parte del proceso de compilación de MS, puede verlo como un estándar de facto

soplar el dardo
fuente
Interesante. ¿Usas StyleCop regularmente?
mmcdole
Para un proyecto sí, porque se utiliza para algunos contratos de MS de vez en cuando. Es una sonrisa
blowdart
1
Usar StyleCop durante mucho tiempo y si usa esas recomendaciones hace que el código sea realmente mejor legible: si abro el archivo .cs de una clase, veo inmediatamente los métodos públicos que son "más importantes" que los privados. Los públicos son las "interfaces" de la clase lo que ofrece y lo que se puede probar (prefiera TDD y Test-First)
hfrmobile
1
Según StyleCop, los campos públicos deben ir antes que los privados. Stylecop.com/docs/SA1202.html
Michael Freidgeim
1
¿Qué quiere decir con "StyleCop es parte del proceso de compilación de MS"? ¿Microsoft utiliza StyleCop para todo su código?
Rico Suter
5

Por lo general, trato de seguir el siguiente patrón:

  • miembros estáticos (generalmente tienen otro contexto, deben ser seguros para subprocesos, etc.)
  • miembros de instancia

Cada parte (estática e instancia) consta de los siguientes tipos de miembros:

  • operadores (son siempre estáticos)
  • campos (inicializados antes de los constructores)
  • constructores
  • destructor ( es una tradición seguir a los constructores )
  • propiedades
  • métodos
  • eventos

Luego, los miembros se ordenan por visibilidad (de menos a más visible):

  • privado
  • interno
  • interno protegido
  • protegido
  • público

El orden no es un dogma: las clases simples son más fáciles de leer, sin embargo, las clases más complejas necesitan agrupación específica de contexto.

Michael Damatov
fuente
5

Mi preferencia es ordenar por tipo y luego disminuir la visibilidad de la siguiente manera

public methods
public events
public properties

protected methods
protected events
protected properties

private methods
private events
private properties
private fields

public delegates
public interfaces
public classes
public structs

protected delegates
protected interfaces
protected classes
protected structs

private delegates
private interfaces
private classes
private structs

Sé que esto viola Style Cop y si alguien me puede dar una buena razón por la que debería colocar los detalles de implementación de un tipo antes de su interfaz, estoy dispuesto a cambiar. En la actualidad, tengo una gran preferencia por poner a los miembros privados en último lugar.

Nota: no utilizo campos públicos o protegidos.

Aluan Haddad
fuente
3
Convenido. Realmente me pregunto si la noción de poner a los miembros privados primero no es un remanente de los días C donde las variables tuvieron que declararse primero. Casi siempre quiero ver primero la interfaz pública, no las partes internas de la clase.
Matt Davis
1
De hecho, eso tiene mucho sentido. Apuesto a que es un remanente de C.
Aluan Haddad
Algunos de los mayores problemas pueden ser las propiedades de la OMI. Cuando hay una lógica en un getter / setter que desconocías, es mucho más probable que muerda que los efectos secundarios en los métodos (que naturalmente esperas que estén) Por lo tanto, prefiero las propiedades junto a sus campos en la parte superior , así que cuando estoy viendo una clase por primera vez, veo que el gotcha está arriba. Donde, como cuando leo un método, normalmente navego / salto inmediatamente al método de todos modos
Ryan The Leach el
3

Las únicas pautas de codificación que he visto sugeridas para esto es colocar los campos en la parte superior de la definición de clase.

tiendo a poner a los constructores a continuación.

mi comentario general sería que debería apegarse a una clase por archivo y si la clase es lo suficientemente grande como para que la organización de propiedades versus métodos sea una gran preocupación, ¿qué tan grande es la clase y debería refactorizarla de todos modos? ¿representa múltiples preocupaciones?

Hamish Smith
fuente
3
y una vez que necesitas regiones ... has perdido.
Hamish Smith
3

Prefiero poner los campos privados en la parte superior junto con los constructores, luego poner los bits de la interfaz pública después de eso, luego los bits de la interfaz privada.

Además, si la definición de su clase es lo suficientemente larga como para que el pedido de artículos sea importante, es probable que sea un olor a código que indique que su clase es demasiado voluminosa y compleja y que debe refactorizar.

Cuña
fuente
3

Lo mantengo lo más simple posible (al menos para mí)

Enumeraciones
Declaraciones
Constructores
Invalida
Métodos
Propiedades
Controlador de eventos

Palmadita
fuente
2

Ciertamente, no hay nada en el lenguaje que lo imponga de ninguna manera. Tiendo a agrupar cosas por visibilidad (pública, luego protegida, luego privada) y uso #regiones para agrupar funcionalmente cosas relacionadas, independientemente de si es una propiedad, método o lo que sea. Los métodos de construcción (ya sean procesadores reales o funciones de fábrica estáticas) generalmente están en la parte superior, ya que son lo primero que los clientes deben saber.

Jeff Kotula
fuente
También uso regiones para separar por visibilidad, y tener un diseño de código Regionerate me mantiene honesto. rauchy.net/regionerate
olvidado
No veo ningún problema con el uso de #regions, sin embargo, a menudo encuentro que tan pronto como me siento tentado a poner en una región, me lleva a considerar dividir mis clases.
mikecamimo
2

Sé que esto es viejo pero mi orden es la siguiente:

en orden de público, protegido, privado, interno, abstracto

  • Constantes
  • Variables Estáticas
  • Campos
  • Eventos
  • Constructor (es)
  • Métodos
  • Propiedades
  • Delegados

También me gusta escribir propiedades como esta (en lugar del enfoque abreviado)

// Some where in the fields section
private int someVariable;

// I also refrain from
// declaring variables outside of the constructor

// and some where in the properties section I do
public int SomeVariable
{
    get { return someVariable; }
    set { someVariable = value; }
}

fuente