.NETPro #18 | Special Edition: Master Partial Properties and Indexers in C# in Part 3 of Our Exclusive Series with Mark J. Price
Partial Types and Members: Breaking Apart and Reassembling C# Classes: Part 3
We’ve come a long way in our journey through the Partial Types and Members: Breaking Apart and Reassembling C# Classes series with Mark J. Price. In Parts 1 and 2, we saw how partial classes help organize sprawling projects and how partial methods let us slip in optional, zero-cost hooks for custom logic.
Now it’s time to bring that same flexibility to partial properties and indexers. They extend the same split-and-merge magic to property accessors, letting you declare a property in one file and implement its getter and setter in another, with the new field keyword managing the backing storage for you.
It’s a small change with a big impact, especially if you love writing clean, maintainable code or enjoy working with source generators that make development smoother and more enjoyable.
Here’s a sneak peek at what’s waiting for you in this issue:
➡️ Understand how partial properties and indexers extend the partial pattern to property accessors in C# 13
➡️ Learn how the new field keyword simplifies backing field management in getters and setters
➡️ Explore practical examples of using partial properties for validation, notifications, and MVVM scenarios
➡️ See how source generators and frameworks benefit from cleaner, more maintainable extensibility points
➡️ Wrap up with a quick Q&A to test your knowledge and reinforce what you’ve learned
Meet the Expert!
Before you jump in, check out these highlights from our last edition, in case you missed them:
➡️ Explore what’s new in .NET 10 RC2 and how it boosts performance and developer productivity
➡️ Check out the new .NET Security Group, aimed at enhancing ecosystem safety and boosting developer collaboration on security
➡️ Watch Nick Chapsas build awesome .NET consoles using the RazorConsole library
➡️ Watch Ed Anderson explain Visual Studio 2026 performance and how to keep your IDE running smoothly
➡️ Read Andrew Lock’s guide on adding metadata to fallback endpoints in ASP.NET Core
Cheers!
Adrija Mitra
Editor-in-Chief
📱 Partial Properties & Indexers (C# 13): Clean Accessors + the ‘field’ Keyword
Want to revisit the first two parts of this series before diving in? Check them out here: [Part 1] and [Part 2].
C# 13 introduced partial properties (and by extension, indexers) to extend the partial pattern to property getters and setters. This feature is designed for scenarios involving source generators or frameworks that need to inject logic into property accessors.
Before C# 13, if a source generator wanted to inject code when a property was accessed or modified, there were few good options apart from using partial methods or rewriting IL. With partial properties, you can declare a property in one part of a partial class (essentially saying, “this property exists, is of this type, and has these accessors”) and then implement the get and/or set logic in another part. This works similarly to partial methods: one part provides the signature of the property, while another part provides the bodies of the accessors.
However, properties have some unique considerations:
A property usually has a backing field to store its value, unless it is computed each time. With an auto-implemented property (for example,
public string Name { get; set; }), the compiler generates a hidden backing field for you.If we split a property’s definition, we need a way for the setter and getter implementations to refer to that backing storage.
Because of this, partial properties cannot be automatically implemented on the defining side. The C# compiler does not allow a partial property to be declared as completely auto-implemented with no body on either side, since it would not know whether { get; set; } represents an auto-property or just a declaration meant to be implemented elsewhere.
Instead, the typical pattern is:
In one file, declare the property with the partial modifier and provide either no body or an auto-property-like empty body.
In the other file, also declare it as partial and include the actual code in the
getand/orsetaccessors.
To make this possible, C# 13 introduced a new contextual keyword, field, for use inside property accessors. The field keyword acts as a placeholder for the backing field of this property. It allows you to write an implementation without explicitly declaring a private field. The compiler ensures that both the defining and implementing parts refer to the same hidden field.
Check out the official documentation to dive deeper: Partial Classes and Members - C# | Microsoft Learn.
📝 Spotted something worth calling out? We’d love to hear about it—just drop us a quick note through this 1-min survey. We’re all ears!
Example: Department property with validation
Let’s say our Employee class has a Department property. Perhaps a source generator wants to ensure that if someone is assigned to the Macrodata Refinement (MDR) department, a special message is logged (because MDR is mysterious). We can declare the property in one partial file and implement the setter logic in another, as shown in the following code:
// File: Employee.Definition.cs
public partial class Employee
{
// Defining declaration of a partial property
public partial string Department { get; set; }
}
// File: Employee.Implementer.cs
public partial class Employee
{
// Implementing declaration with actual logic
public partial string Department
{
get => field; // ‘field’ represents the backing field for Department
set
{
// Use the implicit backing field via ‘field’
field = value;
if (value == “Macrodata Refinement”)
{
Console.WriteLine($”[Notice] {Name} is assigned to the secretive MDR department.”);
}
}
}
}In the preceding code, note the following:
In
Employee.Definition.cs, we declarepublic partial string Department { get; set; }. This looks like an auto-property, but because it is markedpartial, the compiler treats it as incomplete and expects to find an implementation elsewhere.In
Employee.Implementer.cs, we again declarepublic partial string Department, but this time we provide bodies forgetandset. We useget => field;, and in the setter, we usefield = value;. The keywordfieldis a stand-in for the compiler-generated backing field that holds the department name. The effect is that when you setemployee.Department = “Macrodata Refinement”, the code in our partial setter runs: it assigns the value and then, if the department is“Macrodata Refinement”, prints the notice. If you set it to another value, it simply assigns the field with no extra output. From outside the class,Departmentbehaves like a normal property.
Without partial properties, doing something like this often meant either writing the entire property yourself (losing auto-property convenience) or using a partial method workaround. For example, some MVVM libraries generate an OnPropertyChanged partial method call in property setters.
Partial properties provide a more natural way to express this kind of split logic.
A real-world scenario is implementing INotifyPropertyChanged: a source generator could declare a partial property and implement the setter to raise PropertyChanged events. Partial properties make certain patterns in MVVM frameworks easier and more expressive.
Important notes for partial properties
Keep these points in mind when working with partial properties:
The
fieldkeyword is only usable within the accessor of a field-backed property (as in the above example). It serves as a shortcut so you do not have to declare a separate private field to store the value. You can usefieldin either or both accessors as needed.
Note
The
fieldkeyword is a preview feature in C# 13. You must target .NET 9 and set the<LangVersion>element topreviewin your project file to use thefieldcontextual keyword. In C# 14 and later, thefieldkeyword is available as a standard feature. Learn more about the field keyword here: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/field
If you have a property with only a getter (a read-only property), you can still make it partial, but the implementing part must provide the getter’s body, perhaps computing the value dynamically or retrieving it from another source.
You cannot create a partial auto-property that is fully implemented by the compiler alone. At least one part must provide logic. In our example, the defining part’s
{ get; set; }isn’t actually implementing anything; it’s more like a placeholder indicating that the property has bothgetandsetaccessors. The second part performs the actual work.The defining and implementing parts must agree on the property’s type and on whether it has
get,set, or both. For example, you cannot declare a property asread-writein one part andread-onlyin another.
The introduction of partial properties is primarily intended to support source generators and framework code in creating cleaner APIs. For example, the .NET team updated the Regex source generator in C# 11 and .NET 7 to use partial methods, as I did in the 7th edition of my book. With C# 13 and .NET 9, they can offer a partial property if that feels more natural (for example, a generated partial Regex GeneratedRegex { get; } property instead of a method). I demonstrate this in the 9th edition of my book.
As a developer, you might not manually write partial properties every day, but understanding how they work helps you read and reason about code generated by tools. You can also use them in advanced scenarios within your own libraries.
📝 Spotted something worth calling out? We’d love to hear about it—just drop us a quick note through this 1-min survey. We’re all ears!
⏱️ Quick Q&A Corner
Quick bites to level up your understanding
Q1: Why do partial properties matter for source generators?
A: Source generators often need to inject logic into properties, such as validation or notifications, without replacing the entire property. Partial properties let generators declare a property shell and inject behavior in another part. This keeps generated and user-written code neatly separated, avoids reflection or IL rewriting, and makes generated APIs feel hand-written and easy to maintain.
Q2: What problem does the field keyword actually solve?
A: Before C# 13, if you wanted to customize an auto-property’s accessor, you had to define your own backing field manually. The new field keyword removes that boilerplate. It gives you direct access to the property’s implicit backing field inside get or set blocks, so you can modify behavior while keeping the simplicity and consistency of an auto-implemented property.
Q3: How do partial properties differ from partial methods?
A: Partial methods split a method’s definition and optional implementation, while partial properties extend that idea to property accessors. The key difference is that a partial method can be omitted entirely, but a partial property must have at least one accessor body. This ensures a consistent storage model through field while still supporting clean extensibility and generated accessor logic.
Q4: Can you mix custom logic with auto-property behavior using partial properties?
A: Yes. You can let the compiler handle the backing field and still add custom logic. For example, you might validate input, trigger events, or log changes in a partial setter while using field for the actual assignment. It is a balanced approach that combines auto-property convenience with the flexibility to extend behavior when needed.
Q5: How might frameworks and libraries use partial properties?
A: Frameworks such as MVVM or ORMs can use partial properties to generate data-binding or validation code automatically. A generator might declare a partial property and implement its setter to raise PropertyChanged events. This eliminates repetitive boilerplate and lets developers focus on logic instead of wiring, resulting in cleaner, more maintainable APIs.
That’s a wrap on partial properties and indexers. You’ve seen how C# 13 brings clean, customizable accessors to life with the field keyword and how this pattern works beautifully with generators and MVVM.
In the next part, we will look ahead to partial events planned for C# 14, explore why separating add and remove logic matters, and take a peek at partial instance constructors to see how object creation fits into the partial story. Stay tuned for Part 4, releasing next month!
And that’s a wrap 🎬
We’re glad you joined us for this edition of .NETPro!
If you have any thoughts, questions, or feedback on this edition, or if you’d like to share what you’d love to see next, feel free to take our 1-min survey and drop us a note. We’d love to hear from you.
Thanks for following along. Until next time, keep learning and keep building.



