Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Можно разделить определение класса, структуры, интерфейса или члена по двум или нескольким исходным файлам. Каждый исходный файл содержит раздел определения типа или члена, а все части объединяются при компиляции приложения.
Частичные классы
Существует несколько ситуаций, когда желательно разделение определения класса.
- Объявление класса по отдельным файлам позволяет нескольким программистам одновременно работать над ним.
- Вы можете добавить код в класс, не воссоздавая исходный файл с автоматически сгенерированным кодом. Visual Studio использует этот подход при создании форм Windows Forms, кода оболочки веб-службы и т. д. Можно создать код, который использует эти классы, без необходимости изменения файла, созданного в Visual Studio.
- Генераторы источников могут создавать дополнительные функциональные возможности в классе.
Чтобы разделить определение класса, используйте модификатор ключевого слова partial. На практике каждый частичный класс обычно определяется в отдельном файле, что упрощает управление и расширение класса с течением времени.
В следующем Employee примере показано, как класс может быть разделен на два файла: Employee_Part1.cs и Employee_Part2.cs.
// This is in Employee_Part1.cs
public partial class Employee
{
public void DoWork()
{
Console.WriteLine("Employee is working.");
}
}
// This is in Employee_Part2.cs
public partial class Employee
{
public void GoToLunch()
{
Console.WriteLine("Employee is at lunch.");
}
}
//Main program demonstrating the Employee class usage
public class Program
{
public static void Main()
{
Employee emp = new Employee();
emp.DoWork();
emp.GoToLunch();
}
}
// Expected Output:
// Employee is working.
// Employee is at lunch.
Ключевое слово partial указывает, что другие части класса, структуры или интерфейса могут быть определены в пространстве имен. Все части должны использовать ключевое слово partial. Для формирования окончательного типа все части должны быть доступны во время компиляции. Все части должны иметь одинаковую доступность, например public, private и т. д.
Если какая-либо из частей объявлена абстрактной, то весь тип будет считаться абстрактным. Если какая-либо из частей объявлена запечатанной, то весь тип будет считаться запечатанным. Если какая-либо из частей объявляет базовый тип, то весь тип унаследует данный класс.
Все части, указывающие базовый класс, должны быть согласованы друг с другом, а части, не использующие базовый класс, все равно наследуют базовый тип. Части могут указывать различные базовые интерфейсы, и окончательный тип будет реализовывать все интерфейсы, перечисленные во всех частичных объявлениях. Любые члены класса, структуры или интерфейса, объявленные в частичном определении, доступны для всех остальных частей. Окончательный тип представляет собой комбинацию всех частей, выполненную во время компиляции.
Примечание.
Модификатор partial недоступен для объявлений делегата или перечисления.
В следующем примере показано, что вложенные типы могут быть частичными, даже если тип, вложенный внутри, не является частичным.
class Container
{
partial class Nested
{
void Test() { }
}
partial class Nested
{
void Test2() { }
}
}
Во время компиляции атрибуты определений разделяемого типа объединяются. В качестве примера рассмотрим следующие объявления:
[SerializableAttribute]
partial class Moon { }
[ObsoleteAttribute]
partial class Moon { }
Они эквивалентны следующим объявлениям:
[SerializableAttribute]
[ObsoleteAttribute]
class Moon { }
Следующие элементы объединяются из всех определений частичных типов:
- КОММЕНТАРИИ XML. Однако если оба объявления частичного члена включают примечания, будут включены только комментарии от реализующего члена.
- интерфейсы
- атрибуты универсального типа-параметра
- атрибуты классов
- члены
В качестве примера рассмотрим следующие объявления:
partial class Earth : Planet, IRotate { }
partial class Earth : IRevolve { }
Они эквивалентны следующим объявлениям:
class Earth : Planet, IRotate, IRevolve { }
Ограничения
При работе с определениями частичного класса существует несколько правил:
- Все определения частичного типа, являющиеся частями одного типа, должны быть изменены с помощью
partial. Например, следующие объявления класса приведут к появлению ошибки:public partial class A { } //public class A { } // Error, must also be marked partial -
partialмодификатор может отображаться непосредственно перед ключевым словомclass,structилиinterface. - В определениях частичных типов могут присутствовать вложенные частичные типы, что показано в следующем примере:
partial class ClassWithNestedClass { partial class NestedClass { } } partial class ClassWithNestedClass { partial class NestedClass { } } - Все определения разделяемого типа, являющиеся частями одного и того же типа, должны быть определены в одной сборке и в одном модуле (EXE-файл или DLL-файл). Частичные определения не могут охватывать несколько модулей.
- Имя класса и параметры универсального типа должны совпадать на всех частичных определениях типов. Универсальные типы могут быть частичными. Все объявления разделяемого типа должны использовать одинаковые имена параметров в одном и том же порядке.
- Следующие ключевые слова для определения частичного типа являются необязательными, но если они присутствуют в одном определении частичного типа, то же самое должно быть указано в другом частичном определении для того же типа:
- общественный
- частный
- защищено
- внутренний
- абстрактный
- запечатанный
- базовый класс
- модификатор new (вложенные части)
- универсальные ограничения
Дополнительные сведения см. в разделе Ограничения параметров типа.
Примеры
В следующем примере поля и конструктор Coords класса объявляются в одном определении разделяемого класса (Coords_Part1.cs), а PrintCoords метод объявляется в другом определении разделяемого класса (Coords_Part2.cs). Это разделение показывает, как частичные классы можно разделить на несколько файлов для упрощения обслуживания.
// This is in Coords_Part1.cs
public partial class Coords
{
private int x;
private int y;
public Coords(int x, int y)
{
this.x = x;
this.y = y;
}
}
// This is in Coords_Part2.cs
public partial class Coords
{
public void PrintCoords()
{
Console.WriteLine("Coords: {0},{1}", x, y);
}
}
// Main program demonstrating the Coords class usage
class TestCoords
{
static void Main()
{
Coords myCoords = new Coords(10, 15);
myCoords.PrintCoords();
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
// Output: Coords: 10,15
В следующем примере показано, что можно также разработать разделяемые структуры и интерфейсы.
partial interface ITest
{
void Interface_Test();
}
partial interface ITest
{
void Interface_Test2();
}
partial struct S1
{
void Struct_Test() { }
}
partial struct S1
{
void Struct_Test2() { }
}
Частичные члены
Частичный класс или структуру может содержать частичный элемент. Одна часть класса содержит сигнатуру члена. Реализацию можно определить в той же части или в другой части.
Реализация не требуется для частичного метода, если подпись подчиняется следующим правилам:
- Объявление не включает модификаторы доступа. Метод имеет
privateдоступ по умолчанию. - Тип возвращаемого значения —
void. - Ни один из параметров не имеет
outмодификатора. - Объявление метода не может содержать ни одного из следующих модификаторов:
Метод и все вызовы метода удаляются во время компиляции при отсутствии реализации.
Любой член, который не соответствует всем этим ограничениям, включая конструкторы, свойства, индексаторы и события, должен предоставлять реализацию. Эта реализация может быть предоставлена генератором источника. Частичные свойства нельзя реализовать с помощью автоматически реализованных свойств. Компилятор не может различать автоматическое свойство и объявление частичного свойства.
Начиная с C# 13, реализация частичного свойства может использовать свойства с поддерживающими полями для определения объявления реализации. Свойство с поддержкой поля предоставляет краткий синтаксис, где ключевое слово field обращается к синтезированному компилятором служебному полю для свойства. Например, можно написать следующий код:
// in file1.cs
public partial class PropertyBag
{
// Defining declaration
public partial int MyProperty { get; set; }
}
// In file2.cs
public partial class PropertyBag
{
// Defining declaration
public partial int MyProperty { get => field; set; }
}
Вы можете использовать field как в методе доступа get, так и в методе доступа set, или в обоих.
Частичные члены позволяют разработчику одной части класса объявить члена. Реализующий другую часть класса может определить этот элемент. Существует два сценария, в которых это разделение полезно: шаблоны, создающие стандартный код и генераторы источников.
- Код шаблона: шаблон резервирует имя и подпись метода, чтобы созданный код мог вызвать метод. Эти методы придерживаются ограничений, которые позволяют разработчику решить, следует ли реализовать этот метод. Если метод не реализован, компилятор удаляет сигнатуру метода и все вызовы метода. Вызовы метода, включая любые результаты, которые могли бы произойти от оценки аргументов в вызовах, не имеют эффекта во время выполнения. Поэтому любой код в частичном классе может свободно использовать частичный метод, даже если реализация не предоставлена. Если метод вызывается, но не реализуется, не возникает никаких ошибок во время компиляции или времени выполнения.
- Генераторы источников: генераторы источников предоставляют реализацию для членов. Разработчик может добавить объявление члена (часто с атрибутами, считываемыми генератором источника). Разработчик может написать код, вызывающий эти элементы. Генератор источника выполняется во время компиляции и обеспечивает реализацию. В этом сценарии ограничения для частично реализованных участников, которые могут не быть внедрены, часто не соблюдаются.
// Definition in file1.cs
partial void OnNameChanged();
// Implementation in file2.cs
partial void OnNameChanged()
{
// method body
}
- Объявления частичных элементов должны начинаться с контекстного ключевого слова partial.
- Частичные подписи членов в обеих частях частичного типа должны соответствовать.
- Частичный член может иметь статические и небезопасные модификаторы.
- Частичный элемент может быть обобщённым. Ограничения должны совпадать с определением и реализацией объявления члена. Имена параметров и параметров типов не обязаны совпадать в объявлении реализации и в определяющем.
- Можно создать делегат для частичного метода, который определен и реализован, но не для частичного метода, который не имеет реализации.
Спецификация языка C#
Дополнительные сведения см. в разделе "Частичные типы " и частичные методы в спецификации языка C#. Спецификация языка является окончательным источником синтаксиса и использования языка C#. Новые функции для частичных элементов определяются в спецификациях функций для расширения частичных методов, частичных свойств и индексаторов, а также частичных событий и конструкторов.