C# 13 and C# 14: Locks and Field-Backed Properties

Recent C# language roadmaps introduce major improvements to developer ergonomics and runtime efficiency, spotlighting dedicated lock objects and field-backed properties. While C# 13 officially updates the lock statement to utilize a high-performance synchronization primitive in .NET 9, the long-awaited field keyword for semi-auto-implemented properties was introduced as a preview feature in C# 13 and targeted for general release in C# 14. Together, these features streamline codebases by removing redundant boilerplate fields and modernizing thread synchronization.

Modern Lock Objects in C# 13

Before C# 13, thread synchronization using the lock statement relied on System.Threading.Monitor under the hood. Developers routinely instantiated generic object instances purely to act as synchronization tokens:

private readonly object _syncRoot = new();

public void Process()
{
    lock (_syncRoot)
    {
        // Critical section
    }
}

This pattern carried drawbacks, including potential overhead and the lack of type safety, as any reference type could be locked, leading to potential deadlocks.

C# 13 and .NET 9 introduce the System.Threading.Lock type. The C# 13 compiler natively recognizes this type when used inside a lock statement:

private readonly System.Threading.Lock _lock = new();

public void Process()
{
    lock (_lock)
    {
        // Critical section
    }
}

When the compiler detects a System.Threading.Lock instance, it alters its code generation. Instead of calling Monitor.Enter and Monitor.Exit, it invokes _lock.EnterScope(). This method returns a ref struct that implements a Dispose method, exiting the lock automatically when execution leaves the block. This specialized pattern avoids allocation, achieves faster acquisition times, and enables companion code analyzers to warn developers if a Lock object is cast to object or misused.

Field-Backed Properties in C# 13 and C# 14

For years, developers have faced an all-or-nothing dilemma with properties: use concise auto-implemented properties (public string Name { get; set; }), or manually declare a private backing field if even a single line of validation or notification logic is required:

private string _name;
public string Name
{
    get => _name;
    set => _name = value ?? throw new ArgumentNullException(nameof(value));
}

The field-backed property feature resolves this dilemma by introducing the contextual keyword field, which grants direct access to the compiler-synthesized backing field inside property accessors:

public string Name
{
    get => field;
    set => field = value ?? throw new ArgumentNullException(nameof(value));
}

This syntax is useful for domain model validation, whitespace trimming, and triggering INotifyPropertyChanged events without polluting the enclosing type with explicit private field declarations.

Timeline and Breaking Changes

While the Lock object feature fully shipped with C# 13 and .NET 9, field-backed properties encountered migration challenges during development. Introducing field as a contextual keyword posed a breaking change for existing codebases that already contained members, local variables, or parameters named field.

To ensure safety and resolve naming ambiguities (such as allowing @field to reference an existing identifier versus the backing field), Microsoft made field-backed properties an opt-in preview feature in C# 13. Full adoption, finalized disambiguation rules, and general availability are targeted for C# 14.