How to Use Partial Classes in C

This article provides a comprehensive guide to partial classes in C#, explaining what they are, why developers use them, and how to split a single class implementation across multiple files. You will learn the core compiler rules governing partial types and see practical code examples demonstrating how to organize and separate your code cleanly.

What Is a Partial Class?

In C#, a partial class allows the definition of a single class, struct, interface, or record to be divided across two or more source files. When the application is compiled, the C# compiler combines all partial sections into a single, cohesive type in the intermediate language (IL). This feature is purely a compile-time mechanism; at runtime, the class behaves identically to any standard class defined in a single file.

Developers primarily use partial classes to:

  • Separate Auto-Generated Code from Custom Logic: Tools like UI designers (Windows Forms, WPF) or ORMs (Entity Framework) place generated code in one file while developers write custom business logic in another. This prevents tool-generated updates from overwriting human-written code.
  • Facilitate Team Collaboration: Multiple developers can work on distinct aspects of a complex class simultaneously without causing merge conflicts.

Rules for Declaring Partial Classes

To split a class implementation successfully, your code must adhere to the following rules:

  1. Use the partial Modifier: Every part of the class definition must include the partial keyword directly before the class keyword.
  2. Match the Namespace and Type Name: All parts must exist within the exact same namespace and share the same identifier name.
  3. Consistent Accessibility: All parts must share the same access modifier (such as public, internal, or private). If any part is declared public, all other parts must also be public.
  4. Assembly Bounds: All parts must be compiled into the same assembly and module. You cannot split a partial class across different projects.
  5. Combined Inheritance and Interfaces: If any part implements an interface or inherits from a base class, the combined class inherits it. Base class declarations cannot conflict across parts.

How to Split a Class Implementation

To split a class implementation, create two or more .cs files in the same project and assign them the same namespace and class name with the partial modifier.

File 1: Employee.Core.cs

This file defines the primary properties and constructors.

namespace CompanyApp.Models
{
    public partial class Employee
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public decimal Salary { get; set; }

        public Employee(int id, string firstName, string lastName, decimal salary)
        {
            Id = id;
            FirstName = firstName;
            LastName = lastName;
            Salary = salary;
        }
    }
}

File 2: Employee.Methods.cs

This file contains the methods and business operations for the Employee type.

namespace CompanyApp.Models
{
    public partial class Employee
    {
        public string GetFullName()
        {
            return $"{FirstName} {LastName}";
        }

        public void ApplyRaise(decimal percentage)
        {
            if (percentage > 0)
            {
                Salary += Salary * (percentage / 100);
            }
        }
    }
}

Partial Methods

Partial classes can also contain partial methods. A partial method allows a declaration signature in one part of the class and an optional implementation in another part. If no implementation is provided, the compiler completely strips out the signature and all calls to that method, incurring zero runtime overhead.

public partial class Employee
{
    // Defined in File 1
    partial void OnSalaryChanged(decimal oldSalary, decimal newSalary);
}

public partial class Employee
{
    // Implemented in File 2 (optional)
    partial void OnSalaryChanged(decimal oldSalary, decimal newSalary)
    {
        System.Diagnostics.Debug.WriteLine($"Salary changed from {oldSalary} to {newSalary}");
    }
}

By applying the partial keyword, you cleanly organize large codebases, separate generated boilerplate from application logic, and maintain modular architecture across your C# projects.