In last year's post about C# 13 we saw several features that ultimately didn't make it into that version but were expected to arrive in C# 14 (November 2025). Today let's take a look at one of them: the field keyword.
Table of Contents
1 - The history of Backing fields in C#
I want to start by talking about how we got here. In C#, we have fields and properties. Properties are public members of an object that access fields, while fields are private elements that store the data in the object.
In the early versions of C#, this combination of features was defined like so:
public class FieldPropExample
{
//field
private string _message;
// property
public string Message
{
get
{
return _message;
}
set
{
_message = value;
}
}
}
Later, the language evolved to allow the getters and setters we have today:
public class GetterSetterExample
{
public string Message { get; set; }
}
Behind the scenes, what the compiler does is create a "backingfield
", so Message is still a property, the field still exists but we don't have to write it.
This works perfectly until you need to add logic to either the getter or setter. While it's not super common, in some cases it's necessary.
In this case, the logic is to check if the first letter is uppercase; if not, we throw an exception:
public class FieldPropExampleWithLogic
{
//field
private string _message;
// property
public string Message
{
get => _message;
set
{
if (string.IsNullOrEmpty(value) || !char.IsUpper(value[0]))
{
throw new ArgumentException("the first letter must be uppercase");
}
_message = value;
}
}
}
To add logic to the getter or setter, up to C# 14 we had to manually create the field.
And that's what changes starting with C# 14. We no longer need to manually add the backing field, because the compiler will do it for us using the new field keyword.
2 - The field keyword in C#
Starting in C# 14, we have the new field
keyword, which allows us to add logic in the getter or setter without having to explicitly declare the backing field:
public class FieldKeywordExampleWithLogic
{
public string Message
{
get => field;
set
{
if (string.IsNullOrEmpty(value) || !char.IsUpper(value[0]))
{
throw new ArgumentException("the first letter must be uppercase");
}
field = value;
}
}
}
This reduces the amount of code we have to write. But not only that—the field keyword is encapsulated within the accessor itself and cannot be accessed outside of it, so even inside the object, you cannot reference the backing field (which is a good thing).
Finally, if you already have a field called field in your object—which can happen if the code is old—you can resolve it with @field
or this.field
, though ideally, you wouldn't name anything field in the first place.
If there is any problem you can add a comment bellow or contact me in the website's contact form