Kolejność przedmiotów w klasach: pola, właściwości, konstruktory, metody

637

Czy istnieją oficjalne wytyczne C # dotyczące kolejności przedmiotów pod względem struktury klas?

Czy to idzie:

  • Pola publiczne
  • Pola prywatne
  • Nieruchomości
  • Konstruktory
  • Metody
    ?

Jestem ciekawy, czy istnieje twarda i szybka zasada dotycząca kolejności przedmiotów? Jestem trochę w tym miejscu. Chcę trzymać się określonego standardu, aby móc to zrobić wszędzie.

Prawdziwy problem polega na tym, że moje bardziej złożone właściwości wyglądają bardzo podobnie do metod i czują się nie na miejscu na szczycie przed konstruktorem.

Wszelkie wskazówki / sugestie?

mmcdole
źródło
7
W rzeczywistości, aby odpowiedzieć na rzeczywiste pytanie, nie, nie ma oficjalnych wytycznych. StyleCop implementuje wytyczne opracowane do użytku w ramach jednej konkretnej grupy w Microsoft. To nie jest oficjalna wytyczna i może nawet nie być jednolita wśród grup w Microsoft.
John Saunders
2
Prostą sztuczką jest zobaczenie metadanych złożonej klasy w .net (F12 w VS). Dowiesz się, jak to jest uporządkowane przynajmniej dla członków publici protected.
nawfal
19
To pytanie nie jest oparte na opiniach, ponieważ pyta, czy istnieje oficjalna wytyczna. Albo jest wytyczna, albo jej nie ma!
Simon MᶜKenzie
2
@nawfal Zdaję sobie sprawę, że jest to stary komentarz, podoba mi się sztuczka, o której wspomniałeś, ale warto wspomnieć, że nie pokaże privateani internalczłonków (wierzę). Miły sposób na zobaczenie publici protectedjednak. Widzimy źródło klas .NET Framework, tutaj referencesource.microsoft.com zbyt
Adam Plocher

Odpowiedzi:

949

Zgodnie z dokumentacją reguł StyleCop kolejność jest następująca.

W obrębie klasy, struktury lub interfejsu: (SA1201 i SA1203)

  • Stałe pola
  • Pola
  • Konstruktory
  • Finalizatory (Destructors)
  • Delegaci
  • Wydarzenia
  • Enums
  • Interfejsy ( implementacje interfejsu )
  • Nieruchomości
  • Indeksujący
  • Metody
  • Struktury
  • Klasy

W ramach każdej z tych grup uporządkuj według dostępu: (SA1202)

  • publiczny
  • wewnętrzny
  • chronione wewnętrznie
  • chroniony
  • prywatny

W obrębie każdej grupy dostępu uporządkuj według statycznych, a następnie niestatycznych: (SA1204)

  • statyczny
  • niestatyczna

W obrębie każdej statycznej / niestatycznej grupy pól, uporządkuj tylko do odczytu, a następnie nie do odczytu: (SA1214 i SA1215)

  • tylko czytać
  • nie tylko do odczytu

Rozwinięta lista ma 130 linii, więc nie rozwinę jej tutaj. Metoda rozwinięta część to:

  • publiczne metody statyczne
  • metody publiczne
  • wewnętrzne metody statyczne
  • metody wewnętrzne
  • chronione wewnętrzne metody statyczne
  • chronione metody wewnętrzne
  • chronione metody statyczne
  • metody chronione
  • prywatne metody statyczne
  • metody prywatne

Dokumentacja zauważa, że ​​jeśli zalecana kolejność nie jest odpowiednia - powiedzmy, że wdrażanych jest wiele interfejsów, a metody interfejsu i właściwości powinny być pogrupowane razem - użyj częściowej klasy, aby pogrupować powiązane metody i właściwości.

Jonathan Wright
źródło
31
Chciałbym podziękować za podjęcie wysiłku w tym poście. Staram się, aby StyleCop był standardem (nawet jeśli chcę zachować spójność i ułatwić znajdowanie rzeczy), a to jest cenne.
Kenny Mann
47
Osobiście uważam, że porządkowanie metod statycznych jest denerwujące. Widzę argument za statycznymi metodami publicznymi na pierwszym miejscu, ale zwykle chcę prywatnych metod statycznych po członkach. W końcu są narzędziami.
Jonathan Wright
18
Podobał mi się
typ
10
Tylko uwaga na temat częściowych zajęć. Biorąc pod uwagę, że w czasie kompilacji wszystkie części są kompilowane w jeden typ, zawsze staram się zapewnić dobry powód do utworzenia tego dodatkowego obciążenia. Głównym powodem klas częściowych jest rozszerzenie automatycznego generowania kodu źródłowego lub podczas pracy nad dużymi projektami, aby umożliwić wielu programistom pracę na tej samej klasie, ale osobnych plikach.
Nie
4
@ FrançoisWahl Czy koszty ogólne związane z kompilatorem łączą klasy częściowe w jeden tak duży typ?
dav_i
38

Zamiast grupować według widoczności lub według rodzaju elementu (pole, właściwość, metoda itp.), A co z grupowaniem według funkcjonalności?

Ryan Lundy
źródło
3
Jeśli „sortowanie” przy użyciu zaleceń StyleCop jest rodzajem funkcjonalności. Istnieje dobry powód, dla którego niektóre metody są publiczne, a inne są prywatne. Kod jest naprawdę lepiej czytelny: otwierając plik .cs klasy, od razu widzę metody publiczne, które są „ważniejsze” niż prywatne (dla faceta, który korzysta z tej klasy)
hfrmobile
75
Jeśli masz w swojej klasie tak wiele metod, właściwości itp., Że musisz je pogrupować według sekcji, może to oznacza, że ​​klasa robi za dużo?
Ryan Lundy,
10
Nawet jeśli klasa jest mała, czy nie ma sensu grupować metod publicznych za pomocą odpowiadających im metod prywatnych, które są wywoływane tylko przez tę metodę publiczną?
Markus Meyer
11
+1, jeśli publiczna metoda Foo () wywołuje chroniony / prywatny InternalFoo (), wtedy ta druga metoda powinna znajdować się bezpośrednio pod DoFoo () w źródle, a nie gdzieś poniżej innych chronionych / prywatnych metod.
Anders Forsgren,
60
grupowanie według funkcji nazywa się klasą
MrDosu,
26

To jest stare, ale wciąż bardzo aktualne pytanie, więc dodam to: Jakiej pierwszej rzeczy szukasz, kiedy otworzysz plik zajęć, który mógłeś przeczytać wcześniej? Pola? Nieruchomości? Z doświadczenia zdałem sobie sprawę, że prawie niezmiennie idę polować na konstruktorów, ponieważ najbardziej podstawową rzeczą do zrozumienia jest to, jak ten obiekt jest zbudowany.

Dlatego zacząłem umieszczać konstruktory na pierwszym miejscu w plikach klas, a wynik był psychologicznie bardzo pozytywny. Standardowa rekomendacja umieszczania konstruktorów po szeregu innych rzeczy wydaje się dysonansowa.

Nadchodząca funkcja głównego konstruktora w C # 6 dostarcza dowodów, że naturalne miejsce dla konstruktora znajduje się na samym szczycie klasy - w rzeczywistości podstawowe konstruktory są określone nawet przed otwartym nawiasem klamrowym.

To zabawne, jak wielką różnicę sprawia takie zamawianie. Przypomina mi to, jak usingkiedyś zamawiano instrukcje - najpierw z przestrzeniami nazw Systemu. Polecenie „Organize Usings” programu Visual Studio używało tej kolejności. Teraz usings są tylko uporządkowane alfabetycznie, bez specjalnego traktowania przestrzeni nazw Systemu. Rezultat jest po prostu prostszy i czystszy.

jasny
źródło
2
Inicjalizacja / konstrukcja klasy jest, moim zdaniem, skomplikowana. Pola są inicjowane przed uruchomieniem jawnych konstruktorów, więc idąc dalej za argumentem polegającym na zasadniczo umieszczeniu elementów w kolejności, w której są używane / tworzone, zainicjowane pola byłyby przed jawnie zadeklarowanymi konstruktorami. Zainicjowane pola statyczne i konstruktory statyczne sprawiają, że jest to jeszcze bardziej interesujące.
David Culp
1
W rzeczywistości kolejność, w jakiej ludzie ich szukają, pojęcie programowania literackiego, że kod powinien być najpierw czytelny dla ludzi.
jasny
1
Zauważ, że pierwotni konstruktorzy zostali usunięci z planów dotyczących C # 6: stackoverflow.com/a/26915809/5085211
fuglede
4
9 razy na 10 szukam interfejsu publicznego, dlatego stawiam wszystkich członków publicznych na pierwszym miejscu, następnie wewnętrznych, następnie chronionych, a na końcu prywatnych.
Matt Davis,
15

Nie znam standardu językowego ani branżowego, ale zwykle układam rzeczy w tej kolejności, a każda sekcja jest zawinięta w #region:

za pomocą instrukcji

Przestrzeń nazw

Klasa

Członkowie prywatni

Nieruchomości publiczne

Konstruktory

Metody publiczne

Metody prywatne

Wayne
źródło
Właśnie tak to robię. Z wyjątkiem członków klasowych i prywatnych, mam jakieś stałe publiczne i wyliczenia itp.
deegee
Tak, wolę zachować właściwości publiczne po metodach prywatnych. Inni ludzie wolą stawiać konstruktora przed nieruchomościami publicznymi ... ale w mojej głowie wolę mieć wartości / konstruktory / zachowania w tej kolejności. Następnie „wartości” dzielone są na stałe / privateMembers / properties i tak dalej. Zwykle nie używam regionów, z wyjątkiem niektórych dużych modeli widoków ... no cóż, modele widoków WPF są swego rodzaju specjalnymi, i w tym przypadku zwykle umieszczam prywatne pola tuż przed każdą własnością publiczną. W tym przypadku zestaw pola prywatnego i członka publicznego jest tą samą jednostką
zameb
15

Poleciłbym stosowanie standardów kodowania IDesign lub wymienionych na stronie internetowej Brada Abrama . To są najlepsze dwa, jakie znalazłem.

Brad powiedziałby ...

Członek klas powinien być alfabetycznie i pogrupowany w sekcje (pola, konstruktory, właściwości, zdarzenia, metody, implementacje prywatnego interfejsu, typy zagnieżdżone)

Dwór Eliasza
źródło
3
Wydaje się, że ten link prowadzi obecnie do strony głównej IDesign. Wygląda na to, że standardy kodowania są obecnie ukryte za linkiem do pobrania w wiadomości e-mail #justsaying
Liam
Wytyczne powinny mieć uzasadnienie. Uzasadnieniem tego jest: 1. abyś zrozumiał, 2. abyś mógł osądzać sprawy graniczne, subtelne, dwuznaczne, nieprzewidziane lub sprzeczne, 3. abyś mógł dostosować się, gdy zmieniają się warunki i niektóre wytyczne nie mają już zastosowania.
Pablo H
6

Jak wspomniano wcześniej, w języku C # nie ma nic, co dyktuje układ, osobiście używam regionów i robię coś takiego dla przeciętnej klasy.

public class myClass
{
#region Private Members

#endregion
#region Public Properties

#endregion

#region Constructors

#endregion
#region Public Methods

#endregion
}

W każdym razie ma to dla mnie sens

Sprzedawcy Mitchel
źródło
19
Można powiedzieć (tylko dla informacji), że stylecop nie zaleca używania regionów (SA1124 DoNotUseRegions)
Gerwald
1
@zwcloud Oczywiście, w pliku z 5538 liniami regiony są konieczne, ale to nie znaczy, że powinieneś używać regionów w normalnych plikach.
Ghost4Man
1
@Gerwald: Myślę, że StyleCop jest tylko dla osób używających StyleCop. Jest to jeden z wielu standardów
zameb,
1
@zameb: Powiedziałbym, że reguły StyleCop są jedną z najpopularniejszych wskazówek dla C #. Podczas kodowania w dowolnym języku zawsze staram się znaleźć najczęstszy zestaw wytycznych dotyczących kodowania i postępować zgodnie z nimi.
Gerwald
5

From StyleCop

pola prywatne, pola publiczne, konstruktory, właściwości, metody publiczne, metody prywatne

Ponieważ StyleCop jest częścią procesu kompilacji MS, można to uznać za de facto standard

strzałka do dmuchawki
źródło
Ciekawy. Czy regularnie używasz StyleCop?
mmcdole
W przypadku jednego projektu tak, ponieważ przyzwyczaja się on do niektórych prac kontraktowych MS od czasu do czasu. To bardzo denerwujący uśmiech
blowdart
1
Używanie StyleCop przez długi czas i stosowanie tych zaleceń sprawia, że ​​kod jest naprawdę lepiej czytelny: jeśli otwieram plik .cs klasy, natychmiast widzę metody publiczne, które są „ważniejsze” niż prywatne. Publiczność to „interfejsy” klasy, co oferuje i co można przetestować (wolą TDD i Test-First)
hfrmobile
1
Według StyleCop pola publiczne powinny przejść przed polami prywatnymi stylecop.com/docs/SA1202.html
Michael Freidgeim
1
Co rozumiesz przez „StyleCop jest częścią procesu kompilacji MS”? Czy Microsoft używa StyleCop do całego swojego kodu?
Rico Suter,
5

Zwykle staram się postępować według następnego wzoru:

  • elementy statyczne (zwykle mają inny kontekst, muszą być bezpieczne dla wątków itp.)
  • członkowie instancji

Każda część (statyczna i instancja) składa się z następujących typów elementów:

  • operatory (zawsze są statyczne)
  • pola (zainicjowane przed konstruktorami)
  • konstruktory
  • destruktor ( jest tradycją podążania za konstruktorami )
  • nieruchomości
  • metody
  • wydarzenia

Następnie członkowie są sortowani według widoczności (od mniej do bardziej widocznych):

  • prywatny
  • wewnętrzny
  • wewnętrzny chroniony
  • chroniony
  • publiczny

Kolejność nie jest dogmatem: proste klasy są łatwiejsze do odczytania, jednak bardziej złożone klasy wymagają grupowania specyficznego dla kontekstu.

Michael Damatov
źródło
5

Preferuję sortowanie według rodzaju, a następnie zmniejszanie widoczności w następujący sposób

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

Wiem, że narusza to Style Copa i jeśli ktoś może podać mi dobry powód, dla którego powinienem umieścić szczegóły implementacji typu przed jego interfejsem, jestem gotów to zmienić. Obecnie zdecydowanie wolę umieszczać członków prywatnych na końcu.

Uwaga: nie używam pól publicznych ani chronionych.

Aluan Haddad
źródło
3
Zgoda. Naprawdę zastanawiam się, czy koncepcja stawiania członków prywatnych na pierwszym miejscu nie jest reliktem z dni C, w których zmienne musiały zostać zadeklarowane jako pierwsze. Prawie zawsze chcę najpierw zobaczyć interfejs publiczny, a nie wewnętrzne elementy klasy.
Matt Davis,
1
To naprawdę ma sens. Założę się, że jest to relacja z C.
Aluan Haddad
Niektóre z największych gotcha mogą mieć właściwości IMO. Kiedy logika na temat gettera / setera jest nieświadoma, będzie znacznie bardziej prawdopodobne, że ugryzie to skutki uboczne metod (których naturalnie się spodziewasz) Dlatego wolę właściwości obok ich pól u góry , więc kiedy patrzę na zajęcia po raz pierwszy, widzę gotcha na górze. Gdzie, jak, kiedy czytam metodę, ja normalnie nawigacja / przeskoczyć od razu do sposobu w każdym razie
Ryan ługowania
4

Najbliżej można znaleźć „Wytyczne projektowe, kod zarządzany i .NET Framework” ( http://blogs.msdn.com/brada/articles/361363.aspx ) autorstwa Brada Abramsa

Wiele standardów jest tu opisanych. Odpowiednia sekcja to 2.8.

Rory Becker
źródło
3

jedyne wskazówki dotyczące kodowania, jakie widziałem w tym zakresie, to umieszczenie pól na początku definicji klasy.

zwykle stawiam konstruktorów w następnej kolejności.

mój ogólny komentarz byłby taki, że powinieneś trzymać się jednej klasy na plik, a jeśli klasa jest na tyle duża, że ​​organizacja właściwości w stosunku do metod jest dużym problemem, jak duża jest klasa i czy powinieneś ją zrefaktoryzować? czy to dotyczy wielu problemów?

Hamish Smith
źródło
3
a kiedy potrzebujesz regionów ... przegrałeś.
Hamish Smith,
3

Wolę umieszczać pola prywatne u góry razem z konstruktorami, potem umieszczać bity interfejsu publicznego, a potem bity interfejsu prywatnego.

Ponadto, jeśli twoja definicja klasy jest wystarczająco długa, aby porządkowanie przedmiotów miało duże znaczenie, prawdopodobnie jest to zapach kodu wskazujący, że twoja klasa jest zbyt obszerna i złożona, i powinieneś zreformować.

Klin
źródło
3

Utrzymuję to tak proste, jak to możliwe (przynajmniej dla mnie)

Wyliczenia
Deklaracje
Konstruktory
Zastępują
Metody
Właściwości
Moduł obsługi zdarzeń

Poklepać
źródło
2

Z pewnością w języku nie ma niczego, co by to wymuszało. Staram się grupować rzeczy według widoczności (publiczne, następnie chronione, a następnie prywatne) i używam #regions do grupowania powiązanych funkcji funkcjonalnie, niezależnie od tego, czy jest to właściwość, metoda, czy cokolwiek innego. Metody konstrukcyjne (czy to rzeczywiste liczniki, czy statyczne funkcje fabryczne) są zwykle na pierwszym miejscu, ponieważ są pierwszą rzeczą, o której klienci powinni wiedzieć.

Jeff Kotula
źródło
Regionów używam również do oddzielania przez widoczność, a posiadanie układu kodu Regionerate zapewnia mi uczciwość. rauchy.net/regionerate
Forgotten
Nie widzę problemu z używaniem #regionów, jednak często zdarza mi się, że gdy tylko mam ochotę umieścić region, to skłania mnie do rozważenia podziału moich klas.
mikecamimo
2

Wiem, że to stare, ale moje zamówienie wygląda następująco:

w kolejności publicznej, chronionej, prywatnej, wewnętrznej, abstrakcyjnej

  • Stałe
  • Zmienne statyczne
  • Pola
  • Wydarzenia
  • Konstruktor (y)
  • Metody
  • Nieruchomości
  • Delegaci

Lubię też pisać takie właściwości (zamiast skróconego podejścia)

// 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; }
}

źródło