Skip to main content

Fixed: "error IDE0044: Make field readonly" in a .NET C# Build

· 5 min read
Jagdish Kumawat
Founder @ Dewiride

error IDE0044: Make field readonly appeared the first time I made the build check code style. The rule is right more often than not: the field was set once and never changed, so the compiler can promise that it never will. Here's what the rule checks, why it was an error rather than a hint, and the fix.

What I Was Doing​

In a .NET 10 solution with TreatWarningsAsErrors on and the default .editorconfig from dotnet new editorconfig, I set EnforceCodeStyleInBuild to true in Directory.Build.props, so dotnet build checks the code-style rules as well. The class library had this class:

src/Dewiride.Inventory.Data/Class1.cs
namespace Dewiride.Inventory.Data;

public class Class1
{
private string _prefix = "INV-";

public required string Name { get; set; }

public string Code => _prefix + Name;
}

What I Expected​

The same clean build as a moment before.

What I Got​

Output (dotnet build)
Restore complete (0.6s)
Dewiride.Inventory.Data net10.0 failed with 1 error(s) (0.1s)
/Users/you/projects/dewiride-inventory-api/src/Dewiride.Inventory.Data/Class1.cs(5,20): error IDE0044: Make field readonly (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0044)

Build failed with 1 error(s) in 0.8s

A terminal where dotnet build fails with error IDE0044: Make field readonly at Class1.cs line 5, column 20, with a link to the rule's documentation.

(5,20) is line 5, column 20: the field _prefix.

What I Checked​

What the rule checks. The IDE0044 page: "This style rule concerns specifying the readonly (C#) or ReadOnly (Visual Basic) modifier for private fields that are initialized (either inline or inside of a constructor) but never reassigned." _prefix is private, initialized inline with "INV-", and only read.

The name. The docs call the rule "Add readonly modifier"; the build prints "Make field readonly". Same rule, IDE0044.

Why It Happens​

_prefix matches what IDE0044 looks for: a private field, set where it's declared and never assigned again. Three settings together turned that into a failed build:

  • The default .editorconfig has dotnet_style_readonly_field = true:warning, the option behind IDE0044, at warning.
  • EnforceCodeStyleInBuild made the build run code-style rules, which it skips by default.
  • TreatWarningsAsErrors turned the warning into an error.

The code hadn't changed; the build had started looking.

The Fix​

Mark the field readonly:

src/Dewiride.Inventory.Data/Class1.cs (the field)
private readonly string _prefix = "INV-";

readonly means the field can be assigned only where it's declared or in a constructor. The compiler then rejects any later assignment, so nobody can change the prefix by accident.

After the Fix​

Output (dotnet build)
Restore complete (0.5s)
Dewiride.Inventory.Data net10.0 succeeded (0.2s) → src/Dewiride.Inventory.Data/bin/Debug/net10.0/Dewiride.Inventory.Data.dll
Dewiride.Inventory.Api net10.0 succeeded (0.4s) → src/Dewiride.Inventory.Api/bin/Debug/net10.0/Dewiride.Inventory.Api.dll

Build succeeded in 1.2s

A terminal where dotnet build succeeds for both projects after the field was marked readonly.

If You Disagree with the Rule​

The severity lives in .editorconfig, after the colon. To keep the editor hint without failing the build, lower it:

.editorconfig (under [*.{cs,vb}])
dotnet_style_readonly_field = true:suggestion

suggestion "Violations appear as build messages and as suggestions in the Visual Studio IDE", which doesn't fail a build. Lowering a rule for the whole solution because of one field is rarely right, though; if one field really must stay writable, it'll be because code assigns it, and then the rule doesn't fire.

Common Mistakes​

MistakeWhat happensDo this instead
Adding readonly to a field that a method assignserror CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)Leave that field writable; IDE0044 doesn't flag fields that are reassigned
Turning off EnforceCodeStyleInBuild to get rid of the errorEvery code-style rule stops running on buildFix the field
Confusing it with IDE0062 or CA rulesDifferent rules, different fixesRead the ID in the message

Troubleshooting​

SymptomLikely causeFix
error IDE0044: Make field readonlyA private field is set once and never reassigned, and the build checks code styleAdd readonly
IDE0044 shows up only after EnforceCodeStyleInBuild was turned onThe build runs code-style rules only with that settingFix the field, or lower the rule's severity in .editorconfig
error CS0191: A readonly field cannot be assigned to … after adding readonlyCode assigns the field after constructionRemove readonly from that field
It's an error, not a warningTreatWarningsAsErrors is onFix the field, as with any warning

FAQ​

Does readonly make the code faster?​

That's not the point of the rule; it's about intent. A reader sees at once that the value never changes, and the compiler enforces it.

Why didn't the editor and the build agree before?​

Code-style rules show in the editor, but command-line builds skip them by default. EnforceCodeStyleInBuild makes the build agree with the editor.

Conclusion​

error IDE0044: Make field readonly points at a private field that's set once and never reassigned. Add readonly to it. It became a build error here because the default .editorconfig sets the rule to warning, EnforceCodeStyleInBuild made the build check it, and TreatWarningsAsErrors turned the warning into an error.

Additional Resources​

Stay Updated

Subscribe to our newsletter for the latest tutorials, tech insights, and developer news.

By subscribing, you agree to our privacy policy. Unsubscribe at any time.