Splitting the definition of a class, struct, interface, or record across multiple source files is possible using partial classes in C# (and by extension, in ASP.NET Core development). At compile time, the C# compiler merges all the components into a single type.
Uses of Partial Classes:
- A typical use case is separating user code from generated code. There are a lot of code-generation tools that you shouldn't touch by hand. These include ORM frameworks like Entity Framework Core, Windows Forms designers, ASP.NET Core scaffolding, and many more. You can avoid having your modifications erased when the code is regenerated by generating this code into a partial class. This allows you to define your own members (methods, properties, events) in another partial portion of the same class.
- Code Organisation for Big Classes: Dividing the definition into logical sections can make the code more readable and easier to maintain for classes that are quite large and have a lot of responsibilities. Without as many merge conflicts, developers can work on different sections of the class at the same time.
- When working in a UI development environment such as Windows Forms or WPF, it is common practice for the graphic designer to also generate the code for the UI elements. It is common practice to include this code in a partial class, which frees up another partial for implementing event handlers and other custom functionality.
How Partial Classes Work:
- The partial keyword is a modifier that can be used to define classes, structures, interfaces, or records. In C#, this tells the compiler that this type's definition is spread out across several files. The C# compiler uses a combinatorial search during compilation to find all partial declarations of the same type, which means they have the same name and namespace.
- To create a single full type definition, the compiler takes all the member declarations (fields, properties, methods, events, nested types, etc.) from each of the partial sections and combines them. It is irrelevant as to the sequence in which the component elements are assembled.
- To create a single full type definition, the compiler takes all the member declarations (fields, properties, methods, events, nested types, etc.) from each of the partial sections and combines them. It is irrelevant as to the sequence in which the component elements are assembled.
- To ensure accessibility, the members declared within each partial part are tagged with the appropriate accessibility modifiers, such as public, private, or internal.
Limitations:
- Whether it's entirely public or all internal, all partial declarations of a class, struct, or interface must have the same accessibility modifiers.
- The entire class is deemed abstract if even a single partial declaration is abstract.
- When a base class is included in a partial declaration, the entire class inherits from it.
- Having attributes in partial type definitions is possible. A partial type has all of its characteristics applied to it.
- Only before class, struct, interface, or record can the partial keyword be used.