- Home
- .NET tutorials
- What are partial classes in C# and why do we use them?
What are partial classes in C# and why do we use them?
Published: Monday 9 September 2024
A partial class can be used to split functionality across multiple files, each with the same namespace and class name.
MyClass.cs, it would generate a file with a MyClass class.
MyClass.Methods.cs, it would also generate a file with a MyClass class.
CS0101: The namespace 'x' already contains a definition for 'MyClass'
You can't have two classes of the same namespace and class name.
partial.
// MyClass.cs
public partial class MyClass
{
}
// MyClass.Methods.cs
public partial class MyClass
{
}
When you have multiple partial classes of the same namespace and class name, the compiler will merge all members from each of the partial classes into one single class.
MyClass.cs file, and then using it in a method inside the partial class within the MyClass.Methods.cs file.
// MyClass.cs
public partial class MyClass
{
public bool Ok { get; set; }
}
// MyClass.Methods.cs
public partial class MyClass
{
public bool IsItOk()
{
return Ok;
}
}
The partial keyword also works in a struct or an interface.
The rules around partial classes
Because the compiler will merge all the members for each of the partial classes into one single class, we need to follow the basic rules of a C# class.
All classes must be marked as partial
All partial classes of the same namespace and class name must include the partial keyword before the class declaration. If they don't, the following exception will appear:
CS0260: Missing partial modifier on declaration of type 'MyClass'; another partial declaration of this type exists
Where the partial keyword appears
The partial keyword must appear before the keyword class (or struct or interface if you are using that). If you try to add abstract after the partial keyword, the following exception will be thrown:
CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type.
// MyClass.cs
// Throws exception
public partial abstract class MyClass
{
public bool Ok { get; set; }
}
Namespaces must be the same
Namespaces must be the same for each of the partial classes.
Access modifiers must be the same
Access modifiers must be the same for all of the partial classes.
internal but leave the other one as public, the following exception would be thrown:
CS0262: Partial declarations of 'MyClass' have conflicting accessibility modifiers
// MyClass.cs
// Throws exception
internal partial class MyClass
{
public bool Ok { get; set; }
}
// MyClass.Methods.cs
public partial class MyClass
{
public bool IsItOk()
{
return Ok;
}
}
Abstract and sealed classes
If one of the partial classes is marked as abstract, the class is an abstract class even if it's not declared on any other partial classes. This rule also applies to the sealed keyword.
abstract, it would throw a compile exception.
// MyClass.cs
public abstract partial class MyClass
{
public bool Ok { get; set; }
}
// MyClass.Methods.cs
public partial class MyClass
{
public bool IsItOk()
{
return Ok;
}
}
// Program.cs
var a = new MyClass(); // Throws exception.
Attributes follow the same rule
Attributes will follow the same rule as the abstract and sealed keywords.
[Obsolete] attribute, the class would be declared as obsolete.
// MyClass.cs
[Obsolete]
public partial class MyClass
{
public bool Ok { get; set; }
}
// MyClass.Methods.cs
public partial class MyClass
{
public bool IsItOk()
{
return Ok;
}
}
// Program.cs
var a = new MyClass(); // Obsolete warning
You can only inherit one class
You can only inherit one class into a partial class. You will get this exception if you try to inherit more:
CS0263: Partial declarations of 'MyClass' must not specify different base classes
This is the same even if you separate the inheritance into each of the partial classes. The resulting exception will still be the same.
// MyBaseClass.cs
public class MyBaseClass {
}
// MyBaseClass2.cs
public class MyBaseClass2 {
}
// MyClass.cs
public partial class MyClass : MyBaseClass
{
public bool Ok { get; set; }
}
// MyClass.Methods.cs
public partial class MyClass
: MyBaseClass2 // This results in an exception.
{
public bool IsItOk()
{
return Ok;
}
}
You can implement multiple interfaces
Like with a normal C# class, you can implement multiple interfaces into a partial class.
// IBase.cs
public interface IBase {
void MyMethod();
}
// IBase2.cs
public interface IBase2 {
}
// MyClass.cs
public partial class MyClass : IBase
{
public bool Ok { get; set; }
}
// MyClass.Methods.cs
public partial class MyClass : IBase2
{
public bool IsItOk()
{
return Ok;
}
public MyMethod() {
// Will compile despite this method being implemented in IBase
}
}
Constructors must have different signatures
As per the rules in a C# class, you can't have multiple constructors of the same signature even if they appear in different partial classes.
CS0111: Type 'MyClass' already defines a member called 'MyClass' with the same parameter types
// MyClass.cs
public partial class MyClass
{
public MyClass() {
}
public bool Ok { get; set; }
}
// MyClass.Methods.cs
public partial class MyClass
{
public MyClass() {
// Already a parameterless constructor in MyClass.cs, so throws an exception.
}
public bool IsItOk()
{
return Ok;
}
}
Partial members
It's also possible to add partial members to a partial class.
Abc without an implementation. You can add this implementation into another partial class as long as the namespace and class match.
// MyClass.cs
public partial class MyClass
{
partial void Abc();
}
// MyClass.Methods.cs
public partial class MyClass
{
partial void Abc()
{
// Add implementation in here.
}
}
Why use partial classes in the first place?
Partial classes are good if you have multiple developers working on the same class. One developer could work on one file, whilst another could work on another file.
Related tutorials
Are C# 14's new features worth updating your app to .NET 10?
Discover the new features in C# 14 - from extension members to the field keyword - and find out whether upgrading your app to .NET 10 is really worth it.