Field keyword in C# 14

August 15th 2025 C# 14 C# .NET

The next C# 14 feature I took a closer look at was the field keyword. Similarly to the null-conditional assignment, it can reduce some of the boilerplate code you need to write. But it's not just syntactic sugar. You might need less private fields in your classes thanks to it.

In C# 3, automatically implemented properties have been introduced so that properties could be created without having to declare a backing field for storing the property value. Instead, the compiler generates such a backing field on its own and prevents access to it from code:

public int NonValidatedProperty { get; set; }

For such properties, you can specify different access modifiers for the getter and the setter, but that's about it. If you want to add any custom code to the getter or the setter, e.g., to add validation, you have to implement a full property with your own backing field:

private int validatedPropertyValue;
public int ValidatedProperty
{
    get { return validatedPropertyValue; }
    set
    {
        validatedPropertyValue =
            value >= 0
                ? value
                : throw new ArgumentOutOfRangeException(
                    nameof(value),
                    "The value must be non-negative."
                );
    }
}

However, by doing this, the code outside the property can also access the backing field. Even if you make it private, you can access it from anywhere within the same class, and, for example, set a value that would otherwise get rejected by validation:

validatedPropertyValue = -1;

C# 14 introduces a new field keyword which gives access to the compiler generated backing field inside the property, but not elsewhere in the class. With this new feature, you don't need to declare a backing field anymore, if you want to implement validation in the property setter. This makes it impossible to circumvent the setter. And you can keep the getter automatically implemented if you don't need any custom code inside it:

public int ValidatedProperty
{
    get;
    set
    {
        field =
            value >= 0
                ? value
                : throw new ArgumentOutOfRangeException(
                    nameof(value),
                    "The value must be non-negative."
                );
    }
}

The new field keyword can introduce a naming conflict in your code if you also have a field named field in the same class. Outside properties, field will still refer to your field, but inside properties, it will refer to the compiler generated backing field instead. You will be informed of that with a compiler warning:

A warning for naming conflict because of the field keyword

As mentioned in the warning, you can still refer to the explicitly declared field field instead of the compiler generated backing field by using @field or this.field:

private int field;
public int FieldProperty
{
    get { return @field; }
    set { this.field = value; }
}

But of course, it's even better to rename your field and avoid the conflict altogether.

The new field keyword is also useful in combination with partial properties which were introduced in C# 13. Not having to declare a backing field in source-generated code means that the backing field won't be accessible outside generated code.

You can try the feature yourself if you have the latest version (17.14.9) of Visual Studio 2022 installed. According to documentation, the new keyword works in .NET 9 or later.

To get access to it in your code, you need to set the language version in your project file to preview:

<PropertyGroup>
  <LangVersion>preview</LangVersion>
</PropertyGroup>

You can find a sample project for this new feature in my GitHub repository. It includes an implementation of a setter with validation with and without the field keyword. It also shows, how to resolve the naming conflict when a field named field is declared in the class. The tests can guide you through the different aspects of the code.

By using the field keyword, you can add some custom code to automatically implemented properties without having to declare your own backing field, if you don't need to access it outside the property. This can prevent bugs in your code being caused by accessing the backing field inside your class directly instead of through the property. The potential naming conflict because of the new keyword is a minor inconvenience for that which can easily be resolved.

Get notified when a new blog post is published (usually every Friday):

Copyright
Creative Commons License