Частичные классы в C#

есть ли хорошее использование частичных классов вне сценариев кода, генерируемых webforms/winforms? Или эта функция в основном поддерживает это?

20 ответов


Он частично поддерживает сценарии (WebForms, WinForms, LINQ-to-SQL и т. д.), смешивая сгенерированный код с кодом программиста.

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


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

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

проект, над которым я сейчас работаю, использует генерацию кода для всех DAL, BLL и бизнес-объектов. Однако генератор получает только 75% информации. Оставшаяся часть должна быть закодирована вручную (например, пользовательская бизнес-логика). Я могу предположить, что каждый класс BLL имеет метод SelectAll, так что это легко генерировать. Однако мой клиент BLL также должен иметь метод SelectAllByLocation. Я не могу поместить это в свой генератор, потому что он не является общим для всех классов BLL. Поэтому я создаю все свои классы как частичные классы, а затем в отдельном файле определяю свои пользовательские методы. Теперь вниз по дороге, когда моя структура меняется, или мне нужно регенерировать мой BLL по какой-то причине, мой пользовательский код не будет уничтожен.


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


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

мы также использовали их для группировки переопределений запасов или скрытия набора свойств запасов. Такие вещи. Это удобный способ смешивания при изменении запаса (просто скопируйте файл и измените имя частичного класса на целевой класс - если целевой класс тоже будет частичным).


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

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

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

// Main Part
public partial class Class1
{
    private partial void LogSomethingDebugOnly();

    public void SomeMethod()
    {
        LogSomethingDebugOnly();
        // do the real work
    }
}

// Debug Part - probably in a different file
public partial class Class1
{

    #if DEBUG

    private partial void LogSomethingDebugOnly()
    {
        // Do the logging or diagnostic work
    }

    #endif
}

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


Я нахожу частичные классы чрезвычайно полезными. Обычно они используются, чтобы быть в состоянии расширить автогенерируемые классы. Я использовал их в одном проекте с тяжелыми юнит-тестами. Мои классы UT имели сложные зависимости, и было не очень практично разделять код между несколькими классами.Конечно, лучше использовать наследование\composition, но в некоторых случаях частичные классы могут быть полезны.


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

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

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


может быть, ее слишком поздно, но, пожалуйста, позвольте мне добавить мои 2 цента тоже:

*.При работе над большими проектами распространение класса по отдельным файлам позволяет нескольким программистам работать над ним одновременно.

*.Вы можете легко написать свой код (для расширенной функциональности) для VS.NET сгенерированный класс. Это позволит вам написать код вашей собственной потребности, не возясь с генерируемым системой кодом


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

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


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


пару лет назад я работал над проектом, где у нас был типизированный класс DataSet, в котором была тонна кода: методы в DataTables, методы в TableAdapters, объявления экземпляров TableAdapter, вы называете его. Это была огромная центральная точка проекта, над которой каждый должен был работать часто, и было много споров о контроле источника над файлом кода частичного класса.

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

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


вообще, я считаю, что это запах кода.

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

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

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


Я опаздываю в игре... но просто мои 2 цента...

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

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


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


Я использую его на уровне доступа к данным. Сгенерированные классы, такие как mapper и запросы partial. Если мне нужно добавить метод mapper, например, для выполнения причудливой загрузки, которая не генерируется, я добавляю его в пользовательский класс.

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


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


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

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


везде, где вы бы использовали #region разделы раньше, вероятно, имеет больше смысла как отдельные файлы в разделяемых классах.

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


EDIT: DSL Tools для Visual Studio использует частичные классы.

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

хорошо иметь этот выбор, который вы можете комбинировать-но не вынуждены использовать-с наследство

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