В моем понимании partial
ключевое слово делает только то, что позволяет разделить класс между несколькими исходными файлами. Есть ли причина для этого, кроме как для организации кода? Я видел, как это используется в сгенерированных классах пользовательского интерфейса.
Кажется, плохая причина для создания целого ключевого слова. Если класс достаточно большой, чтобы требовать нескольких файлов, он, вероятно, делает слишком много. Я подумал, что, возможно, вы могли бы использовать его, чтобы частично определить класс для другого программиста, где-то, чтобы завершить, но было бы лучше сделать абстрактный класс.
c#
design
language-design
Майкл К
источник
источник
partial
только означает что-то, когда это приходит раньшеclass
. Вы можете использовать его как имя идентификатора в других частях кода и т. Д.Ответы:
Это очень полезно в каждом сценарии, когда одна часть класса генерируется каким-либо настраиваемым инструментом, поскольку позволяет добавлять пользовательскую логику в сгенерированный код без наследования сгенерированного класса. Btw. Есть также частичные методы по той же причине.
Это касается не только пользовательского интерфейса, но и других технологий, таких как Linq-To-Sql или Entity Framework.
источник
Как вы говорите, он часто используется для разделения сгенерированного кода. Часто это не имеет ничего общего с размером классов / файлов.
Преимущество разделения сгенерированного кода заключается в стиле. Сгенерированный код может быть довольно уродливым и нечитаемым и может не соответствовать многим стандартам кодирования (и проверкам StyleCop), но это нормально, никто не должен его читать или поддерживать напрямую. Таким образом, если вы «скрываете» его в другом файле, вы можете сосредоточиться на том, чтобы убедиться, что остальная часть класса соответствует стандарту, проходит проверки StyleCop и так далее.
Другая область, где я использовал это, где класс реализует несколько интерфейсов, может быть неплохо разделить реализацию на отдельные файлы, хотя это больше вопрос личных предпочтений, я никогда не видел, чтобы какие-либо стандарты кодирования требовали ( или предотвратить) это.
источник
Пару недель назад один из разработчиков, где я работаю, очень хорошо их использовал для рефакторинга огромных классов Бога, которые вышли из-под контроля и имеют множество открытых методов: путем разделения логических функций каждого бита. Класс на отдельные частичные классы. Вы можете физически разделить класс на более атомарные единицы, которые должны быть классами, не нарушая существующую функциональность, позволяя вам увидеть, что является общим, а что нет. На первом этапе вы можете легко разбить партиалы на их собственные независимые классы и реализовать их во всей базе кода. Я думал, что это была хорошая идея.
Тем не менее, в целом, я думаю, что они должны использоваться только для расширения машинно-генерируемых классов при написании нового кода.
источник
Я могу вспомнить несколько полезных сценариев, в которых партиалы имеют смысл, большинство из которых я использую сам в своих проектах:
Чтобы отделить сгенерированный код Tool / IDE / Designer от поддерживаемого вами кода. Хорошим примером является
Form.Designer.cs
файл, содержащий сгенерированный дизайнером код для приложений форм Windows. Многие другие форматы .NET также имеют некоторый код, сгенерированный инструментами, который потенциально может быть регенерирован при сборке вашего проекта, и, таким образом, все ваши пользовательские изменения будут удалены. Разделение поможет вам сохранить ваш код и изменения в безопасности от таких автоматических изменений.Когда вы реализуете несколько интерфейсов с большим количеством кода в реализации. Я , как правило , использовать отдельный частичный файл для каждого такого интерфейса, называя это следующим образом :
{Class}.{Interface}.cs
. Мне легко увидеть в IDE, какие интерфейсы{Class}
реализует и как.Когда класс должен содержать один или несколько вложенных классов , особенно с достаточным количеством кода, который можно поместить в отдельный файл. Я придерживаюсь вышеупомянутого образца и использую
{Class}.{NestedClass}.cs
соглашение об именах для каждого вложенного класса. Подобная практика уже упоминается в ответе Virtlink .Когда я пишу
static
классы, которые будут содержать методы расширения . Часто бывает так, чтобы предоставить одинаковую логику метода расширения для схожих классов или интерфейсов - как, например,Reverse
для общих и неуниверсальных коллекций. Я бы поместил все методы расширения для одного класса или интерфейса в отдельную часть статического класса. Например, у меня есть все методы расширения дляIList
интерфейса в одном месте и те же методы, что иIList<T>
в другом файле. Другой подход заключается в том, чтобы поместить один и тот же метод (все его перегрузки) в один и тот же фрагмент со всеми возможными классами дляthis
параметра - например, иметь всеReverse
реализации в одном файле. Это зависит от того, какой из них лучше оправдал бы разделение с точки зрения объема кода или каких-то внутренних соглашений, которых вы или ваша организация должны придерживаться.Я не использую это, но я видел, что некоторым людям на C / C ++ нравится подход, который я опишу здесь: создайте частичное для класса только с частичными методами . Это напоминает способ C / C ++ для определения интерфейсов и отделения объявления метода от реализации.
Разделение по чисто логическим соображениям . Если вам доведется работать с большим классом, который объединяет в себе более одного логического набора операций, то вы можете разделить каждый логически связанный код на отдельный фрагмент. Обычно существование таких классов противоречит принципу разделения интересов , но это часто наблюдается в реальной жизни, особенно для старых кодовых баз. Другой пользователь Стив Эверс упомянул их в своем ответе на этот вопрос , ссылаясь на них именем бога объектов, Я бы лично использовал подход частичных классов для разделения кода до того, как произойдет рефакторинг таких действительно больших файлов, чтобы упростить мою работу и сделать рефакторинг более прозрачным. Это также уменьшит конфликты, которые я потенциально могу вызвать, когда задействованы системы контроля версий, такие как SVN.
источник
Я не видел никого упомянутого: я использую,
partial
чтобы поместить вложенные классы в свои файлы.Все мои файлы кода содержат только один класс, структуру, интерфейс или перечисление. Намного легче найти определение для объекта, когда имена файлов показывают название того, что вы ищете. А поскольку Visual Studio пытается сопоставить папки проекта с пространствами имен, имена файлов должны соответствовать классам.
Это также означает , что класс
NestedClass
вложенныйMyClass
будет иметь свой собственный файл в моих проектах:MyClass.NestedClass.cs
.источник
За исключением использования сгенерированного кода, я только когда-либо видел, чтобы они использовались в попытке прикрыть объекты бога . Попытка понять новую кодовую базу или перемещаться по нескольким исходным файлам, которые являются одним и тем же объектом, слишком раздражает.
Поэтому, когда вы спрашиваете,
Why use partial classes?
я отвечаю: если вы не используете сгенерированный код, не делайте этого.источник
Организация кода - единственная причина, но она идет глубже, чем кажется на первый взгляд. Если у вас есть частичные классы, где генерируются части, вы можете легко:
источник
Есть также несколько мест, где сгенерированные / подразумеваемые классы объявляются частичными, поэтому, если разработчик должен расширить их, он имеет полный доступ без необходимости возиться с наследованием и переопределением повсеместно. Посмотрите на сгенерированные классы во временной области asp.net после первого запуска сайта веб-форм под IIS, если вы хотите попытаться поймать некоторые примеры.
источник
Я могу думать о грязном использовании для них.
Предположим, у вас есть классы, которым нужна общая функциональность, но вы не хотите внедрять эту функциональность в цепочку наследования над ними. Или у вас есть набор классов, которые используют общий вспомогательный класс.
В основном вы хотите сделать множественное наследование, но C # не похоже. Итак, вы используете частичное для создания того, что по сути является #include в C / C ++;
Поместите всю функциональность в класс или используйте вспомогательный класс. Затем скопируйте помощник X раз и переименуйте его в частичный класс A, B, C. и поставить частичный на ваши классы A, B, C.
Отказ от ответственности: Да, это зло. Никогда не делай этого - особенно если это заставит других людей злиться на тебя.
источник