Порядок элементов в классах: поля, свойства, конструкторы, методы

Есть ли официальное руководство C# по порядку элементов с точки зрения структуры классов?

Идет ли это:

  • Публичные поля
  • Частные поля
  • Характеристики
  • Конструкторы
  • Методы ?

Мне любопытно, есть ли жесткое правило о порядке элементов? Я как бы повсюду. Я хочу придерживаться определенного стандарта, чтобы делать это везде.

Настоящая проблема в том, что мои более сложные свойства в конечном итоге очень похожи на методы и кажутся неуместными наверху перед конструктором.

Любые советы / предложения?

На самом деле, чтобы ответить на актуальный вопрос, нет, официального руководства нет. StyleCop реализует рекомендации, разработанные для использования внутри одной конкретной группы в Microsoft. Это не официальная директива, и она может даже не быть единообразной для разных групп в Microsoft.

John Saunders 29.04.2013 02:15

Один простой трюк - увидеть метаданные некоторого сложного класса в .net (F12 в VS). Вы узнаете, как это устроено, по крайней мере, для членов public и protected.

nawfal 21.05.2013 00:04

Этот вопрос не основан на мнении, поскольку он спрашивает, есть ли официальное руководство. Либо инструкция есть, либо нет!

Simon MᶜKenzie 03.06.2014 08:24

@nawfal Я понимаю, что это старый комментарий, мне нравится упомянутый вами трюк, но стоит упомянуть, что он не показывает членов private или internal (я думаю). Однако хороший способ увидеть public и protected. Мы видим источник классов .NET Framework, здесь тоже linksource.microsoft.com

Adam Plocher 02.03.2020 20:43
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
686
4
242 822
15
Перейти к ответу Данный вопрос помечен как решенный

Ответы 15

В языке определенно нет ничего, что могло бы его принудить. Я склонен группировать вещи по видимости (общедоступные, затем защищенные, затем частные) и использую #regions для функциональной группировки связанных вещей, независимо от того, является ли это свойством, методом или чем-то еще. Методы построения (будь то фактические ctors или статические фабричные функции) обычно находятся вверху, поскольку они - первое, о чем должны знать клиенты.

Я также использую регионы для разделения по видимости, и наличие макета кода Regionerate делает меня честным. rauchy.net/regionerate

Forgotten Semicolon 30.09.2008 00:28

Я не вижу проблем с использованием #regions, однако я часто обнаруживаю, что, как только у меня возникает соблазн добавить регион, мне предлагается подумать о разделении моих классов.

mikecamimo 22.02.2018 05:08

единственные рекомендации по кодированию, которые я видел для этого, - это поместить поля в начало определения класса.

Следующими я обычно помещаю конструкторы.

Мой общий комментарий заключался бы в том, что вам следует придерживаться одного класса для каждого файла, и если класс достаточно велик, чтобы организация свойств по сравнению с методами была большой проблемой, насколько велик класс и нужно ли вам все равно проводить его рефакторинг? представляет ли это несколько проблем?

а раз вам нужны регионы ... вы проиграли.

Hamish Smith 30.10.2012 03:14

Ближайшее, что вы, вероятно, найдете, - это «Рекомендации по проектированию, управляемый код и .NET Framework» (http://blogs.msdn.com/brada/articles/361363.aspx) Брэда Абрамса.

Здесь описаны многие стандарты. Соответствующий раздел я думаю 2.8.

Я не знаю языка или отраслевого стандарта, но я стараюсь располагать вещи в таком порядке, каждый раздел заключен в #region:

с использованием заявлений

Пространство имен

Класс

Частные участники

Общедоступные свойства

Конструкторы

Публичные методы

Частные методы

Я тоже так делаю. За исключением случаев между классом и частными членами, у меня есть какие-либо общедоступные константы, перечисления и т. д.

deegee 08.01.2016 02:11

Да, я предпочитаю оставлять общедоступные свойства после частных методов. Другие люди предпочитают помещать конструктор перед общедоступными свойствами ... но в моей голове я предпочитаю иметь значения / конструкторы / поведения в таком порядке. Затем «значения» делятся на константы / privateMembers / свойства и так далее. Обычно я не использую регионы, за исключением некоторых больших моделей представления ... ну, модели представления WPF особенные, и в этом случае я обычно помещаю поддерживающие частные поля непосредственно перед каждым общедоступным свойством. В этом случае набор частного поля плюс открытый член - это одна и та же единица.

zameb 07.12.2018 23:10

Если ваш класс достаточно большой, и ему нужны регионы для поиска предметов, это довольно сильный индикатор того, что ваш класс слишком велик.

ssmith 15.02.2021 01:34

Я бы рекомендовал использовать стандарты кодирования из IDesign или те, которые перечислены в Сайт Брэда Абрама. Это лучшие два, которые я нашел.

Брэд сказал бы ...

Classes member should be alphabetized, and grouped into sections (Fields, Constructors, Properties, Events, Methods, Private interface implementations, Nested types)

В наши дни эта ссылка ведет только на домашнюю страницу IDesign. Похоже, что в наши дни стандарты кодирования скрыты за отправляемой по электронной почте ссылкой для скачивания #justsaying

Liam 13.05.2015 12:56

У руководящих принципов должно быть обоснование. Обоснование этого: 1. чтобы вы понимали, 2. чтобы вы могли выносить суждение в пограничных, скрытых, неоднозначных, непредвиденных или конфликтующих случаях, 3. чтобы вы могли приспособиться, когда условия меняются, а некоторые рекомендации больше не применяются.

Pablo H 18.02.2019 15:35

Как насчет группировки по функциональности вместо группировки по видимости или по типу элемента (поле, свойство, метод и т. д.)?

Если «сортировка» по рекомендациям StyleCop - это своего рода функционал. Есть веская причина, по которой одни методы являются общедоступными, а другие - частными. Код действительно лучше читается: открывая файл .cs класса, я сразу вижу общедоступные методы, которые «более важны», чем частные (для парня, который использует этот класс)

hfrmobile 14.08.2012 12:12

Если в вашем классе так много методов, свойств и т. д., Что вам нужно сгруппировать их по разделам, возможно, это признак того, что класс делает слишком много?

Ryan Lundy 14.08.2012 17:24

Даже если класс невелик, не имеет ли смысла группировать общедоступные методы с соответствующими им частными методами, которые вызываются только этим общедоступным методом?

Markus Meyer 15.02.2013 14:06

+1, если публичный метод Foo () вызывает защищенный / частный InternalFoo (), тогда этот второй метод лучше быть прямо под DoFoo () в источнике, а не где-то ниже среди других защищенных / частных методов.

Anders Forsgren 29.04.2013 01:49

группировка по функциональности называется классом

MrDosu 11.07.2013 15:11

+1. Если под другой функциональностью вы подразумеваете «бизнес-функциональность», то я не согласен. Однако, если это «служебный функционал», то, возможно, это имеет смысл. Скажем, например, ваш класс имеет одно бизнес-значение, но это IEnumerable, IDisposable и INotifyPropertyChanged, реализация каждого интерфейса требует немного больше, чем один метод, тогда, возможно, имеет смысл сгруппировать их вместе, даже если весь класс способствует одному и тому же бизнесу функциональность.

Rui Craveiro 17.02.2014 23:37

От StyleCop

частные поля, общедоступные поля, конструкторы, свойства, общедоступные методы, частные методы

Поскольку StyleCop является частью процесса сборки MS, вы можете рассматривать это как стандарт де-факто.

Интересно. Вы регулярно пользуетесь StyleCop?

mmcdole 30.09.2008 01:09

Для одного проекта да, потому что он время от времени используется для некоторых контрактных работ с MS. Очень напрягает ухмылка

blowdart 30.09.2008 01:27

Использование StyleCop в течение длительного времени и при использовании этих рекомендаций делает код действительно более читаемым: открывая файл .cs класса, я сразу вижу общедоступные методы, которые «более важны», чем частные. Публикации - это «интерфейсы» класса, которые он предлагает и что может быть протестировано (предпочитайте TDD и Test-First).

hfrmobile 14.08.2012 12:11

Согласно StyleCop публичные поля должны располагаться перед приватными полями stylecop.com/docs/SA1202.html

Michael Freidgeim 29.04.2013 01:16

Что вы имеете в виду под «StyleCop - это часть процесса сборки MS»? Microsoft использует StyleCop для всего своего кода?

Rico Suter 25.09.2014 18:50

Как упоминалось ранее, в языке C# нет ничего, что диктует макет, я лично использую регионы, и я делаю что-то подобное для среднего класса.

public class myClass
{
#region Private Members

#endregion
#region Public Properties

#endregion

#region Constructors

#endregion
#region Public Methods

#endregion
}

В любом случае это имеет смысл для меня

Здесь нужно сказать (только для информации), что stylecop не рекомендует использовать регионы (SA1124 DoNotUseRegions)

Gerwald 19.01.2012 19:43

@zwcloud Конечно, в файле с 5538 строками регионы необходимы, но это не значит, что вы должны использовать регионы в обычных файлах.

Ghost4Man 27.05.2018 13:49

@Gerwald: Я думаю, что StyleCop предназначен только для людей, использующих StyleCop. Это один из многих стандартов

zameb 07.12.2018 23:16

@zameb: Я бы сказал, что правила StyleCop - одно из самых распространенных правил кодирования для C#. При кодировании на любых языках я всегда стараюсь найти наиболее распространенный набор рекомендаций по кодированию и следовать им.

Gerwald 14.12.2018 18:48

Я предпочитаю размещать частные поля вверху вместе с конструктором (ами), затем помещать биты общедоступного интерфейса после этого, а затем биты частного интерфейса.

Кроме того, если определение вашего класса достаточно длинное, чтобы порядок элементов имел большое значение, вероятно, запах кода указывает на то, что ваш класс слишком громоздкий и сложный, и вам следует провести рефакторинг.

Обычно я стараюсь следовать следующей схеме:

  • статические члены (обычно имеют другой контекст, должны быть потокобезопасными и т. д.)
  • члены экземпляра

Каждая часть (статическая и экземплярная) состоит из следующих типов членов:

  • операторы (всегда статичны)
  • поля (инициализируются перед конструкторами)
  • конструкторы
  • деструктор (традиция следовать за конструкторами)
  • характеристики
  • методы
  • События

Затем участники сортируются по видимости (от менее заметной к более заметной):

  • частный
  • внутренний
  • внутренняя защита
  • защищенный
  • общественный

Порядок не является догмой: простые классы легче читать, однако более сложные классы нуждаются в группировке в зависимости от контекста.

Я стараюсь сделать это как можно проще (по крайней мере, для меня)

Перечисления Объявления Конструкторы Переопределения
Методы Свойства Обработчик событий

Ответ принят как подходящий

Согласно Документация по правилам StyleCop порядок следующий.

Внутри класса, структуры или интерфейса: (SA1201 и SA1203)

  • Постоянные поля
  • Поля
  • Конструкторы
  • Финализаторы (деструкторы)
  • Делегаты
  • События
  • Перечисления
  • Интерфейсы (реализации интерфейса)
  • Характеристики
  • Индексаторы
  • Методы
  • Структуры
  • Классы

В каждой из этих групп упорядочить по доступу: (SA1202)

  • общественный
  • внутренний
  • защищенный внутренний
  • защищенный
  • частный

В каждой из групп доступа в порядке статического, затем нестатического: (SA1204)

  • статический
  • нестатический

В каждой из статических / нестатических групп полей упорядочивайте только чтение, затем не только чтение: (SA1214 и SA1215)

  • только чтение
  • не только для чтения

Развернутый список состоит из 130 строк, поэтому я не буду его здесь разворачивать. Развернутая часть методов:

  • общедоступные статические методы
  • публичные методы
  • внутренние статические методы
  • внутренние методы
  • защищенные внутренние статические методы
  • защищенные внутренние методы
  • защищенные статические методы
  • защищенные методы
  • частные статические методы
  • частные методы

В документации отмечается, что если предписанный порядок не подходит - скажем, реализуется несколько интерфейсов, а методы и свойства интерфейса должны быть сгруппированы вместе, - тогда используйте частичный класс, чтобы сгруппировать связанные методы и свойства вместе.

Я хотел бы поблагодарить вас за то, что вы приложили усилия для написания этой статьи. Я пытаюсь сделать StyleCop стандартом (даже если просто для того, чтобы упростить поиск), и это ценно.

Kenny Mann 24.03.2009 22:49

Лично меня раздражает порядок статических методов. Я вижу аргумент в пользу того, что сначала идут статические общедоступные методы, но обычно мне нужны частные статические методы после членов. В конце концов, это коммунальные службы.

Jonathan Wright 26.03.2009 03:56

Спасибо, это немного помогло мне с моими последними изменениями в моей надстройке помощи StyleCop (sweeper.codeplex.com). Единственное, что я хотел бы отметить дополнительно, это то, что многие типы элементов не поддерживают статику.

McAden 07.09.2011 10:16

Мне понравился совет частичного класса

Keith Sirmons 20.01.2012 00:41

Просто примечание о частичных классах. Учитывая, что во время компиляции все частичные файлы компилируются в один тип, я всегда старался найти вескую причину для создания этих дополнительных накладных расходов. Основная причина использования частичных классов заключается в расширении автоматического создания исходного кода или при работе над большими проектами, чтобы позволить нескольким разработчикам работать с одним и тем же классом, но с отдельными файлами.

Nope 30.04.2012 17:36

@ FrançoisWahl Так ли велики накладные расходы, связанные с компилятором, объединяющим частичные классы в один тип?

dav_i 04.09.2012 13:14

@dav_i: Если накладные расходы заметны или нет, я действительно не знаю, я не проводил никаких тестов производительности на этом. Скорее всего, это незаметно, но, как правило, я стараюсь создавать только частичные файлы при расширении автоматически сгенерированного кода. Вот также хороший ресурс по частям: 4guysfromrolla.com/articles/071509-1.aspx

Nope 04.09.2012 13:23

@ FrançoisWahl Я полагаю, накладные расходы не так уж и плохи, и преимущества удобочитаемости сэкономят вам больше времени в долгосрочной перспективе :) Интересная статья - я не понимал, что существуют частичные методы!

dav_i 04.09.2012 13:31

Другой момент. Каков стандартный способ группировки в public static fields и т. д. - то есть идет по имени поля или по типу, а затем по имени поля? (например, public int a; public bool b; или public bool b; public int a;?

dav_i 04.09.2012 13:34

Единственное, чего я избегаю, - это разделение полей и связанных с ними свойств доступа. Я рассматриваю такие пары как одно поле.

LightStriker 06.01.2015 17:31

Что означает «Интерфейсы» (между перечислениями и свойствами)? Явные реализации интерфейса или ...?

Maxim Kamalov 06.02.2015 03:57

@ FrançoisWahl - Я часто использую частичные классы в своих больших проектах. Я не заметил абсолютно никаких накладных расходов на компиляцию, а самый большой проект составляет около 600 тыс. Строк. Мне не нравится иметь класс с десятками средств доступа и методов. В больших классах я разделю его на отдельные файлы .cs, по одному для каждого метода. Я считаю, что это также упрощает просмотр обозревателя решений и мгновенный визуальный просмотр всех доступных методов в классе вместо того, чтобы открывать файл и сканировать его.

deegee 08.01.2016 02:17

К вашему сведению, ваша ссылка на правила полицейского стиля не работает.

rory.ap 03.06.2016 21:02

Правила упорядочивания StyleCop можно найти в github.com/Visual-Stylecop/Visual-StyleCop/wiki/Ordering-Rul‌ es.

Theophilus 12.07.2016 23:33

С «новыми» автоматическими свойствами C# мне не очень нравятся поля -> конструкторы -> порядок свойств, я чувствую, что свойства должны идти после полей, если их всего 1 или 2. Трудно сохранить «один или два» как определенное правило, поэтому я продолжаю следовать этому ...

Alexander Derck 23.08.2016 12:53

Кто-нибудь знает, доступно ли это в виде файла макета Resharper?

Jack Ukleja 21.03.2017 10:04

Я бы сгруппировал вместе все статические элементы, кроме экземпляров. Очень вероятно, что вы работаете с несколькими элементами, статическими элементами и, статическими полями, поэтому имеет смысл держать их рядом. С другой стороны, когда вы ищете статический член, вы очень хорошо знаете, что он статический, поэтому поиск в другом месте не должен вызывать особого беспокойства. Я не нашел преимуществ в чередовании статических элементов с динамическими; то есть третий критерий заказа должен быть первым, на мой взгляд.

AgostinoX 15.01.2020 18:47

Style Cop использует порядок, который имел смысл в старые времена C, но не более того. В объектно-ориентированных клиентах вашего класса следует использовать общедоступный интерфейс вашего класса (и, если необходимо, это общедоступные свойства). Поместите их вверху, чтобы облегчить пользователям вашего класса. Если вы используете контейнер DI, ваш конструктор (-ы) также не очень актуален для ваших читателей, он может идти со всем остальным, что вам нужно только при работе над внутренней работой класса.

k.c. 27.05.2020 12:11

Хотя это превосходно отвечает на первую половину вопроса, я хотел бы добавить примечание ко второй части: если ваши свойства сложны и похожи на методы, тогда свойство должно вызывать метод. Я все время вижу одно и то же в отношении событий. Фактически выполняйте работу в частных методах и классах. Если код достаточно мелкий, порядок StyleCop становится более понятным.

gremlin 01.07.2020 20:32

А как насчет автоматически реализуемых свойств? Должны ли они придерживаться полей или других свойств?

underthevoid 27.12.2020 03:15

Это старый, но все еще очень актуальный вопрос, поэтому я добавлю следующее: на что вы в первую очередь обращаете внимание, открывая файл класса, который вы, возможно, читали раньше, а могли и не читали? Поля? Характеристики? На собственном опыте я понял, что почти всегда я иду на охоту за конструкторами, потому что самое основное, что нужно понять, - это то, как этот объект построен.

Поэтому я начал ставить конструкторы на первое место в файлах классов, и психологически результат оказался очень положительным. Стандартная рекомендация ставить конструкторы после множества других вещей кажется диссонирующей.

Предстоящая функция основного конструктора в C# 6 свидетельствует о том, что естественное место для конструктора находится на самом верху класса - на самом деле основные конструкторы указываются даже перед открывающей фигурной скобкой.

Забавно, насколько сильно меняет такое переупорядочивание. Это напоминает мне о том, как раньше были упорядочены операторы using - сначала с пространством имен System. Команда Visual Studio «Организовать использование» использовала этот порядок. Теперь using просто упорядочены в алфавитном порядке, без особой обработки пространств имен System. Результат кажется проще и чище.

Инициализация / построение класса, на мой взгляд, запутана. Поля инициализируются до запуска явных конструкторов, поэтому, продолжая свой аргумент о размещении элементов в том порядке, в котором они используются / создаются, инициализированные поля будут перед явно объявленными конструкторами. Инициализированные статические поля и статические конструкторы делают его еще более интересным.

David Culp 29.05.2015 18:22

На самом деле, в том порядке, в котором их обычно ищут люди, представление литературного программирования о том, что код должен сначала быть читаемым людьми.

bright 19.10.2015 07:56

Обратите внимание, что основные конструкторы были удалены из планов для C# 6: stackoverflow.com/a/26915809/5085211

fuglede 11.10.2016 17:10

В 9 случаях из 10 я ищу общедоступный интерфейс, поэтому сначала ставлю все общедоступные члены, затем внутренние, затем защищенные и, наконец, частные члены.

Matt Davis 15.03.2017 21:25

@DavidCulp: я думаю, он не хотел сказать, что хочет видеть, в каком порядке инициализируется класс, он не компилятор, а человек. Он хочет «понять, как устроен этот объект», и это понятно. Ему может понадобиться этот класс, и он хочет увидеть зависимости и то, что ему действительно нужно.

Tim Schmelter 10.03.2021 11:42

Я предпочитаю упорядочивать по типу, а затем уменьшать видимость следующим образом

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

Я знаю, что это нарушает Style Cop, и если кто-то может дать мне вескую причину, почему я должен поместить детали реализации типа перед его интерфейсом, я готов изменить. В настоящее время я сильно предпочитаю ставить частных участников в последнюю очередь.

Примечание: я не использую публичные или защищенные поля.

Согласовано. Мне действительно интересно, не является ли идея размещения частных членов в первую очередь пережитком дней C, когда переменные должны были быть объявлены в первую очередь. Я почти всегда хочу сначала увидеть общедоступный интерфейс, а не внутреннее устройство класса.

Matt Davis 15.03.2017 21:28

На самом деле в этом есть большой смысл. Бьюсь об заклад, это пережиток C.

Aluan Haddad 15.03.2017 21:30

Некоторые из самых больших ошибок могут быть свойства IMO. Когда в геттере / сеттере есть логика, о которой вы не знали, у нее гораздо больше шансов укусить, чем побочные эффекты в методах (которые, естественно, вы ожидаете от них) .Поэтому я предпочитаю свойства рядом с их полями вверху. , поэтому, когда я впервые смотрю на класс, я вижу, что проблема на высоте. Когда, когда я читаю метод, я обычно сразу перехожу к методу в любом случае

Ryan The Leach 24.04.2018 08:14

Я знаю, что это старый, но мой порядок следующий:

в порядке публичного, защищенного, частного, внутреннего, абстрактного

  • Константы
  • Статические переменные
  • Поля
  • События
  • Конструктор (ы)
  • Методы
  • Характеристики
  • Делегаты

Мне также нравится записывать такие свойства (вместо сокращенного подхода)

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

Другие вопросы по теме