Ответы:
Самое частое использование частичных классов - облегчить жизнь генераторам / дизайнерам кода. Частичные классы позволяют генератору просто испускать код, который им нужен, и им не нужно иметь дело с пользовательскими изменениями в файле. Пользователи также могут свободно аннотировать класс новыми членами, имея второй частичный класс. Это обеспечивает очень чистую основу для разделения проблем.
Лучший способ взглянуть на это - увидеть, как дизайнеры работали до частичных классов. Дизайнер WinForms выплевывал весь код внутри региона с жестко сформулированными комментариями о том, как не изменять код. Пришлось вставить всевозможные эвристики, чтобы найти сгенерированный код для последующей обработки. Теперь он может просто открыть файл designer.cs и иметь высокую степень уверенности, что он содержит только код, относящийся к конструктору.
Другое использование состоит в том, чтобы разделить реализацию различных интерфейсов, например:
partial class MyClass : IF1, IF2, IF3
{
// main implementation of MyClass
}
partial class MyClass
{
// implementation of IF1
}
partial class MyClass
{
// implementation of IF2
}
Implements
ключевое слово для обозначения метода, принадлежащего интерфейсу)
Помимо других ответов ...
Я нашел их полезными в качестве трамплина в рефакторинге богов. Если у класса есть несколько обязанностей (особенно если это очень большой файл кода), то я считаю целесообразным добавить 1x частичный класс для каждой ответственности в качестве первого прохода для организации, а затем рефакторинга кода.
Это очень помогает, потому что может помочь сделать код намного более читабельным, фактически не влияя на поведение при выполнении. Это также может помочь определить, когда ответственность легко реорганизовать или тесно связана с другими аспектами.
Однако - чтобы быть ясным - это все еще плохой код, в конце разработки вы все еще хотите одну ответственность за класс ( НЕ за частичный класс). Это просто трамплин :)
Только частичное объявление метода Даже код компилируется только с объявлением метода, и, если реализация метода отсутствует, компилятор может безопасно удалить этот кусок кода, и не возникнет ошибка времени компиляции.
Чтобы проверить пункт 4. Просто создайте проект winform и добавьте эту строку после конструктора Form1 и попробуйте скомпилировать код
partial void Ontest(string s);
Вот некоторые моменты, которые следует учитывать при реализации частичных классов:
Одним из важных применений является отделение сгенерированного кода от рукописного кода, принадлежащего одному и тому же классу.
Например, поскольку LINQ to SQL использует частичные классы, вы можете написать собственную реализацию определенных частей функциональности (например, отношений «многие ко многим»), и эти части пользовательского кода не будут перезаписаны при повторной генерации кода.
То же самое касается кода WinForms. Весь сгенерированный дизайнером код помещается в один файл, который вы обычно не трогаете. Ваш рукописный код помещается в другой файл. Таким образом, когда вы что-то меняете в Designer, ваши изменения не срываются.
Это правда, что Partial Class используется для автоматической генерации кода, одним из которых может быть поддержание большого файла класса, который может иметь тысячи строк кода. Вы никогда не знаете, что ваш класс может закончиться 10 тысячами строк, и вы не хотите создавать новый класс с другим именем.
public partial class Product
{
// 50 business logic embedded in methods and properties..
}
public partial class Product
{
// another 50 business logic embedded in methods and properties..
}
//finally compile with product.class file.
Другое возможное использование может заключаться в том, что более одного разработчика могут работать в одном классе, поскольку они хранятся в разных местах. Люди могут смеяться, но вы никогда не знаете, что иногда это может быть горсткой.
public partial class Product
{
//you are writing the business logic for fast moving product
}
public partial class Product
{
// Another developer writing some business logic...
}
Надеюсь, это имеет смысл!
Частичные классы охватывают несколько файлов.
Как вы можете использовать частичный модификатор в объявлении класса C #?
Частичные классы позволяют физически разделить класс на несколько файлов. Это часто делается генераторами кода.
пример
С обычными классами C # вы не можете объявить класс в двух отдельных файлах в одном проекте. Но с partial
модификатором вы можете.
Это полезно, если один файл обычно редактируется, а другой генерируется машиной или редко редактируется.
Вот пример, чтобы уточнить:
class Program
{
static void Main()
{
A.A1();
A.A2();
}
}
Содержимое файла A1.cs: C #
using System;
partial class A
{
public static void A1()
{
Console.WriteLine("A1");
}
}
Содержимое файла A2.cs: C #
using System;
partial class A
{
public static void A2()
{
Console.WriteLine("A2");
}
}
Вывод:
A1
A2
Частичное требуется здесь.
Если вы удалите partial
модификатор, вы получите ошибку, содержащую этот текст:
[Пространство имен '
<global namespace>
' уже содержит определение для 'A
'].
Подсказка:
Чтобы это исправить, вы можете использовать partial
ключевое слово или изменить одно из имен классов.
Как компилятор C # работает с частичными классами?
Если вы разберете вышеуказанную программу (используя IL Disassembler), вы увидите, что файлы A1.cs и A2.cs исключены. Вы обнаружите, что класс А присутствует.
Класс A будет содержать методы A1 и A2 в одном и том же блоке кода. Два класса были объединены в один.
Скомпилированный результат A1.cs и A2.cs: C #
internal class A
{
// Methods
public static void A1()
{
Console.WriteLine("A1");
}
public static void A2()
{
Console.WriteLine("A2");
}
}
Резюме
Сохраняйте все как можно более чистыми при работе с огромными классами или при работе в команде, вы можете редактировать без переопределения (или всегда вносить изменения)
Основное использование для частичных классов - сгенерированный код. Если вы посмотрите на сеть WPF (Windows Presentation Foundation), вы определите свой пользовательский интерфейс с помощью разметки (XML). Эта разметка компилируется в частичные классы. Вы заполняете код частичными собственными классами.
Если у вас достаточно большой класс, который не поддается эффективному рефакторингу, разделение его на несколько файлов помогает сохранить порядок.
Например, если у вас есть база данных для сайта, содержащего дискуссионный форум и систему продуктов, и вы не хотите создавать два разных класса провайдеров (НЕ то же самое, что прокси-класс, просто для ясности), вы можете создать один частичный класс в разных файлах, например
MyProvider.cs - основная логика
MyProvider.Forum.cs - методы, относящиеся конкретно к форуму
MyProvider.Product.cs - методы для продуктов
Это просто еще один способ держать вещи в порядке.
Кроме того, как уже говорили другие, это единственный способ добавить методы в сгенерированный класс, не рискуя уничтожить ваши добавления при следующей регенерации класса. Это очень удобно для кода, сгенерированного шаблоном (T4), ORM и т. Д.
Как альтернатива директивам прекомпилятора.
Если вы используете директивы прекомпилятора (а именно #IF DEBUG
), то в итоге вы получите какой-то мрачно выглядящий код, смешанный с вашим реальным кодом Release.
Вы можете создать отдельный частичный класс, содержащий этот код, и либо обернуть весь частичный класс в директиву, либо пропустить этот кодовый файл для отправки компилятору (фактически, делая то же самое).
Ссылки на сервисы являются еще одним примером, где частичные классы полезны для отделения сгенерированного кода от кода, созданного пользователем.
Вы можете «расширить» классы обслуживания, не перезаписывая их при обновлении ссылки на службу.
Другое использование, которое я видел,
Расширение большого абстрактного класса относительно логики доступа к данным,
у меня есть различные файлы с именами Post.cs, Comment.cs, Pages.cs ...
in Post.cs
public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of post..
}
in Comment.cs
public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of comment..
}
in Pages.cs
public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of Pages..
}
Большинство людей отмечают, что их partial
следует использовать только для класса, в котором есть файл сгенерированного кода, или для интерфейсов. Я не согласен, и вот почему.
Для одного примера, давайте посмотрим на класс C # System.Math ... это класс . Я бы не пытался втиснуть все 70+ методов в один и тот же файл кода. Это было бы кошмаром для поддержания.
Размещение каждого математического метода в отдельных файлах частичного класса и всех файлов кода в папке Math в проекте будет значительно более чистой организацией.
То же самое может / будет справедливо для многих других классов, которые имеют большое количество разнообразных функциональных возможностей. Например, класс для управления API PrivateProfile может быть полезен, если его разделить на чистый набор частичных файлов классов в одной папке проекта.
Лично я также разделил то, что большинство людей называют «вспомогательными» или «служебными» классами, на отдельные частичные файлы для каждого метода или функциональной группы методов. Например, в одном проекте класс вспомогательных строк имеет почти 50 методов. Это был бы длинный громоздкий файл кода, даже с использованием регионов. Значительно проще поддерживать использование отдельных файлов классов для каждого метода.
Я просто буду осторожен, используя частичные классы, и при этом сохраню согласованность всей структуры файла кода на протяжении всего проекта. Например, помещая любые общедоступные перечисления класса и закрытые члены класса в файл Common.cs или файл с аналогичным именем в папке, вместо того, чтобы распространять их по файлам, если они не относятся только к частичному файлу, в котором они содержатся.
Помните, что когда вы разделяете класс на отдельные файлы, вы также теряете возможность использовать разделительную панель текстового редактора, которая позволяет одновременно просматривать два разных раздела текущего файла.
Частичные классы позволяют добавлять функциональные возможности в специально разработанную программу, просто добавляя исходные файлы. Например, программа импорта файлов может быть разработана таким образом, чтобы можно было добавлять различные типы известных файлов, добавляя модули, которые их обрабатывают. Например, основной конвертер типов файлов может включать небольшой класс:
Частичный открытый класс zzFileConverterRegistrar Регистр событий (ByVal mainConverter as zzFileConverter) ПодрегистрAll (ByVal mainConverter as zzFileConverter) Регистрация RaiseEvent (mainConverter) End Sub Конечный класс
Каждый модуль, который хочет зарегистрировать один или несколько типов файловых конвертеров, может включать что-то вроде:
Частичный открытый класс zzFileConverterRegistrar Private Sub RegisterGif (ByVal mainConverter as zzFileConverter) Обрабатывает Me.Register mainConverter.RegisterConverter ("GIF", GifConverter.NewFactory)) End Sub Конечный класс
Обратите внимание, что основной класс конвертера файлов не «выставлен» - он просто представляет небольшой класс-заглушку, к которому могут подключаться модули расширения. Существует небольшой риск возникновения конфликтов имен, но если подпрограмма «register» каждого модуля расширения именуется в соответствии с типом файла, с которым он имеет дело, они, вероятно, не должны создавать проблем. Можно указать GUID в имени подпрограммы регистрации, если вы беспокоитесь о таких вещах.
Редактировать / Добавление Чтобы было ясно, цель этого состоит в том, чтобы предоставить средство, с помощью которого различные отдельные классы могут сообщить основной программе или классу о них. Единственное, что будет делать основной конвертер файлов с zzFileConverterRegistrar, - это создать один его экземпляр и вызвать метод registerAll, который вызовет событие Register. Любой модуль, который хочет перехватить это событие, может выполнить произвольный код в ответ на него (вот и вся идея), но модуль ничего не может сделать, неправильно расширив класс zzFileConverterRegistrar, кроме определения метода, имя которого совпадает с именем другого объекта. , Конечно, было бы возможно, чтобы одно неправильно написанное расширение сломало другое неправильно написанное расширение, но решение для этого для тех, кто не хочет, чтобы его расширение было сломано, просто написать его правильно.
Можно было бы, без использования частичных классов, иметь немного кода где-то внутри основного класса конвертера файлов, который был бы похож на:
RegisterConverter ("GIF", GifConvertor.NewFactory) RegisterConverter ("BMP", BmpConvertor.NewFactory) RegisterConverter ("JPEG", JpegConvertor.NewFactory)
но добавление другого модуля преобразователя потребует перехода в эту часть кода преобразователя и добавления нового преобразователя в список. Используя частичные методы, в этом больше нет необходимости - все конвертеры будут включены автоматически.
IModule
интерфейс?
IModule
, вы можете использовать плагин-фреймворк, такой как MEF (только один из многих) и т. Д. И т. Д.
Частичные классы недавно помогли с контролем исходного кода, когда несколько разработчиков добавляли в один файл, где новые методы были добавлены в одну и ту же часть файла (автоматизировано Resharper).
Эти толчки вызвали конфликты слияний. Я не нашел способа заставить инструмент слияния принять новые методы как полный блок кода.
Частичные классы в этом отношении позволяют разработчикам придерживаться версии своего файла, и мы можем объединить их позже вручную.
пример -
Из MSDN :
1. Во время компиляции атрибуты определений частичного типа объединяются. Например, рассмотрим следующие объявления:
[SerializableAttribute]
partial class Moon { }
[ObsoleteAttribute]
partial class Moon { }
Они эквивалентны следующим декларациям:
[SerializableAttribute]
[ObsoleteAttribute]
class Moon { }
Следующее объединено со всеми определениями частичного типа:
XML комментарии
интерфейсы
атрибуты параметров универсального типа
атрибуты класса
члены
2. Еще одна вещь, вложенные частичные классы могут быть также частичными:
partial class ClassWithNestedClass
{
partial class NestedClass { }
}
partial class ClassWithNestedClass
{
partial class NestedClass { }
}
Вот список некоторых преимуществ частичных классов.
Вы можете разделить код разработки пользовательского интерфейса и код бизнес-логики, чтобы его было легко читать и понимать. Например, вы разрабатываете веб-приложение с использованием Visual Studio и добавляете новую веб-форму, тогда есть два исходных файла: «aspx.cs» и «aspx.designer.cs». Эти два файла имеют один и тот же класс с частичным ключевым словом. Класс «.aspx.cs» имеет код бизнес-логики, а «aspx.designer.cs» - определение элемента управления пользовательского интерфейса.
При работе с автоматически сгенерированным исходным кодом код можно добавить в класс, не создавая заново исходный файл. Например, вы работаете с LINQ to SQL и создаете файл DBML. Теперь, когда вы перетаскиваете таблицу, она создает частичный класс в designer.cs, и все столбцы таблицы имеют свойства в этом классе. Вам нужно больше столбцов в этой таблице для привязки к сетке пользовательского интерфейса, но вы не хотите добавлять новый столбец в таблицу базы данных, поэтому вы можете создать отдельный исходный файл для этого класса, который имеет новое свойство для этого столбца, и он будет быть частичным классом. Так что это влияет на отображение между таблицей базы данных и сущностью DBML, но вы можете легко получить дополнительное поле. Это означает, что вы можете написать код самостоятельно, не вмешиваясь в сгенерированный системой код.
Несколько разработчиков могут одновременно написать код для класса.
Вы можете лучше поддерживать свое приложение, сжимая большие классы. Предположим, у вас есть класс с несколькими интерфейсами, поэтому вы можете создавать несколько исходных файлов в зависимости от реализации интерфейса. Легко понять и поддерживать реализованный интерфейс, в котором исходный файл имеет частичный класс.
Всякий раз, когда у меня есть класс, который содержит вложенный класс любого существенного размера / сложности, я отмечаю класс как partial
и помещаю вложенный класс в отдельный файл. Я называю файл, содержащий вложенный класс, используя правило: [имя класса]. [Имя вложенного класса] .cs.
В следующем блоге MSDN объясняется использование частичных классов с вложенными классами для удобства обслуживания: http://blogs.msdn.com/b/marcelolr/archive/2009/04/13/using-partial-classes-with-nested-classes-for- maintainability.aspx
Я знаю, что этот вопрос действительно старый, но я просто хотел бы добавить свой взгляд на частичные занятия.
Одна из причин, по которой я лично использую частичные классы, - это когда я создаю привязки для программы, особенно конечных автоматов.
Например, OpenGL - это конечный автомат, есть куча методов, которые можно изменить глобально, однако, по моему опыту, связывая нечто похожее с OpenGL, где есть так много методов, класс может легко превысить 10 000 LOC.
Частичные уроки сломают это для меня и помогут мне быстро найти методы.
Частичные классы в основном вводятся для помощи генераторам кода, поэтому мы (пользователи) не теряем всю нашу работу / изменения в сгенерированных классах, таких как класс .designer.cs в ASP.NET, каждый раз, когда мы обновляем, почти все новые инструменты, которые генерируют код LINQ, EntityFrameworks, ASP.NET используют частичные классы для сгенерированного кода, поэтому мы можем безопасно добавлять или изменять логику этих сгенерированных кодов, используя преимущества частичных классов и методов, но будьте очень осторожны, прежде чем добавлять материал в сгенерированный код с использованием частичных классов легче, если мы нарушаем сборку, но хуже, если мы вводим ошибки во время выполнения. Для более подробной информации проверьте это http://www.4guysfromrolla.com/articles/071509-1.aspx
Я отмечаю два использования, которые я не смог найти явно в ответах.
Некоторые разработчики используют комментарии для разделения различных «частей» своего класса. Например, команда может использовать следующее соглашение:
public class MyClass{
//Member variables
//Constructors
//Properties
//Methods
}
С частичными классами мы можем пойти дальше и разделить разделы на отдельные файлы. Как правило, команда может добавлять суффикс к каждому файлу с соответствующим ему разделом. Таким образом, в приведенном выше примере мы имеем что-то вроде: MyClassMembers.cs, MyClassConstructors.cs, MyClassProperties.cs, MyClassMethods.cs.
Как уже упоминалось в других ответах, стоит ли разделять класс, вероятно, зависит от того, насколько велик класс в этом случае. Если оно маленькое, то, вероятно, проще иметь все в одном мастер-классе. Но если какой-либо из этих разделов становится слишком большим, его содержимое можно переместить в отдельный частичный класс, чтобы сохранить мастер-класс в чистоте. Соглашение в этом случае может заключаться в том, чтобы оставить комментарий, сказав что-то вроде «Смотрите частичный класс» после заголовка раздела, например:
//Methods - See partial class
Вероятно, это редкое явление, но может возникнуть конфликт пространства имен между двумя функциями из библиотек, которые вы хотите использовать. В одном классе вы можете максимально использовать предложение using для одного из них. Для другого вам понадобится полное имя или псевдоним. С частичными классами, поскольку каждое пространство имен и список использования операторов различны, можно разделить два набора функций на два отдельных файла.
using Library1 = The.Namespace.You.Need
илиglobal::Root.Of.Namespace