Skip to content

BRO1144: Escape identifiers that C# 14 reads as keywords

C# 14 reads field, extension and partial as keywords in places where they used to be plain names. Code that used such a name there changes meaning or stops compiling when the project moves to C# 14 (.NET 10's default). BRO1144 writes @ before the name in exactly those places; @field means the same in every C# version. Not a StyleCop rule (Sonar S8367, S8368 and S8380 report these without a fix; the compiler's CS9258 warning has no fix either).

Example

Before

public class Counter
{
    private int field;

    public int Value
    {
        get => field;
        set => field = value;
    }

    public int Read() => this.field;
}

After

public class Counter
{
    private int field;

    public int Value
    {
        get => @field;
        set => @field = value;
    }

    public int Read() => this.field;
}

Why

In C# 14, field inside a property accessor is the property's own backing field. get => field; above stops reading the class's field field and reads a new, hidden one instead: the code still compiles (warning CS9258), but Value and Read() no longer see the same storage. With @field it keeps its meaning in every language version, so a multi-targeted project (net48;net10.0, where each target framework compiles with its own C# version) behaves the same everywhere.

What is reported

These are the cases in Roslyn's list of C# 14 breaking changes, each checked with the C# 14 compiler:

Before After In C# 14 without @
field in a property's accessor or expression body (also in a lambda or local function there) that names a member, local, parameter or range variable @field the backing field (CS9258), or error CS9272/CS9273 for a local or parameter declared there
a type, delegate, type parameter or using alias named extension @extension error CS9306
a member of a type whose declaration starts with the type name extension (extension M(), extension[] items;, a constructor of a type named extension) @extension M() read as an extension block: syntax errors
a method or local function returning a type named partial (partial F()) @partial F() read as a partial member: errors

In code that already compiles as C# 14, a field keyword is reported only when a member, local or parameter named field of the property's type is in scope (the CS9258 case). Next to a member of another type (a string property in a class with an int field named field) the keyword can only mean the backing field and stays.

Not reported

  • this.field, x.field, x?.field, named arguments (M(field: 1)) and anonymous object members (new { field = 1 }): they stay names in C# 14.
  • field in an indexer or event accessor, or anywhere outside a property: not a keyword there.
  • extension used as a type anywhere else (a parameter, a local, new extension()), and partial as the type of a field, property or parameter, or in an array return type (partial[] F()): C# 14 compiles these unchanged.
  • scoped as a type name of a lambda parameter ((scoped s) => ..., Sonar S8381): a narrower case, not covered.
  • Code with syntax errors around the name.

Renaming rules and C# 14

When a member named field is also renamed (BRO1303, BRO1306, ...), the rename takes the field keywords that mean the member along with it (get => field; becomes get => _field;), so the escape and the rename give the same result in one dotnet format run, in either order (checked with a C# 14 project and the SDK 10 compiler, 2026-10-06).

Compared with StyleCop

StyleCop has no such rule. stylebro-migrate turns it off (see Rules beyond StyleCop).