Every new .NET release brings performance improvements, but sometimes, it also brings breaking changes that can quietly break your code, such as the new field keyword.

It introduces a real risk of breaking changes if your codebase already uses a member named field.

What Problem Does field Solve?

Before C# 14, if you wanted to:

Then you could NOT use an auto property.

You had to explicitly declare a backing field:

private string _msg;

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

This is fine until you have dozens of properties with validation logic.

It becomes repetitive, noisy, and harder to maintain.

C# 14 Fixes This

With C# 14, you can now write:

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

The compiler automatically generates the backing field, and inside the accessor, you can reference it using the field keyword.

Examples Before & After C# 14

Before C# 14 (verbose version)

private int _age;

public int Age
{
    get => _age;
    set
    {
        if (value < 0)
            throw new ArgumentOutOfRangeException(nameof(value));
        _age = value;
    }
}

C# 14 version

public int Age
{
    get;
    set
    {
        if (value < 0)
            throw new ArgumentOutOfRangeException(nameof(value));
        field = value;
    }
}

Important: Possible Breaking Change!

Because field is now a contextual keyword, any existing type member named field can now conflict with it.

Example of a problem

public class User
{
    public string field;

    public string Name
    {
        get;
        set => field = value; // Which 'field' are we setting??
    }
}

This is ambiguous and confusing. Fix it by :

set => @field = value;

or

set => this.field = value;

or (best option) rename the old field 🤔