Const vs Readonly in C#: What to Choose and What's the Difference?

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Const vs Readonly in C#: What's the Difference and When to Use Which?

\n\n

Every C# developer sooner or later faces a dilemma: should a value be declared as const or as readonly? At first glance, both keywords do the same thing — they prevent a variable from being changed after initialization. But dig deeper, and a whole chasm of differences opens up, affecting architecture, performance, and even code security.

\n\n

In this article, we won't just list dry facts from the documentation. We'll examine real-world scenarios, show pitfalls, and help you make an informed choice. Let's go!

\n\n

What is const in C#?

\n\n

Const is a compile-time constant. Its value must be known at compile time and cannot change at runtime.

\n\n
    \n
  • Can only be of primitive types: int, double, string, bool, enum, and null.
  • \n
  • Implicitly static — belongs to the type, not an instance.
  • \n
  • The value is substituted directly into the code at compile time (like a macro in C++).
  • \n
  • Cannot be used with new or reference types (except string).
  • \n
\n\n
public class MathConstants\n{\n    public const double Pi = 3.14159;\n    public const int MaxRetries = 5;\n    public const string AppName = "MyApp";\n    \n    // Error! Reference types (except string) cannot be used\n    // public const List<int> Numbers = new List<int>();\n}
\n\n

When the compiler encounters const, it literally embeds the value into the IL code. This means that if you use a constant from another assembly and then change its value, old assemblies will still use the old value — until they are recompiled.

\n\n

What is readonly in C#?

\n\n

Readonly is a field that can only be initialized at the point of declaration or in the class constructor. After that, it cannot be changed.

\n\n
    \n
  • Can be of any type: both value and reference types.
  • \n
  • Can be either static or instance.
  • \n
  • The value is computed at runtime (e.g., you can use new or a method call).
  • \n
  • Not substituted into the code — it's a regular field with write protection.
  • \n
\n\n
public class Config\n{\n    public readonly DateTime CreatedAt = DateTime.Now;\n    public readonly List<string> Tags;\n    public static readonly Guid InstanceId = Guid.NewGuid();\n    \n    public Config()\n    {\n        Tags = new List<string> { "csharp", "tutorial" };\n        // Error! Cannot change after the constructor\n        // Tags = new List<string>();\n    }\n}
\n\n

An important nuance: readonly only protects the reference, not the object's contents. If you have a readonly List<int>, you cannot assign a new list, but you can freely add or remove elements.

\n\n

Comparison of const and readonly: Difference Table

\n\n

To solidify the material, here's a visual comparison:

\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
Criterionconstreadonly
Evaluation timeCompile timeExecution (runtime)
Data typesOnly primitives + stringAny types
Static natureImplicitly staticCan be static or instance
MutabilityNeverOnly in the constructor
AccessAs

Blogs

Book Recommendations