C# 14 Field-Backed Properties and Null-Conditional Assignment — The Quietly Useful Upgrades
Two C# 14 features that pay for themselves in your next PR. No grand pattern, just less boilerplate where you had it.
Most C# language releases come with one big-ticket feature and a pile of paper-cut fixes. C# 14's headline is fine, but the paper-cut fixes are the ones I keep using.
The field keyword in property accessors.
Before:
private string _name = "";
public string Name
{
get => _name;
set => _name = value?.Trim() ?? throw new ArgumentNullException();
}
After:
public string Name
{
get;
set => field = value?.Trim() ?? throw new ArgumentNullException();
}
The backing field is implicit. The field keyword refers to it. You save one line per property and you stop the perennial "should this be _name or name?" debate. It compiles to the same IL. There's no clever cost.
Null-conditional assignment.
Before:
if (user is not null) user.LastSeen = DateTime.UtcNow;
After:
user?.LastSeen = DateTime.UtcNow;
Reads exactly how you'd say it. Fine for chained mutators on possibly-null parents.
Five places I've refactored these into and noticed the diff:
- ASP.NET Core action filters with optional headers —
context.HttpContext?.Items["UserId"] = id; - EF Core navigation property setters where the parent might be null on a partial load.
- POCO setters that previously needed manual backing fields just to validate input.
- Builder patterns where each step touches an optional inner object.
- Test setup code where you've got a half-constructed object you want to poke.
Two things to know before you sprinkle these everywhere:
The field keyword is contextual. It only acts as a backing-field reference inside a property accessor. Existing code that uses field as a variable name compiles fine. There's a Roslyn analyzer that warns when your usage is ambiguous — turn it on.
Extension members are in preview in C# 14. Don't ship them yet. They will change. The promise is good (static methods that look like instance methods, plus extension properties), but library authors will need a stable release before they refactor. Wait one more version.
Neither feature is exciting in isolation. Both are quietly useful in every file you touch. That's a better deal than most language features get.