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

638

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

Это идет:

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

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

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

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

mmcdole
источник
7
Собственно, чтобы ответить на актуальный вопрос, нет, официального руководства нет. StyleCop реализует рекомендации, разработанные для использования в одной определенной группе в Microsoft. Это не официальное руководство, и может даже не быть единообразным среди групп в Microsoft.
Джон Сондерс
2
Один простой прием - увидеть метаданные какого-то сложного класса в .net (F12 в VS). Вы узнаете , как его заказали , по крайней мере для publicи protectedчленов.
Nawfal
19
Этот вопрос не основан на мнении, поскольку он спрашивает, есть ли официальное руководство. Либо есть руководство, либо его нет!
Саймон Мекензи
2
@nawfal Я понимаю, что это старый комментарий, мне нравится трюк, который вы упомянули, но стоит упомянуть, что он не будет отображаться privateили internalучастников (я полагаю). Хороший способ увидеть publicи protected, однако. Мы можем видеть источник .NET Framework классов, здесь referencesource.microsoft.com тоже
Адам Plocher

Ответы:

952

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

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

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

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

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

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

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

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

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

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

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

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

Джонатан Райт
источник
31
Я хотел бы поблагодарить вас за усилия в этом посте. Я пытаюсь сделать материал StyleCop стандартным (даже если просто быть последовательным и облегчить поиск вещей), и это ценно.
Кенни Манн
47
Лично меня раздражает порядок статических методов. Сначала я вижу аргумент для статических открытых методов, но обычно я хочу частные статические методы после членов. Они утилиты в конце концов.
Джонатан Райт
18
Мне понравился частичный совет класса
Кит Сирмонс
10
Просто заметка о частичных занятиях. Учитывая, что во время компиляции все партиалы компилируются в один тип, я всегда стараюсь найти вескую причину для создания этих дополнительных издержек. Основная причина частичных классов заключается в расширении автоматического создания исходного кода или при работе над большими проектами, чтобы позволить нескольким разработчикам работать над одним и тем же классом, но отдельными файлами.
Нет
4
@ FrançoisWahl Связаны ли издержки компилятора с объединением частичных классов в один такой большой тип?
dav_i
38

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

Райан Ланди
источник
3
Если «сортировка» с использованием рекомендаций StyleCop, это своего рода функциональность. Есть веская причина, почему некоторые методы являются публичными, а другие - частными. Код действительно лучше читается: открывая файл .cs класса, я сразу же вижу открытые методы, которые «более важны», чем частные (для парня, использующего этот класс)
hfrmobile
75
Если в вашем классе так много методов, свойств и т. Д., Что вам нужно сгруппировать их по разделам, возможно, это признак того, что класс делает слишком много?
Райан Ланди
10
Даже если класс небольшой, не имеет ли смысла группировать открытые методы с соответствующими частными методами, которые вызываются только этим открытым методом?
Маркус Мейер
11
+1, если открытый метод Foo () вызывает защищенный / закрытый InternalFoo (), тогда этот второй метод лучше находиться прямо под DoFoo () в источнике, а не где-то еще ниже среди других защищенных / частных методов.
Андерс Форсгрен
60
Группировка по функциональности называется классом
MrDosu
26

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

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

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

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

яркий
источник
2
Класс инициализация / конструирование, на мой взгляд, запутан. Поля инициализируются перед запуском явных конструкторов, поэтому, продолжая свой аргумент о существенном размещении членов в порядке их использования / создания, инициализированные поля были бы до явно объявленных конструкторов. Инициализированные статические поля и статические конструкторы делают его еще более интересным.
Дэвид Калп
1
На самом деле, порядок, в котором они обычно ищут люди, понятие литературного программирования, что код должен быть вначале читаемым для людей.
ярко
1
Обратите внимание, что первичные конструкторы были удалены из планов для C # 6: stackoverflow.com/a/26915809/5085211
fuglede
4
9 раз из 10 я ищу общедоступный интерфейс, поэтому сначала я ставлю всех публичных участников, затем внутренних, защищенных и, наконец, частных.
Мэтт Дэвис
15

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

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

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

Учебный класс

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

Публичные свойства

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

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

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

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

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

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

Член классов должен быть в алфавитном порядке и сгруппирован в разделы (поля, конструкторы, свойства, события, методы, реализации частного интерфейса, вложенные типы)

Поместье Илии
источник
3
Похоже, что в эти дни эта ссылка ведет на домашнюю страницу IDesign. Похоже, что стандарты кодирования скрыты за ссылкой для скачивания по электронной почте в эти дни #justsaying
Liam
Руководящие принципы должны иметь обоснование. Основанием для этого является: 1. чтобы вы понимали, 2. чтобы вы могли выносить суждения по пограничным, тонким, неоднозначным, непредвиденным или противоречивым делам, 3. чтобы вы могли скорректировать ситуацию, когда условия меняются, а некоторые рекомендации больше не применяются.
Пабло Х
6

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

public class myClass
{
#region Private Members

#endregion
#region Public Properties

#endregion

#region Constructors

#endregion
#region Public Methods

#endregion
}

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

Митчел Селлерс
источник
19
Здесь нужно сказать (только для информации), что stylecop рекомендует не использовать регионы (SA1124 DoNotUseRegions)
Гервальд
1
@zwcloud Конечно, в файле с 5538 строками регионы необходимы, но это не значит, что вы должны использовать регионы в обычных файлах.
Ghost4Man
1
@Gerwald: я думаю StyleCop только для людей, использующих StyleCop. Это один из многих стандартов
zameb
1
@zameb: Я бы сказал, правила StyleCop - одно из самых распространенных правил кодирования для C #. При кодировании на любых языках я всегда пытаюсь найти наиболее распространенный набор правил кодирования и следовать им.
Гервальд
5

От StyleCop

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

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

blowdart
источник
Интересно. Вы регулярно используете StyleCop?
mmcdole
Для одного проекта - да, потому что он время от времени привыкает к работе по контракту с MS. Это очень раздражает улыбкой
Blowdart
1
Использование StyleCop в течение длительного времени и использование этих рекомендаций делает код действительно более читабельным: открывая файл .cs класса, я сразу же вижу открытые методы, которые «более важны», чем частные. Публичность - это «интерфейсы» класса, которые он предлагает и что можно тестировать (предпочитают TDD и Test-First)
hfrmobile
1
Согласно StyleCop, открытые поля должны быть перед частными полями stylecop.com/docs/SA1202.html
Майкл Фрейдгейм,
1
Что вы подразумеваете под "StyleCop является частью процесса сборки MS"? Microsoft использует StyleCop для всего своего кода?
Рико Сутер
5

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

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

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

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

Затем элементы сортируются по видимости (от меньшего к более заметному):

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

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

Михаил Даматов
источник
5

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

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, и если кто-то может дать мне вескую причину, почему я должен поместить детали реализации типа перед его интерфейсом, я готов изменить его. В настоящее время я сильно предпочитаю ставить частных членов на последнее место.

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

Алуан Хаддад
источник
3
Согласовано. Я действительно задаюсь вопросом, не является ли идея поставить приватных членов первыми в те дни C, когда переменные должны были быть объявлены первыми. Я почти всегда хочу сначала увидеть общедоступный интерфейс, а не внутренние классы.
Мэтт Дэвис
1
Это на самом деле имеет большой смысл. Бьюсь об заклад, это пережиток от C.
Алуан Хаддад
Некоторые из самых больших проблем могут быть свойствами IMO. Когда на получателе / ​​установщике есть логика, о которой вы не знали, это будет гораздо более вероятным, чем побочные эффекты в методах (в которых вы, естественно, ожидаете), поэтому я предпочитаю свойства рядом с их полями вверху Поэтому, когда я впервые смотрю на урок, я вижу, что гоча наверху. Где, когда я читаю метод, я обычно все равно
Райан Лич
4

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

Многие стандарты изложены здесь. Соответствующий раздел - 2,8, я думаю.

Рори Беккер
источник
3

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

Я склонен ставить конструкторов дальше.

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

Хэмиш Смит
источник
3
и когда тебе нужны регионы ... ты проиграл.
Хэмиш Смит
3

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

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

Клин
источник
3

Я держу это настолько просто насколько возможно (для меня по крайней мере)

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

похлопывание
источник
2

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

Джефф Котула
источник
Я также использую регионы для разделения по видимости, а расположение кода Regionerate делает меня честным. rauchy.net/regionerate
забытая
Я не вижу проблем с использованием #regions, однако часто обнаруживаю, что, как только у меня возникает желание добавить регион, это заставляет меня задуматься о разделении своих классов.
mikecamimo
2

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

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

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

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

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

источник