Partial Properties: Completing the Partial Story

C# has supported partial methods since version 3, but properties were left out. This meant source generators had to use awkward workarounds — generating backing fields and calling partial methods from generated property bodies, or generating entire classes that developers then subclassed. C# 13 adds partial properties, giving generators a clean way to split property declarations and implementations across files.

The Syntax

A partial property has a declaring declaration (the signature) and an implementing declaration (the body):

Person.cs (hand-written)
public partial class Person
{
    public partial string Name { get; set; }
}

// File: Person.g.cs (source-generated)
public partial class Person
{
    private string _name = string.Empty;

    public partial string Name
    {
        get => _name;
        set
        {
            if (_name != value)
            {
                _name = value;
                OnPropertyChanged(nameof(Name));
            }
        }
    }
}

The declaring declaration uses semicolons for the accessor bodies (like an interface). The implementing declaration provides the actual logic.

Source Generator Use Cases

The primary motivation for partial properties is source generators. Consider the common MVVM pattern where every property needs change notification:

Example.cs
// What you write
public partial class SettingsViewModel
{
    [ObservableProperty]
    public partial string Theme { get; set; }

    [ObservableProperty]
    public partial int FontSize { get; set; }

    [ObservableProperty]
    public partial bool AutoSave { get; set; }
}

A source generator reads the [ObservableProperty] attribute and generates the implementations with backing fields, change notification, and validation — all without you writing boilerplate.

Before partial properties, generators like the MVVM Community Toolkit had to use a different pattern: you would declare a field with an attribute, and the generator would create the property. This worked but was unintuitive — fields are not properties, and the naming conventions felt backwards.

Partial Indexers

C# 13 also extends partial to indexers:

Example.cs
public partial class DataRow
{
    public partial object this[string column] { get; set; }
}

public partial class DataRow
{
    private readonly Dictionary<string, object> _values = new();

    public partial object this[string column]
    {
        get => _values[column];
        set => _values[column] = value;
    }
}

Rules

Partial properties follow similar rules to partial methods:

Attributes can appear on either declaration. The compiler merges them:

Example.cs
// Declaring
[JsonPropertyName("full_name")]
public partial string Name { get; set; }

// Implementing
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public partial string Name
{
    get => _name;
    set => _name = value;
}

// Effective: both attributes apply

Hand-Written Use Cases

Although partial properties are designed primarily for source generators, they can be useful in hand-written code when you want to separate interface from implementation in large partial classes:

PublicApi.cs
// The public surface
public partial class OrderService
{
    public partial IReadOnlyList<Order> PendingOrders { get; }
    public partial Order? CurrentOrder { get; }
}

// File: OrderService.Implementation.cs
public partial class OrderService
{
    private readonly List<Order> _pendingOrders = [];

    public partial IReadOnlyList<Order> PendingOrders
    {
        get => _pendingOrders.AsReadOnly();
    }

    public partial Order? CurrentOrder
    {
        get => _pendingOrders.FirstOrDefault(o => o.Status == OrderStatus.Processing);
    }
}

Impact on the Ecosystem

Partial properties are likely to influence how community libraries design their APIs. The MVVM Community Toolkit has already adopted them, and other frameworks that rely on source generation — ORM mappers, serialisation libraries, dependency injection containers — can now offer more natural property-based APIs instead of field-based or method-based workarounds.

For most developers, the benefit is indirect: libraries you use will become more ergonomic. If you write source generators yourself, partial properties are an essential addition to your toolkit.