Есть ли официальное руководство C# по порядку элементов с точки зрения структуры классов?
Идет ли это:
Мне любопытно, есть ли жесткое правило о порядке элементов? Я как бы повсюду. Я хочу придерживаться определенного стандарта, чтобы делать это везде.
Настоящая проблема в том, что мои более сложные свойства в конечном итоге очень похожи на методы и кажутся неуместными наверху перед конструктором.
Любые советы / предложения?
Один простой трюк - увидеть метаданные некоторого сложного класса в .net (F12 в VS). Вы узнаете, как это устроено, по крайней мере, для членов public и protected.
Этот вопрос не основан на мнении, поскольку он спрашивает, есть ли официальное руководство. Либо инструкция есть, либо нет!
@nawfal Я понимаю, что это старый комментарий, мне нравится упомянутый вами трюк, но стоит упомянуть, что он не показывает членов private или internal (я думаю). Однако хороший способ увидеть public и protected. Мы видим источник классов .NET Framework, здесь тоже linksource.microsoft.com





В языке определенно нет ничего, что могло бы его принудить. Я склонен группировать вещи по видимости (общедоступные, затем защищенные, затем частные) и использую #regions для функциональной группировки связанных вещей, независимо от того, является ли это свойством, методом или чем-то еще. Методы построения (будь то фактические ctors или статические фабричные функции) обычно находятся вверху, поскольку они - первое, о чем должны знать клиенты.
Я также использую регионы для разделения по видимости, и наличие макета кода Regionerate делает меня честным. rauchy.net/regionerate
Я не вижу проблем с использованием #regions, однако я часто обнаруживаю, что, как только у меня возникает соблазн добавить регион, мне предлагается подумать о разделении моих классов.
единственные рекомендации по кодированию, которые я видел для этого, - это поместить поля в начало определения класса.
Следующими я обычно помещаю конструкторы.
Мой общий комментарий заключался бы в том, что вам следует придерживаться одного класса для каждого файла, и если класс достаточно велик, чтобы организация свойств по сравнению с методами была большой проблемой, насколько велик класс и нужно ли вам все равно проводить его рефакторинг? представляет ли это несколько проблем?
а раз вам нужны регионы ... вы проиграли.
Ближайшее, что вы, вероятно, найдете, - это «Рекомендации по проектированию, управляемый код и .NET Framework» (http://blogs.msdn.com/brada/articles/361363.aspx) Брэда Абрамса.
Здесь описаны многие стандарты. Соответствующий раздел я думаю 2.8.
Я не знаю языка или отраслевого стандарта, но я стараюсь располагать вещи в таком порядке, каждый раздел заключен в #region:
с использованием заявлений
Пространство имен
Класс
Частные участники
Общедоступные свойства
Конструкторы
Публичные методы
Частные методы
Я тоже так делаю. За исключением случаев между классом и частными членами, у меня есть какие-либо общедоступные константы, перечисления и т. д.
Да, я предпочитаю оставлять общедоступные свойства после частных методов. Другие люди предпочитают помещать конструктор перед общедоступными свойствами ... но в моей голове я предпочитаю иметь значения / конструкторы / поведения в таком порядке. Затем «значения» делятся на константы / privateMembers / свойства и так далее. Обычно я не использую регионы, за исключением некоторых больших моделей представления ... ну, модели представления WPF особенные, и в этом случае я обычно помещаю поддерживающие частные поля непосредственно перед каждым общедоступным свойством. В этом случае набор частного поля плюс открытый член - это одна и та же единица.
Если ваш класс достаточно большой, и ему нужны регионы для поиска предметов, это довольно сильный индикатор того, что ваш класс слишком велик.
Я бы рекомендовал использовать стандарты кодирования из IDesign или те, которые перечислены в Сайт Брэда Абрама. Это лучшие два, которые я нашел.
Брэд сказал бы ...
Classes member should be alphabetized, and grouped into sections (Fields, Constructors, Properties, Events, Methods, Private interface implementations, Nested types)
В наши дни эта ссылка ведет только на домашнюю страницу IDesign. Похоже, что в наши дни стандарты кодирования скрыты за отправляемой по электронной почте ссылкой для скачивания #justsaying
У руководящих принципов должно быть обоснование. Обоснование этого: 1. чтобы вы понимали, 2. чтобы вы могли выносить суждение в пограничных, скрытых, неоднозначных, непредвиденных или конфликтующих случаях, 3. чтобы вы могли приспособиться, когда условия меняются, а некоторые рекомендации больше не применяются.
Как насчет группировки по функциональности вместо группировки по видимости или по типу элемента (поле, свойство, метод и т. д.)?
Если «сортировка» по рекомендациям StyleCop - это своего рода функционал. Есть веская причина, по которой одни методы являются общедоступными, а другие - частными. Код действительно лучше читается: открывая файл .cs класса, я сразу вижу общедоступные методы, которые «более важны», чем частные (для парня, который использует этот класс)
Если в вашем классе так много методов, свойств и т. д., Что вам нужно сгруппировать их по разделам, возможно, это признак того, что класс делает слишком много?
Даже если класс невелик, не имеет ли смысла группировать общедоступные методы с соответствующими им частными методами, которые вызываются только этим общедоступным методом?
+1, если публичный метод Foo () вызывает защищенный / частный InternalFoo (), тогда этот второй метод лучше быть прямо под DoFoo () в источнике, а не где-то ниже среди других защищенных / частных методов.
группировка по функциональности называется классом
+1. Если под другой функциональностью вы подразумеваете «бизнес-функциональность», то я не согласен. Однако, если это «служебный функционал», то, возможно, это имеет смысл. Скажем, например, ваш класс имеет одно бизнес-значение, но это IEnumerable, IDisposable и INotifyPropertyChanged, реализация каждого интерфейса требует немного больше, чем один метод, тогда, возможно, имеет смысл сгруппировать их вместе, даже если весь класс способствует одному и тому же бизнесу функциональность.
От StyleCop
частные поля, общедоступные поля, конструкторы, свойства, общедоступные методы, частные методы
Поскольку StyleCop является частью процесса сборки MS, вы можете рассматривать это как стандарт де-факто.
Интересно. Вы регулярно пользуетесь StyleCop?
Для одного проекта да, потому что он время от времени используется для некоторых контрактных работ с MS. Очень напрягает ухмылка
Использование StyleCop в течение длительного времени и при использовании этих рекомендаций делает код действительно более читаемым: открывая файл .cs класса, я сразу вижу общедоступные методы, которые «более важны», чем частные. Публикации - это «интерфейсы» класса, которые он предлагает и что может быть протестировано (предпочитайте TDD и Test-First).
Согласно StyleCop публичные поля должны располагаться перед приватными полями stylecop.com/docs/SA1202.html
Что вы имеете в виду под «StyleCop - это часть процесса сборки MS»? Microsoft использует StyleCop для всего своего кода?
Как упоминалось ранее, в языке C# нет ничего, что диктует макет, я лично использую регионы, и я делаю что-то подобное для среднего класса.
public class myClass
{
#region Private Members
#endregion
#region Public Properties
#endregion
#region Constructors
#endregion
#region Public Methods
#endregion
}
В любом случае это имеет смысл для меня
Здесь нужно сказать (только для информации), что stylecop не рекомендует использовать регионы (SA1124 DoNotUseRegions)
@zwcloud Конечно, в файле с 5538 строками регионы необходимы, но это не значит, что вы должны использовать регионы в обычных файлах.
@Gerwald: Я думаю, что StyleCop предназначен только для людей, использующих StyleCop. Это один из многих стандартов
@zameb: Я бы сказал, что правила StyleCop - одно из самых распространенных правил кодирования для C#. При кодировании на любых языках я всегда стараюсь найти наиболее распространенный набор рекомендаций по кодированию и следовать им.
Я предпочитаю размещать частные поля вверху вместе с конструктором (ами), затем помещать биты общедоступного интерфейса после этого, а затем биты частного интерфейса.
Кроме того, если определение вашего класса достаточно длинное, чтобы порядок элементов имел большое значение, вероятно, запах кода указывает на то, что ваш класс слишком громоздкий и сложный, и вам следует провести рефакторинг.
Обычно я стараюсь следовать следующей схеме:
Каждая часть (статическая и экземплярная) состоит из следующих типов членов:
Затем участники сортируются по видимости (от менее заметной к более заметной):
Порядок не является догмой: простые классы легче читать, однако более сложные классы нуждаются в группировке в зависимости от контекста.
Я стараюсь сделать это как можно проще (по крайней мере, для меня)
Перечисления
Объявления
Конструкторы
Переопределения
Методы
Свойства
Обработчик событий
Согласно Документация по правилам StyleCop порядок следующий.
Внутри класса, структуры или интерфейса: (SA1201 и SA1203)
В каждой из этих групп упорядочить по доступу: (SA1202)
В каждой из групп доступа в порядке статического, затем нестатического: (SA1204)
В каждой из статических / нестатических групп полей упорядочивайте только чтение, затем не только чтение: (SA1214 и SA1215)
Развернутый список состоит из 130 строк, поэтому я не буду его здесь разворачивать. Развернутая часть методов:
В документации отмечается, что если предписанный порядок не подходит - скажем, реализуется несколько интерфейсов, а методы и свойства интерфейса должны быть сгруппированы вместе, - тогда используйте частичный класс, чтобы сгруппировать связанные методы и свойства вместе.
Я хотел бы поблагодарить вас за то, что вы приложили усилия для написания этой статьи. Я пытаюсь сделать StyleCop стандартом (даже если просто для того, чтобы упростить поиск), и это ценно.
Лично меня раздражает порядок статических методов. Я вижу аргумент в пользу того, что сначала идут статические общедоступные методы, но обычно мне нужны частные статические методы после членов. В конце концов, это коммунальные службы.
Спасибо, это немного помогло мне с моими последними изменениями в моей надстройке помощи StyleCop (sweeper.codeplex.com). Единственное, что я хотел бы отметить дополнительно, это то, что многие типы элементов не поддерживают статику.
Мне понравился совет частичного класса
Просто примечание о частичных классах. Учитывая, что во время компиляции все частичные файлы компилируются в один тип, я всегда старался найти вескую причину для создания этих дополнительных накладных расходов. Основная причина использования частичных классов заключается в расширении автоматического создания исходного кода или при работе над большими проектами, чтобы позволить нескольким разработчикам работать с одним и тем же классом, но с отдельными файлами.
@ FrançoisWahl Так ли велики накладные расходы, связанные с компилятором, объединяющим частичные классы в один тип?
@dav_i: Если накладные расходы заметны или нет, я действительно не знаю, я не проводил никаких тестов производительности на этом. Скорее всего, это незаметно, но, как правило, я стараюсь создавать только частичные файлы при расширении автоматически сгенерированного кода. Вот также хороший ресурс по частям: 4guysfromrolla.com/articles/071509-1.aspx
@ FrançoisWahl Я полагаю, накладные расходы не так уж и плохи, и преимущества удобочитаемости сэкономят вам больше времени в долгосрочной перспективе :) Интересная статья - я не понимал, что существуют частичные методы!
Другой момент. Каков стандартный способ группировки в public static fields и т. д. - то есть идет по имени поля или по типу, а затем по имени поля? (например, public int a; public bool b; или public bool b; public int a;?
Единственное, чего я избегаю, - это разделение полей и связанных с ними свойств доступа. Я рассматриваю такие пары как одно поле.
Что означает «Интерфейсы» (между перечислениями и свойствами)? Явные реализации интерфейса или ...?
@ FrançoisWahl - Я часто использую частичные классы в своих больших проектах. Я не заметил абсолютно никаких накладных расходов на компиляцию, а самый большой проект составляет около 600 тыс. Строк. Мне не нравится иметь класс с десятками средств доступа и методов. В больших классах я разделю его на отдельные файлы .cs, по одному для каждого метода. Я считаю, что это также упрощает просмотр обозревателя решений и мгновенный визуальный просмотр всех доступных методов в классе вместо того, чтобы открывать файл и сканировать его.
К вашему сведению, ваша ссылка на правила полицейского стиля не работает.
Правила упорядочивания StyleCop можно найти в github.com/Visual-Stylecop/Visual-StyleCop/wiki/Ordering-Rul es.
С «новыми» автоматическими свойствами C# мне не очень нравятся поля -> конструкторы -> порядок свойств, я чувствую, что свойства должны идти после полей, если их всего 1 или 2. Трудно сохранить «один или два» как определенное правило, поэтому я продолжаю следовать этому ...
Кто-нибудь знает, доступно ли это в виде файла макета Resharper?
Я бы сгруппировал вместе все статические элементы, кроме экземпляров. Очень вероятно, что вы работаете с несколькими элементами, статическими элементами и, статическими полями, поэтому имеет смысл держать их рядом. С другой стороны, когда вы ищете статический член, вы очень хорошо знаете, что он статический, поэтому поиск в другом месте не должен вызывать особого беспокойства. Я не нашел преимуществ в чередовании статических элементов с динамическими; то есть третий критерий заказа должен быть первым, на мой взгляд.
Style Cop использует порядок, который имел смысл в старые времена C, но не более того. В объектно-ориентированных клиентах вашего класса следует использовать общедоступный интерфейс вашего класса (и, если необходимо, это общедоступные свойства). Поместите их вверху, чтобы облегчить пользователям вашего класса. Если вы используете контейнер DI, ваш конструктор (-ы) также не очень актуален для ваших читателей, он может идти со всем остальным, что вам нужно только при работе над внутренней работой класса.
Хотя это превосходно отвечает на первую половину вопроса, я хотел бы добавить примечание ко второй части: если ваши свойства сложны и похожи на методы, тогда свойство должно вызывать метод. Я все время вижу одно и то же в отношении событий. Фактически выполняйте работу в частных методах и классах. Если код достаточно мелкий, порядок StyleCop становится более понятным.
А как насчет автоматически реализуемых свойств? Должны ли они придерживаться полей или других свойств?
Это старый, но все еще очень актуальный вопрос, поэтому я добавлю следующее: на что вы в первую очередь обращаете внимание, открывая файл класса, который вы, возможно, читали раньше, а могли и не читали? Поля? Характеристики? На собственном опыте я понял, что почти всегда я иду на охоту за конструкторами, потому что самое основное, что нужно понять, - это то, как этот объект построен.
Поэтому я начал ставить конструкторы на первое место в файлах классов, и психологически результат оказался очень положительным. Стандартная рекомендация ставить конструкторы после множества других вещей кажется диссонирующей.
Предстоящая функция основного конструктора в C# 6 свидетельствует о том, что естественное место для конструктора находится на самом верху класса - на самом деле основные конструкторы указываются даже перед открывающей фигурной скобкой.
Забавно, насколько сильно меняет такое переупорядочивание. Это напоминает мне о том, как раньше были упорядочены операторы using - сначала с пространством имен System. Команда Visual Studio «Организовать использование» использовала этот порядок. Теперь using просто упорядочены в алфавитном порядке, без особой обработки пространств имен System. Результат кажется проще и чище.
Инициализация / построение класса, на мой взгляд, запутана. Поля инициализируются до запуска явных конструкторов, поэтому, продолжая свой аргумент о размещении элементов в том порядке, в котором они используются / создаются, инициализированные поля будут перед явно объявленными конструкторами. Инициализированные статические поля и статические конструкторы делают его еще более интересным.
На самом деле, в том порядке, в котором их обычно ищут люди, представление литературного программирования о том, что код должен сначала быть читаемым людьми.
Обратите внимание, что основные конструкторы были удалены из планов для C# 6: stackoverflow.com/a/26915809/5085211
В 9 случаях из 10 я ищу общедоступный интерфейс, поэтому сначала ставлю все общедоступные члены, затем внутренние, затем защищенные и, наконец, частные члены.
@DavidCulp: я думаю, он не хотел сказать, что хочет видеть, в каком порядке инициализируется класс, он не компилятор, а человек. Он хочет «понять, как устроен этот объект», и это понятно. Ему может понадобиться этот класс, и он хочет увидеть зависимости и то, что ему действительно нужно.
Я предпочитаю упорядочивать по типу, а затем уменьшать видимость следующим образом
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, когда переменные должны были быть объявлены в первую очередь. Я почти всегда хочу сначала увидеть общедоступный интерфейс, а не внутреннее устройство класса.
На самом деле в этом есть большой смысл. Бьюсь об заклад, это пережиток C.
Некоторые из самых больших ошибок могут быть свойства IMO. Когда в геттере / сеттере есть логика, о которой вы не знали, у нее гораздо больше шансов укусить, чем побочные эффекты в методах (которые, естественно, вы ожидаете от них) .Поэтому я предпочитаю свойства рядом с их полями вверху. , поэтому, когда я впервые смотрю на класс, я вижу, что проблема на высоте. Когда, когда я читаю метод, я обычно сразу перехожу к методу в любом случае
Я знаю, что это старый, но мой порядок следующий:
в порядке публичного, защищенного, частного, внутреннего, абстрактного
Мне также нравится записывать такие свойства (вместо сокращенного подхода)
// 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; }
}
На самом деле, чтобы ответить на актуальный вопрос, нет, официального руководства нет. StyleCop реализует рекомендации, разработанные для использования внутри одной конкретной группы в Microsoft. Это не официальная директива, и она может даже не быть единообразной для разных групп в Microsoft.