Updated November 2026: I checked everything again on .NET 10 with two real projects, fixed the list of types a
constaccepts and a sample that no longer compiled, and switched to file-scoped namespaces and top-level statements.
When we need a value that never changes, C# gives us two keywords: const and readonly. They look interchangeable, but they behave differently, and one difference can break an application after a library update.
The const keyword
A const declares a value that is fixed at compile time:
public static class Colour
{
public const string ConstRed = "#FF0000";
}- A
constis implicitlystatic: we readColour.ConstRedwithout an instance. Addingstaticourselves is an error:error CS0504: The constant 'ConstRed' cannot be marked static. - A
constcan also be declared inside a method, as a local constant. - A
constonly accepts the built-in numeric types (int,double,decimal…),bool,char,stringand enums. Any other reference type can only be aconstwith the valuenull. ADateTime, or any other struct, cannot be aconst(error CS0283: The type 'DateTime' cannot be declared const): that is a job forstatic readonly. - Since C# 10, a
const stringcan be an interpolated string, as long as every part of it is itself a constant string:
public static class Colour
{
public const string Hash = "#";
public const string ConstRed = $"{Hash}FF0000";
}The readonly keyword
A readonly field can only be assigned in its declaration, in a constructor of the same class, or in an init accessor:
public class Colour
{
public readonly string ReadOnlyRed;
public Colour()
{
ReadOnlyRed = "#FF0000";
}
public Colour(string red)
{
ReadOnlyRed = red;
}
}A readonly field can also be static:
public static class Colour
{
public static readonly string ReadOnlyRed = "#FF0000";
}- As a variable modifier,
readonlyonly applies to fields. Areadonlylocal variable does not compile:error CS0106: The modifier 'readonly' is not valid for this item. - A
readonlyfield accepts any type, value or reference. With a reference type,readonlyprotects the reference, not the object: we can still change the object's properties, but we cannot replace it with another object.
The difference that matters
A const is a compile-time constant: the compiler copies its value into every assembly that uses it. A readonly field is read at runtime.
Let's see what this means in practice. A class library, Core, holds a Colour class with a const and a static readonly field of the same value:
namespace Core;
public static class Colour
{
public const string ConstRed = "#FF0000";
public static readonly string ReadOnlyRed = "#FF0000";
}A console application, SampleConstVsReadonly (in the App folder, with a project reference to Core), prints both values. With top-level statements, its whole Program.cs is:
using Core;
Console.WriteLine($"Const value: {Colour.ConstRed}.");
Console.WriteLine($"Readonly value: {Colour.ReadOnlyRed}.");Running it prints:
Const value: #FF0000.
Readonly value: #FF0000.Now we change the red to #EF4444 in both fields of Core. Since the application's code has not changed, we rebuild only Core and replace its DLL next to the application, without recompiling the application:
dotnet build Core
cp Core/bin/Debug/net10.0/Core.dll App/bin/Debug/net10.0/Core.dll
dotnet App/bin/Debug/net10.0/SampleConstVsReadonly.dllConst value: #FF0000.
Readonly value: #EF4444.Only the readonly value is updated. When the application was compiled, the compiler replaced Colour.ConstRed with "#FF0000" in the application's own DLL, so it never asks Core for it. The readonly field, on the other hand, is read from Core every time the application runs.
Recompiling the application (dotnet build App) fixes it: both lines then show #EF4444.
This is why the .NET design guidelines reserve constant fields for values that will never change, such as Math.PI. For a public value that may change in a future version of a library, use a static readonly field.
Conclusion
const and readonly both prevent a value from changing, but a const is resolved at compile time and a readonly field at runtime. When a public const changes in a library, every project that references it must be recompiled to see the new value.
If you have questions about const and readonly, I will be happy to discuss them in the comments.
References
- const keyword — C# reference: the types a constant accepts and local constants.
- readonly keyword — C# reference: where a
readonlyfield can be assigned, and how it differs fromconst. - Constants (C# programming guide) — why a program keeps the old value of a constant until it is recompiled.
- Field design guidelines — when to use constant fields and when to use
static readonlyfields. - String interpolation — constant interpolated strings (C# 10).
- Top-level statements — the
Program.csstyle used in the sample.