Разделяемые классы и методы (Руководство по программированию в C#)Partial Classes and Methods (C# Programming Guide)

Можно разделить определение класса, структуры, интерфейса или метода между двумя или более исходными файлами.It is possible to split the definition of a class, a struct, an interface or a method over two or more source files. Каждый исходный файл содержит часть определения класса или метода, а во время компиляции приложения все части объединяются.Each source file contains a section of the type or method definition, and all parts are combined when the application is compiled.

Разделяемые классыPartial Classes

Существует несколько ситуаций, когда желательно разделение определения класса.There are several situations when splitting a class definition is desirable:

  • При работе над большими проектами распределение класса между различными файлами позволяет нескольким программистам работать с ним одновременно.When working on large projects, spreading a class over separate files enables multiple programmers to work on it at the same time.

  • При работе с использованием автоматически создаваемого источника код можно добавлять в класс без повторного создания файла источника.When working with automatically generated source, code can be added to the class without having to recreate the source file. Visual Studio использует этот подход при создании форм Windows Forms, кода оболочки веб-службы и т. д.Visual Studio uses this approach when it creates Windows Forms, Web service wrapper code, and so on. Можно создать код, который использует эти классы, без необходимости изменения файла, созданного в Visual Studio.You can create code that uses these classes without having to modify the file created by Visual Studio.

  • Чтобы разделить определение класса, используйте модификатор ключевого слова partial, как показано ниже:To split a class definition, use the partial keyword modifier, as shown here:

    public partial class Employee
    {
        public void DoWork()
        {
        }
    }
    
    public partial class Employee
    {
        public void GoToLunch()
        {
        }
    }
    

Ключевое слово partial указывает, что другие части класса, структуры или интерфейса могут быть определены в пространстве имен.The partial keyword indicates that other parts of the class, struct, or interface can be defined in the namespace. Все части должны использовать ключевое слово partial.All the parts must use the partial keyword. Для формирования окончательного типа все части должны быть доступны во время компиляции.All the parts must be available at compile time to form the final type. Все части должны иметь одинаковые модификаторы доступа, например public, private и т. д.All the parts must have the same accessibility, such as public, private, and so on.

Если какая-либо из частей объявлена абстрактной, то весь тип будет считаться абстрактным.If any part is declared abstract, then the whole type is considered abstract. Если какая-либо из частей объявлена запечатанной, то весь тип будет считаться запечатанным.If any part is declared sealed, then the whole type is considered sealed. Если какая-либо из частей объявляет базовый тип, то весь тип будет наследовать данный класс.If any part declares a base type, then the whole type inherits that class.

Все части, указывающие базовый класс, должны быть согласованы друг с другом, а части, не использующие базовый класс, все равно наследуют базовый тип.All the parts that specify a base class must agree, but parts that omit a base class still inherit the base type. Части могут указывать различные базовые интерфейсы, и окончательный тип будет реализовывать все интерфейсы, перечисленные во всех разделяемых объявлениях.Parts can specify different base interfaces, and the final type implements all the interfaces listed by all the partial declarations. Любые члены класса, структуры или интерфейса, объявленные в разделяемом объявлении, доступны для всех остальных частей.Any class, struct, or interface members declared in a partial definition are available to all the other parts. Окончательный тип представляет собой комбинацию всех частей, выполненную во время компиляции.The final type is the combination of all the parts at compile time.

Примечание

Модификатор partial недоступен в объявлениях делегатов или перечислений.The partial modifier is not available on delegate or enumeration declarations.

В следующем примере показано, что вложенные типы могут быть разделяемыми, даже если тип, в который они вложены, не является разделяемым.The following example shows that nested types can be partial, even if the type they are nested within is not partial itself.

class Container
{
    partial class Nested
    {
        void Test() { }
    }
    partial class Nested
    {
        void Test2() { }
    }
}

Во время компиляции атрибуты определений разделяемого типа объединяются.At compile time, attributes of partial-type definitions are merged. В качестве примера рассмотрим следующие объявления:For example, consider the following declarations:

[SerializableAttribute]
partial class Moon { }

[ObsoleteAttribute]
partial class Moon { }

Они эквивалентны следующим объявлениям:They are equivalent to the following declarations:

[SerializableAttribute]
[ObsoleteAttribute]
class Moon { }

Следующие элементы объединяются из всех определений разделяемого типа:The following are merged from all the partial-type definitions:

  • XML-комментарииXML comments

  • интерфейсыinterfaces

  • атрибуты параметров универсального параметраgeneric-type parameter attributes

  • атрибуты классовclass attributes

  • членыmembers

В качестве примера рассмотрим следующие объявления:For example, consider the following declarations:

partial class Earth : Planet, IRotate { }
partial class Earth : IRevolve { }

Они эквивалентны следующим объявлениям:They are equivalent to the following declarations:

class Earth : Planet, IRotate, IRevolve { }

ОграниченияRestrictions

Имеется несколько правил, которые необходимо выполнять при работе с определениями разделяемого класса.There are several rules to follow when you are working with partial class definitions:

  • Все определения разделяемого типа, являющиеся частями одного типа, должны изменяться с использованием типа partial.All partial-type definitions meant to be parts of the same type must be modified with partial. Например, следующие объявления класса приведут к появлению ошибки:For example, the following class declarations generate an error:

    public partial class A { }
    //public class A { }  // Error, must also be marked partial
    
  • Модификатор partial должен находиться непосредственно перед ключевыми словами class, struct или interface.The partial modifier can only appear immediately before the keywords class, struct, or interface.

  • В определениях разделяемого типа могут присутствовать вложенные разделяемые типы, что показано в следующем примере:Nested partial types are allowed in partial-type definitions as illustrated in the following example:

    partial class ClassWithNestedClass
    {
        partial class NestedClass { }
    }
    
    partial class ClassWithNestedClass
    {
        partial class NestedClass { }
    }
    
  • Все определения разделяемого типа, являющиеся частями одного и того же типа, должны быть определены в одной сборке и в одном модуле (EXE-файл или DLL-файл).All partial-type definitions meant to be parts of the same type must be defined in the same assembly and the same module (.exe or .dll file). Разделяемые определения не могут находиться в разных модулях.Partial definitions cannot span multiple modules.

  • Имя класса и параметры универсального типа должны соответствовать всем определениям разделяемого типа.The class name and generic-type parameters must match on all partial-type definitions. Универсальные типы могут быть разделяемыми.Generic types can be partial. Все объявления разделяемого типа должны использовать одинаковые имена параметров в одном и том же порядке.Each partial declaration must use the same parameter names in the same order.

  • Приведенные ниже ключевые слова необязательно должны присутствовать в определении разделяемого типа, но если они присутствуют в одном определении разделяемого типа, то не должны конфликтовать с ключевыми словами, указанными в других определениях того же разделяемого типа.The following keywords on a partial-type definition are optional, but if present on one partial-type definition, cannot conflict with the keywords specified on another partial definition for the same type:

Дополнительные сведения см. в разделе Ограничения параметров типа.For more information, see Constraints on Type Parameters.

Пример 1Example 1

ОписаниеDescription

В следующем примере поля и конструктор класса Coords объявлены в одном определении разделяемого класса, а член PrintCoords — в другом определении разделяемого класса.In the following example, the fields and the constructor of the class, Coords, are declared in one partial class definition, and the member, PrintCoords, is declared in another partial class definition.

КодCode

public partial class Coords
{
    private int x;
    private int y;

    public Coords(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
}

public partial class Coords
{
    public void PrintCoords()
    {
        Console.WriteLine("Coords: {0},{1}", x, y);
    }

}

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

Пример 2Example 2

ОписаниеDescription

В следующем примере показано, что можно также разработать разделяемые структуры и интерфейсы.The following example shows that you can also develop partial structs and interfaces.

КодCode

partial interface ITest
{
    void Interface_Test();
}

partial interface ITest
{
    void Interface_Test2();
}

partial struct S1
{
    void Struct_Test() { }
}

partial struct S1
{
    void Struct_Test2() { }
}

Разделяемые методыPartial Methods

Разделяемый класс или структура могут содержать разделяемый метод.A partial class or struct may contain a partial method. Одна часть класса содержит сигнатуру метода.One part of the class contains the signature of the method. В той же или в другой части можно определить дополнительную реализацию.An optional implementation may be defined in the same part or another part. Если реализация не предоставлена, метод и все вызовы метода удаляются во время компиляции.If the implementation is not supplied, then the method and all calls to the method are removed at compile time.

Разделяемые методы позволяют разработчику одной части класса определить метод, схожий с событием.Partial methods enable the implementer of one part of a class to define a method, similar to an event. Разработчик другой части класса может решить, реализовывать этот метод или нет.The implementer of the other part of the class can decide whether to implement the method or not. Если метод не реализован, то компилятор удаляет сигнатуру метода и все вызовы этого метода.If the method is not implemented, then the compiler removes the method signature and all calls to the method. Вызовы метода, включая любые результаты, которые могли бы произойти от оценки аргументов в вызовах, не имеют эффекта во время выполнения.The calls to the method, including any results that would occur from evaluation of arguments in the calls, have no effect at run time. Таким образом, любой код в разделяемом классе может свободно использовать разделяемый метод, даже если реализация не предоставлена.Therefore, any code in the partial class can freely use a partial method, even if the implementation is not supplied. Во время компиляции и выполнения программы не возникнут никакие ошибки, если метод будет вызван, но не реализован.No compile-time or run-time errors will result if the method is called but not implemented.

Разделяемые методы особенно полезны для настройки автоматически созданного кода.Partial methods are especially useful as a way to customize generated code. Они позволяют зарезервировать имя и сигнатуру метода, чтобы автоматически созданный код мог вызвать метод, а разработчик мог сам решить, реализовывать этот метод или нет.They allow for a method name and signature to be reserved, so that generated code can call the method but the developer can decide whether to implement the method. Как и разделяемые классы, разделяемые методы позволяют организовать совместную работу автоматически созданного кода и кода, созданного человеком, без дополнительных затрат во время выполнения.Much like partial classes, partial methods enable code created by a code generator and code created by a human developer to work together without run-time costs.

Объявление разделяемого метода состоит из двух частей: определения и реализации.A partial method declaration consists of two parts: the definition, and the implementation. Они могут находиться в разных частях или в одной и той же части разделяемого класса.These may be in separate parts of a partial class, or in the same part. Если объявление реализации отсутствует, то компилятор оптимизирует код, удаляя как объявление определения, так и все вызовы метода.If there is no implementation declaration, then the compiler optimizes away both the defining declaration and all calls to the method.

// Definition in file1.cs
partial void onNameChanged();

// Implementation in file2.cs
partial void onNameChanged()
{
  // method body
}
  • Объявления разделяемого метода должны начинаться с контекстно-зависимого ключевого слова partial, а метод должен возвращать значение типа void.Partial method declarations must begin with the contextual keyword partial and the method must return void.

  • Разделяемые методы могут иметь параметры in или ref, но не out.Partial methods can have in or ref but not out parameters.

  • Разделяемые методы неявно имеют модификатор private и поэтому не могут иметь модификатор virtual.Partial methods are implicitly private, and therefore they cannot be virtual.

  • Разделяемые методы не могут иметь модификатор extern, поскольку наличие тела определяет, выполняется ли их определение или реализация.Partial methods cannot be extern, because the presence of the body determines whether they are defining or implementing.

  • Разделяемые методы могут иметь модификаторы static и unsafe.Partial methods can have static and unsafe modifiers.

  • Разделяемые методы могут быть универсальными.Partial methods can be generic. Ограничения налагаются на ту часть объявления разделяемого метода, где находится определение, и могут дополнительно повторяться в разделе реализации.Constraints are put on the defining partial method declaration, and may optionally be repeated on the implementing one. Имена параметров и типов параметров необязательно должны совпадать в объявлении реализации и в объявлении определения.Parameter and type parameter names do not have to be the same in the implementing declaration as in the defining one.

  • Можно использовать делегат в качестве определенного и реализованного разделяемого метода, но его нельзя использовать в качестве разделяемого метода, который только определен.You can make a delegate to a partial method that has been defined and implemented, but not to a partial method that has only been defined.

Спецификация языка C#C# Language Specification

Дополнительные сведения см. в разделе Разделяемые типы в Спецификации языка C#.For more information, see Partial types in the C# Language Specification. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.The language specification is the definitive source for C# syntax and usage.

См. такжеSee also