C# 13 will introduce an exciting feature to boost developer productivity and code clarity: semi-auto properties. This new feature solves the trade-off between the ease of auto-implemented properties with the versatility of manual ones.
Reminder: Auto-Property and Backing Field
Here is a usual C# auto-property:
1 2 3 |
public class Person { public int BirthYear { get; set; } } |
If we compile this code we can see that a backing field is created for us by the C# compiler:
1 2 3 4 5 6 7 8 9 10 11 |
public class Person { [CompilerGenerated] [DebuggerBrowsable(DebuggerBrowsableState.Never)] private int <BirthYear>k__BackingField; public int BirthYear { [CompilerGenerated] get { return <BirthYear>k__BackingField; } [CompilerGenerated] set { <BirthYear>k__BackingField = value; } } } |
Problem solved by the C# 13 Semi Auto Properties
Including logic in a property’s getter or setter is common for handling validation, default value, computation, notification, or lazy loading. However, this requires defining the backing field manually, as auto-property syntax can’t be used:
1 2 3 4 5 6 7 8 9 10 11 12 |
using System; public class Person { int _birthYear; public int BirthYear { get { return _birthYear; } set { if (value < 0) // Validation code throw new ArgumentOutOfRangeException("Age cannot be negative."); _birthYear = value; } } } |
The C# 13 Semi Auto Properties syntax proposes to skip the backing field explicit declaration and use the new C# keyword field
to refer to it:
1 2 3 4 5 6 7 8 9 10 11 |
using System; public class Person { public int BirthYear { get => field; set { if (value < 0) // Validation code throw new ArgumentOutOfRangeException("Age cannot be negative."); field = value; } } } |
Notice that in the sample code above we cannot use the auto-accessor get;
instead of get => field;
or get { return field; }
. I hope this is a limitation that will be fixed in the final C# 13 version:
Benefits of C# 13 Semi Auto Properties
- Reduced Boilerplate Code: Eliminates the need for private backing fields. This results in more concise code.
- Improved Readability: We don’t need to care for the name of the backing field, the
field
keyword standard makes the code clearer. -
Property-Scoped Field: A private property field is only visible within the property, preventing unintended use elsewhere in the parent class. This encapsulation benefit might be the main one of C# 13 Semi Auto Properties because this solves quite an error-prone situation.
Potential field Keyword Breaking Change
field
, it takes precedence over the new field
keyword:int field;
:Sincefield
is a keyword and not an identifier, it can only be “shadowed” by an identifier using the normal keyword-escaping route:@field
. All identifiers namedfield
declared within property accessor bodies can safeguard against breaks when upgrading from C# versions prior to 13 by adding the initial@
.
Conclusion
field
is another welcomed tiny and subtle language improvement. We will likely soon see a Roslyn Analyzer that identifies opportunities to simplify code using the field
keyword, along with an automatic code fixer to apply this syntax across your application.
Semi auto?? That sounds scary, and as a Democrat I lack basic cognitive reasoning or even the faintest modicum of self reliance, so I can’t be bothered to read further or educate myself, so we should just ban it! Think of the children! No one needs a high capacity assault semi auto property!
This does mean that you should never, and I mean never ever, use the variable named field in your source any more (your private field should be named _field anyway) as that could potentially alter the behavior of your code.