Start Debugging
2025-04-05 14c-sharpnetnet-10

C# 14 – The field keyword and field-backed properties

C# 14 introduces a new contextual keyword, field, that can be used inside a property’s accessors (the get, set, or init blocks) to refer to the property’s backing storage​. In simpler terms, field is a placeholder representing the hidden variable where a property’s value is stored. This keyword lets you add custom logic to automatically…

C# 14 introduces a new contextual keyword, field, that can be used inside a property’s accessors (the get, set, or init blocks) to refer to the property’s backing storage​. In simpler terms, field is a placeholder representing the hidden variable where a property’s value is stored. This keyword lets you add custom logic to automatically implemented properties without manually declaring a separate private field. It was first made available as a preview in C# 13 (requiring .NET 9 with the language version set to preview)​, and is officially part of the language in C# 14.

Why is this useful? Before C# 14, if you wanted to add logic (like validation or change notification) to a property, you had to turn it into a full property with a private backing field. That meant more boilerplate code and the risk of other class members accidentally using that field directly, bypassing your property logic​. The new field keyword addresses these issues by letting the compiler generate and manage the backing field for you, while you simply use field in your property code. This results in cleaner, more maintainable property declarations and prevents the backing storage from “leaking” into the rest of your class’s scope​.

field benefits & use cases

The field keyword was introduced to make property declarations more concise and less error-prone. Here are the key benefits and scenarios where it’s useful:

Overall, field improves readability and maintainability by removing redundant code and focusing only on the custom behavior you need​. It’s conceptually similar to how the value keyword works in a setter (representing the value being assigned); here field represents the underlying storage for the property​.

Before vs. After: manual backing field vs. field keyword

To see the difference, let’s compare how you would declare a property that enforces some rule before C# 14 and after using the new field keyword.

Scenario: Suppose we want a property Hours that must never be set to a negative number. In older C# versions, we’d do the following:

Before C# 14 – using a manual backing field:

public class TimePeriodBefore
{
    private double _hours;  // backing field

    public double Hours
    {
        get { return _hours; }
        set 
        {
            if (value < 0)
                throw new ArgumentOutOfRangeException(nameof(value), "Value must not be negative");
            _hours = value;
        }
    }
}

In this pre-C#14 code, we had to introduce a private field _hours to store the value. The property’s getter returns this field, and the setter performs a check before assigning to _hours. This approach works, but it’s verbose: we have extra code to declare and manage _hours, and _hours is accessible anywhere in the class (meaning other methods could write to _hours and bypass the validation logic if one isn’t careful).

Starting with C# 14 – using the field keyword:

public class TimePeriod
{
    public double Hours
    {
        get;  // auto-implemented getter (compiler provides it)
        set => field = (value >= 0) 
            ? value 
            : throw new ArgumentOutOfRangeException(nameof(value), "Value must not be negative");
    }
}

Here, the Hours property is declared with no explicit backing field. We use get; with no body, indicating an automatic getter, and we provide a body for set that uses field. The expression field = ... inside the setter tells the compiler to assign to the property’s backing field. The compiler will automatically generate a private field behind the scenes and implement the get accessor to return that field. In the setter above, if the value is negative, we throw an exception; otherwise, we assign it to field (which stores it). We did not have to declare _hours ourselves, and there’s no need to write the getter’s body either – the compiler does those for us​. The result is a more concise property definition with the same behavior.

Notice how much cleaner the C# 14 version is:

You can also use field in a get accessor if needed. For example, to implement lazy initialization, you might do something like:

public string Name 
{
    get => field ??= "Unknown";
    set => field = value;
}

In this case, the first time Name is accessed, if it wasn’t set, the getter assigns a default "Unknown" to the backing field and returns it. Subsequent gets or any set will use the same field. Without this feature, you would have needed a private field and more code in the getter to accomplish the same behavior.

How does the compiler handle the field keyword?

When you use field inside a property accessor, the compiler quietly generates a hidden backing field for that property (very similar to how it does for an auto-implemented property). You never see this field in your source code, but the compiler gives it an internal name (for example, something like <Hours>k__BackingField) and uses it to store the property’s value. Here’s what happens under the hood:

TLDR; the compiler generates a private backing field and wires up your property accessors to use it. You get the functionality of a full property with a fraction of the code. The property remains a true automatic property from an implementation standpoint – you just got a hook to inject logic into it.

Syntax and usage rules for field

When using the field keyword, keep in mind the following rules and limitations:

To put it simply: use field inside your property accessors to refer to that property’s hidden storage, and nowhere else. Follow normal C# scoping rules for everything outside of properties.

Handling naming conflicts (when you have your own field variable)

Because field wasn’t a reserved word in older C# versions, it’s possible (though uncommon) that some code might have used “field” as a variable name or field name. With the introduction of the field contextual keyword in accessors, such code could become ambiguous or break. The language design takes this into account:

private int field = 10; // a field unfortunately named "field" 
public int Example
{
    get { return @field; } // use @field to return the actual field 
    set { @field = value; } // or this.field = value; either works 
}

References

  1. field – Field backed property declarations
  2. C# Feature Proposal Notes – field keyword in properties”
  3. What’s new in C# 14
< Back