Являются ли частичные классы С# плохой конструкцией?

Мне интересно, почему концепция "частичного класса" существует даже в С#/VB.NET. Я работаю над приложением, и мы читаем (на самом деле очень хорошую) книгу, соответствующую платформе разработки, которую мы реализуем на работе. В книге автор предоставляет большую базу/оболочку кода вокруг API-интерфейсов платформы и объясняет, как он развивал ее, изучая различные темы разработки платформы.

В любом случае, длинный рассказ короткий - он использует частичные классы повсюду, как способ подделать множественное наследование в С# (IMO). Почему он не просто разделил классы на несколько, а использование композиции вне меня. Он будет иметь 3 'частичных классных файла, чтобы составить свой базовый класс, каждый из которых содержит 3-500 строк кода... И делает это несколько раз в своем API.

Вы находите это оправданным? Если бы это был я, я бы следовал за S.R.P. и создал несколько классов для обработки различных требуемых поведений, а затем создал базовый класс, который имеет экземпляры этих классов в качестве членов (например, композиция). Почему MS даже включила частичный класс в рамки? Они удалили возможность развернуть/свернуть весь код на каждом уровне уровня в С# (это было разрешено на С++), потому что это, очевидно, просто позволяло использовать вредные привычки - частичный класс, IMO, то же самое. Я думаю, мой вопрос: вы можете объяснить мне, когда будет законная причина когда-либо использовать частичный класс?

EDIT: Я знаю, что для Web/WinForms другого выбора нет. Но вне этого? Почему MS не просто добавил несколько ключевых слов для склеивания кода? Или действительно ли существует подходящий сценарий дизайна?

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

Спасибо

Ответ 1

Можете ли вы объяснить мне, когда будет законная причина когда-либо использовать частичный класс?

Одной из наиболее законных и полезных причин является поощрение разделения автоматически сгенерированного кода и собственных пользовательских расширений. Например, обычно возникает автоматически созданный код формы от какого-то конструктора, но вы обычно хотите добавить к нему свое собственное поведение. Таким образом, если вы регенерируете часть автоматического кода, вы не трогаете часть, которая имеет ваши конкретные расширения.

Тем не менее, вполне возможно иметь слишком много хорошего. Некоторые советы:

  • Не делайте свои классы partial ради partial.

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

  • Не используйте partial как метод, чтобы скрыть размер класса. Если вы разбиваете свои классы с помощью partial, потому что они слишком большие, вы должны вернуться к Принципу единой ответственности.

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

В любом случае, длинный рассказ короткий - он использует частичные классы повсюду, как способ подделать множественное наследование в С# (IMO). Почему он просто не разбил классы на несколько, и использование композиции вне меня. Он будет иметь 3 'частичных классных файла, чтобы составить свой базовый класс, каждый из которых содержит 3-500 строк кода... И делает это несколько раз в своем API.

Да, это определенно явное злоупотребление partial!

Ответ 2

Есть две причины, по которым я (и делаю) использовал бы частичные классы.

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

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

Для более подробного обсуждения проверьте, что этот дубликат: Частичные классы в С#

Ответ 3

Другое законное использование частичных классов - помочь уменьшить беспорядок "монолитного веб-сервиса" в WCF. Вы хотите разбить его на логические группы функциональности, но не хотите создавать множество отдельных экземпляров/конечных точек службы (по-видимому, потому, что они разделяют состояние, ресурсы и т.д.).

Решение? Попросите сервис реализовать несколько интерфейсов и реализовать каждый интерфейс в своем собственном частичном классе. Затем сопоставьте разные конечные точки в конфигурации с той же физической реализацией. Это делает проект намного более удобным, но у вас все еще есть одна физическая конечная точка.

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

Ответ 4

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

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

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

Ответ 5

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

Помимо автогенерированного кода, я не могу думать о хорошем использовании частичных классов. Даже если вы используете EF и нуждаетесь в разных метаданных, они даже не рекомендуют использовать частичные метаданные. Фактически, если вы попытаетесь дублировать любые свойства в другом частичном (просто добавить метаданные), вы получите ошибку компилятора.

Чем больше мы узнаем о рефакторинге и SOC (Разделение проблем), тем меньше становятся все более и более сосредоточенными наши классы. Они по умолчанию используются повторно, что со временем делает их пуленепробиваемыми и легко проверенными. Просто скажите "НЕТ" для гигантских программ. Генри Форд узнал эту концепцию в начале 1900 года, когда программисты начали изучать ее через 100 лет.

Используйте композицию, когда вы можете...

Ответ 6

Можете ли вы объяснить мне, когда будет законная причина когда-либо использовать частичный класс?

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

Пример ASP.NET:

  • Page.aspx
  • Page.aspx.cs < - Ваш код
  • Page.aspx.Designer.cs < - частичный класс, содержащий автоматически сгенерированный код.

Пример WinForms:

  • Form1.resx
  • Form1.cs < - Ваш код
  • Form1.Designer.cs < - частичный класс, содержащий автоматически сгенерированный код

Ответ 7

Я полностью согласен с ответом Джона. Но я бы сделал еще один шаг.

  • Не делайте частичные части.

Единственное использование частичных классов, о которых я могу думать, что я считаю "хорошим дизайном", - это сгенерированный автоматически код. Любое другое использование почти наверняка не обязательно разделяет ваш класс. (На самом деле, я вижу, что вторая точка Джеффа на вложенных классах, возможно, действительное использование)

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

Ответ 8

Я использовал частичные классы для "физического" разделения методов статического доступа к данным из свойств и методов бизнес-класса в активной архитектуре записи. Например, у нас были частичные классы Company и CompanyData бок о бок. Преимущество заключалось в том, что один файл был POCO, а другой - только методы доступа к данным. Это стало шагом к удалению доступа к данным к классам репозитория в устаревшем приложении. Я думаю, что это было законное использование, это, безусловно, сделало процесс повторного факторинга более ясным.

Ответ 9

Еще одно полезное использование для частичных классов было бы при реализации Abstract factory pattern. Сделайте часть корня factory частичной, а затем поместите фактические методы factory в тот же файл, что и экземпляр класса factory.

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

Ответ 10

Просто наткнулся на эту нить, в то время как вы использовали преимущества частичного класса. Я в процессе преобразования приложения Java EE в .NET на основе Silverlight. Я наткнулся на следующий код на уровне представления:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.225
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

...

 public partial class Wwcusts04d : System.Windows.Controls.Page {

Теперь, если сама частичная страница автогенерируется, что ее использовать? Кроме того, код внутри просто связывает различные элементы управления с их именами. Я не признаюсь, что имею знания о Silverlight, но разве эта вещь лучше не подходит для xaml?

Ответ 11

Частичный класс существует в .NET Framework исключительно, чтобы разработчики Visual Studio (например, дизайнер Asp.Net и дизайнер Windows Forms) генерировали код/​​беспорядок с вашими классами, сохраняя этот сгенерированный код в отдельном файле.

(См. Частичные классы .NET и Наследование)

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

Не так много, что использование Partial classes - плохой дизайн - его просто вы, вероятно, не найдете для них использования.

Ответ 12

Я использовал частичный класс дважды в VB.Net, и оба раза были для редкого случая, что мне нужно было поздно связывать. Просто создайте частичный класс и включите опцию Strict Off в верхней части.

Ответ 13

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

Ответ 14

Там много дискуссий по этой теме, и многие люди говорят, что 1) это плохой дизайн для использования частичных классов, 2) что он используется для автогенерированного кода и 3) что он не должен заменять это место наследования.

У меня есть ситуация, в которой частичные классы выглядят так, как будто они пригодится: я создаю серию приложений, которые в конечном итоге будут интегрированы в набор. Все они будут иметь основную форму, которая обеспечит некоторые функции и несколько общих компонентов (например, форму для отображения отчетов). Хотя я мог определять базовый класс и наследовать его, это означало бы большую переделку, когда пришло время объединить все приложения в "корпоративную" версию продукта.

Таким образом, частичные классы весьма полезны, потому что я могу просто включить различные частичные классы в комбинированную версию, сохраняя при этом возможность создавать отдельные автономные версии продукта. Если бы я попытался выполнить это с помощью наследования, я бы включил каждый компонент, который вызывал свою собственную версию общих компонентов (например, InvoiceReportViewer, PurchasingReportsViewer и т.д.), А не просто вызывал ReportViewer и знал, что Visual Studio будет интегрирован все биты для меня.

Ответ 15

Другое дело, что частичные классы заставляют вас создавать разные имена файлов, которые содержат одно и то же имя класса. Например, у вас есть FactoryClass, и вы создаете частичные версии этого типа; Factory.designer.cs, Factory.data.cs, ​​и все эти файлы имеют класс с именем FactoryClass.

Если вы перейдете к этому вопросу; существует лучшая практика, определяемая как:

Лучшей практикой, однако, является определение одного класса для каждого файла и предоставление файлу того же имени, что и определение класса (или структуры и т.д.).