Ordre des éléments dans les classes: champs, propriétés, constructeurs, méthodes


637

Existe-t-il une directive officielle C # pour l'ordre des éléments en termes de structure de classe?

Est-ce que ça va:

  • Champs publics
  • Champs privés
  • Propriétés
  • Constructeurs
  • Méthodes
    ?

Je suis curieux de savoir s'il existe une règle stricte et rapide sur l'ordre des articles? Je suis un peu partout. Je veux m'en tenir à une norme particulière pour pouvoir le faire partout.

Le vrai problème est que mes propriétés plus complexes finissent par ressembler beaucoup à des méthodes et elles se sentent déplacées au sommet avant le constructeur.

Des conseils / suggestions?


7
En fait, pour répondre à la vraie question, non, il n'y a pas de ligne directrice officielle. StyleCop implémente les directives développées pour une utilisation au sein d'un groupe particulier dans Microsoft. Ce n'est pas une directive officielle et peut même ne pas être uniforme parmi les groupes de Microsoft.
John Saunders

2
Une astuce simple consiste à voir les métadonnées d'une classe complexe dans .net (F12 dans VS). Vous saurez comment il est commandé au moins pour les membres publicet protected.
nawfal

19
Cette question n'est pas fondée sur l'opinion, car elle demande s'il existe une directive officielle. Soit il y a une directive, soit il n'y en a pas!
Simon MᶜKenzie

2
@nawfal Je me rends compte que c'est un vieux commentaire, j'aime le truc que vous avez mentionné, mais il vaut la peine de mentionner qu'il ne sera pas affiché privateni les internalmembres (je crois). Belle façon de voir publicet protectedpourtant. Nous pouvons voir la source des classes .NET Framework, ici referencesource.microsoft.com aussi
Adam Plocher

Réponses:


951

Selon la documentation des règles StyleCop, la commande est la suivante.

Au sein d'une classe, d'une structure ou d'une interface: (SA1201 et SA1203)

  • Champs constants
  • Des champs
  • Constructeurs
  • Finaliseurs (destructeurs)
  • Délégués
  • Événements
  • Enums
  • Interfaces ( implémentations d'interfaces )
  • Propriétés
  • Indexeurs
  • Les méthodes
  • Structs
  • Des classes

Au sein de chacun de ces groupes, commandez par accès: (SA1202)

  • Publique
  • interne
  • intérieur protégé
  • protégé
  • privé

Dans chacun des groupes d'accès, triez par ordre statique, puis non statique: (SA1204)

  • statique
  • non statique

Dans chacun des groupes de champs statiques / non statiques, triez en lecture seule, puis en lecture seule: (SA1214 et SA1215)

  • lecture seulement
  • non en lecture seule

Une liste déroulée comporte 130 lignes, donc je ne la déroulerai pas ici. La partie méthodes déroulée est:

  • méthodes statiques publiques
  • méthodes publiques
  • méthodes statiques internes
  • méthodes internes
  • méthodes statiques internes protégées
  • méthodes internes protégées
  • méthodes statiques protégées
  • méthodes protégées
  • méthodes statiques privées
  • méthodes privées

La documentation note que si l'ordre prescrit ne convient pas - par exemple, plusieurs interfaces sont mises en œuvre et que les méthodes et propriétés d'interface doivent être regroupées -, utilisez ensuite une classe partielle pour regrouper les méthodes et propriétés associées.


31
Je tiens à vous remercier d'avoir pris l'effort dans ce post. J'essaie de faire des trucs StyleCop un standard (même si c'est juste pour être cohérent et faciliter la recherche de choses) et c'est précieux.
Kenny Mann

47
Personnellement, je trouve ennuyeux le classement des méthodes statiques. Je peux voir l'argument pour les méthodes publiques statiques venir en premier, mais je veux normalement des méthodes statiques privées après les membres. Ce sont des services publics après tout.
Jonathan Wright

18
J'ai aimé le conseil de classe partielle
Keith Sirmons

10
Juste une note sur les classes partielles. Étant donné que pendant la compilation, tous les partiels sont compilés en un seul type, j'essayerais toujours de garantir une bonne raison de créer cette surcharge supplémentaire. La raison principale des classes partielles est d'étendre le code source généré automatiquement ou lorsque vous travaillez sur de grands projets pour permettre à plusieurs développeurs de travailler sur la même classe mais sur des fichiers séparés.
Non

4
@ FrançoisWahl La surcharge est-elle associée au compilateur combinant des classes partielles en un seul type de cette taille?
dav_i

38

Plutôt que de regrouper par visibilité ou par type d'élément (champ, propriété, méthode, etc.), que diriez-vous de regrouper par fonctionnalité?


3
Si "trier" en utilisant les recommandations StyleCop c'est une sorte de fonctionnalité. Il y a une bonne raison pour laquelle certaines méthodes sont publiques et d'autres privées. Le code est vraiment mieux lisible: si j'ouvre le fichier .cs d'une classe, je vois immédiatement les méthodes publiques qui sont "plus importantes" que les méthodes privées (pour le gars qui utilise cette classe)
hfrmobile

75
Si vous avez tellement de méthodes, de propriétés, etc. dans votre classe que vous devez les regrouper par section, c'est peut-être un signe que la classe en fait trop?
Ryan Lundy

10
Même si la classe est petite, ne serait-il pas logique de regrouper les méthodes publiques avec leurs méthodes privées correspondantes qui ne sont appelées que par cette méthode publique?
Markus Meyer

11
+1 si la méthode publique Foo () appelle un InternalFoo protégé / privé (), alors cette deuxième méthode vaut mieux être juste sous DoFoo () dans la source, pas quelque part plus bas parmi les autres méthodes protégées / privées.
Anders Forsgren

60
le regroupement par fonctionnalité est appelé une classe
MrDosu

26

C'est une question ancienne mais toujours très pertinente, alors j'ajouterai ceci: Quelle est la première chose que vous recherchez lorsque vous ouvrez un fichier de classe que vous avez peut-être lu ou non auparavant? Des champs? Propriétés? J'ai réalisé par expérience que je vais presque toujours à la recherche des constructeurs, car la chose la plus fondamentale à comprendre est la façon dont cet objet est construit.

Par conséquent, j'ai commencé à placer les constructeurs en premier dans les fichiers de classe, et le résultat a été psychologiquement très positif. La recommandation standard de mettre les constructeurs après un tas d'autres choses semble dissonante.

La fonctionnalité de constructeur principal à venir dans C # 6 fournit la preuve que la place naturelle pour un constructeur est tout en haut d'une classe - en fait, les constructeurs principaux sont spécifiés avant même l'accolade ouverte.

C'est drôle à quel point une réorganisation comme celle-ci fait la différence. Cela me rappelle comment les usinginstructions étaient auparavant ordonnées - avec les espaces de noms System en premier. La commande "Organiser les utilisations" de Visual Studio a utilisé cet ordre. Maintenant, les usings sont simplement classés par ordre alphabétique, sans traitement spécial pour les espaces de noms System. Le résultat semble plus simple et plus propre.


2
L'initialisation / construction de classe est, à mon avis, compliquée. Les champs sont initialisés avant l'exécution des constructeurs explicites, donc pour aller plus loin dans votre argument de mettre essentiellement les membres dans l'ordre dans lequel ils sont utilisés / créés, les champs initialisés le seraient avant les constructeurs explicitement déclarés. Les champs statiques initialisés et les constructeurs statiques le rendent encore plus intéressant.
David Culp

1
En fait, l'ordre dans lequel ils ont tendance à être recherchés par les humains, la notion de programmation littéraire selon laquelle le code devrait d'abord être lisible par les humains.
lumineux

1
Notez que les constructeurs principaux ont été supprimés des plans pour C # 6: stackoverflow.com/a/26915809/5085211
fuglede

4
9 fois sur 10, je recherche l'interface publique, c'est pourquoi j'ai mis tous les membres du public en premier, suivi des internes, puis des protégés et enfin des particuliers.
Matt Davis

15

Je ne connais pas de langage ou de norme industrielle, mais j'ai tendance à mettre les choses dans cet ordre avec chaque section enveloppée dans une # région:

à l'aide d'instructions

Espace de noms

Classe

Membres privés

Propriétés publiques

Constructeurs

Méthodes publiques

Méthodes privées


C'est exactement comme ça que je le fais aussi. Sauf entre classe et membres privés, j'ai des constantes publiques et des énumérations, etc.
deegee

Oui, je préfère conserver les propriétés publiques après des méthodes privées. D'autres préfèrent placer le constructeur avant les propriétés publiques ... mais dans ma tête, je préfère avoir des valeurs / constructeurs / comportements, dans cet ordre. Ensuite, "valeurs" est divisé en constantes / privateMembers / propriétés et ainsi. Habituellement, je n'utilise pas de régions, à l'exception de certains grands modèles de vue ... eh bien, les modèles de vue WPF sont un peu spéciaux, et, dans ce cas, je place généralement les champs privés de support juste avant chaque propriété publique. Dans ce cas, l'ensemble du champ privé plus le membre public est la même unité
zameb

15

Je recommanderais d'utiliser les normes de codage d' IDesign ou celles répertoriées sur le site Web de Brad Abram . Ce sont les deux meilleurs que j'ai trouvés.

Brad dirait ...

Les membres des classes doivent être classés par ordre alphabétique et regroupés en sections (champs, constructeurs, propriétés, événements, méthodes, implémentations d'interface privée, types imbriqués)


3
Ce lien semble simplement mener à la page d'accueil IDesign ces jours-ci. Il semble que les normes de codage soient cachées derrière un lien de téléchargement envoyé par e-mail ces jours-ci #justsaying
Liam

Les lignes directrices devraient avoir une justification. La raison en est: 1. pour que vous compreniez, 2. pour que vous puissiez appliquer un jugement sur des cas limites, subtils, ambigus, imprévus ou conflictuels, 3. pour que vous puissiez vous adapter lorsque les conditions changent et que certaines directives ne s'appliquent plus.
Pablo H

6

Comme mentionné précédemment, il n'y a rien dans le langage C # qui dicte la disposition, j'utilise personnellement les régions et je fais quelque chose comme ça pour une classe moyenne.

public class myClass
{
#region Private Members

#endregion
#region Public Properties

#endregion

#region Constructors

#endregion
#region Public Methods

#endregion
}

Cela a du sens pour moi de toute façon


19
Voici pour dire (juste pour information) que stylecop recommande de ne pas utiliser les régions (SA1124 DoNotUseRegions)
Gerwald


1
@zwcloud Bien sûr, dans un fichier de 5538 lignes, les régions sont nécessaires, mais cela ne signifie pas que vous devez utiliser les régions dans les fichiers normaux.
Ghost4Man

1
@Gerwald: Je pense que StyleCop est réservé aux personnes utilisant StyleCop. C'est l'une des nombreuses normes
zameb

1
@zameb: Je dirais que les règles StyleCop sont l'une des directives de codage les plus courantes pour C #. Lors du codage dans toutes les langues, j'essaie toujours de trouver l'ensemble de directives de codage le plus courant et de les suivre.
Gerwald

5

De StyleCop

champs privés, champs publics, constructeurs, propriétés, méthodes publiques, méthodes privées

Comme StyleCop fait partie du processus de construction MS, vous pouvez voir cela comme une norme de facto


Intéressant. Utilisez-vous régulièrement StyleCop?
mmcdole

Pour un projet, oui, car il est utilisé de temps en temps pour certains travaux sous contrat avec les États membres. C'est un sourire
Blowdart

1
L'utilisation de StyleCop pendant longtemps et si l'utilisation de ces recommandations rend le code vraiment plus lisible: Si j'ouvre le fichier .cs d'une classe, je vois immédiatement les méthodes publiques qui sont "plus importantes" que les méthodes privées. Les publics sont les "interfaces" de la classe ce qu'elle offre et ce qui peut être testé (préférez TDD et Test-First)
hfrmobile

1
Selon StyleCop, les champs publics doivent précéder les
Michael Freidgeim

1
Que voulez-vous dire par "StyleCop fait partie du processus de construction MS"? Microsoft utilise-t-il StyleCop pour tout son code?
Rico Suter

5

Habituellement, j'essaie de suivre le modèle suivant:

  • membres statiques (ont généralement un autre contexte, doivent être thread-safe, etc.)
  • membres d'instance

Chaque partie (statique et instance) se compose des types de membres suivants:

  • opérateurs (sont toujours statiques)
  • champs (initialisés avant les constructeurs)
  • constructeurs
  • destructeur ( est une tradition de suivre les constructeurs )
  • Propriétés
  • les méthodes
  • événements

Ensuite, les membres sont triés par visibilité (du moins au plus visible):

  • privé
  • interne
  • interne protégé
  • protégé
  • Publique

L'ordre n'est pas un dogme: les classes simples sont plus faciles à lire, cependant, les classes plus complexes nécessitent un groupement spécifique au contexte.


5

Ma préférence est de commander par type, puis de diminuer la visibilité comme suit

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

Je sais que cela viole Style Cop et si quelqu'un peut me donner une bonne raison pour laquelle je devrais placer les détails d'implémentation d'un type avant son interface, je suis prêt à changer. À l'heure actuelle, j'ai une forte préférence pour la priorité des députés.

Remarque: je n'utilise pas de champs publics ou protégés.


3
D'accord. Je me demande vraiment si la notion de donner la priorité aux députés n'est pas une rémanence des jours C où les variables devaient être déclarées en premier. Je veux presque toujours voir l'interface publique en premier, pas les internes de classe.
Matt Davis

1
Cela a en fait beaucoup de sens. Je parie que c'est une relance de C.
Aluan Haddad

Certains des plus gros pièges peuvent être les propriétés de l'OMI. Quand il y a une logique sur un getter / setter que vous ignoriez, cela va être beaucoup plus susceptible de mordre que les effets secondaires dans les méthodes (que vous attendez naturellement qu'ils soient) Par conséquent, je préfère les propriétés à côté de leurs champs en haut , donc quand je regarde une classe pour la première fois, je vois le problème. Où comme quand je lis une méthode, je navigue normalement / saute immédiatement à la méthode de toute façon
Ryan The Leach


3

les seules directives de codage que j'ai vues suggérées pour cela sont de mettre les champs en haut de la définition de classe.

j'ai tendance à mettre les constructeurs à côté.

mon commentaire général serait que vous devriez vous en tenir à une classe par fichier et si la classe est assez grande pour que l'organisation des propriétés par rapport aux méthodes soit un gros problème, quelle est la taille de la classe et devriez-vous la refactoriser quand même? représente-t-il de multiples préoccupations?


3
et une fois que vous avez besoin de régions ... vous avez perdu.
Hamish Smith

3

Je préfère mettre les champs privés en haut avec le ou les constructeurs, puis mettre les bits d'interface publique après cela, puis les bits d'interface privée.

De plus, si la définition de votre classe est suffisamment longue pour que la commande d'articles soit importante, c'est probablement une odeur de code indiquant que votre classe est trop volumineuse et complexe et que vous devriez refactoriser.


3

Je le garde aussi simple que possible (pour moi au moins)

Énumérations
Déclarations
Constructeurs
Remplace les
méthodes
Propriétés
Gestionnaire d'événements


2

Il n'y a certainement rien dans le langage qui l'impose en aucune façon. J'ai tendance à grouper les choses par visibilité (publique, puis protégée, puis privée) et à utiliser #regions pour grouper fonctionnellement les choses liées, qu'il s'agisse d'une propriété, d'une méthode ou autre. Les méthodes de construction (qu'il s'agisse de cteurs réels ou de fonctions statiques d'usine) sont généralement en tête de liste, car elles sont la première chose que les clients doivent savoir.


J'utilise également des régions pour séparer par visibilité, et avoir une disposition de code Regionerate me garde honnête. rauchy.net/regionerate
Point-virgule oublié

Je ne vois pas de problème avec l'utilisation de #regions, mais je trouve souvent que dès que je suis tenté de m'installer dans une région, cela m'incite à envisager de diviser mes classes.
mikecamimo

2

Je sais que c'est vieux mais ma commande est la suivante:

dans l'ordre public, protégé, privé, interne, abstrait

  • Constantes
  • Variables statiques
  • Des champs
  • Événements
  • Constructeur (s)
  • Les méthodes
  • Propriétés
  • Délégués

J'aime aussi écrire des propriétés comme celle-ci (au lieu de l'approche raccourcie)

// 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; }
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.