Const vs Readonly in C#: What's the Difference and When to Use Which?
\n\nEvery 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.
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\nWhat is const in C#?
\n\nConst 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, andnull. \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
newor reference types (exceptstring). \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\nWhen 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.
What is readonly in C#?
\n\nReadonly 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
newor a method call). \n - Not substituted into the code — it's a regular field with write protection. \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\nAn 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.
Comparison of const and readonly: Difference Table
\n\nTo solidify the material, here's a visual comparison:
\n\n| Criterion | \nconst | \nreadonly | \n
|---|---|---|
| Evaluation time | \nCompile time | \nExecution (runtime) | \n
| Data types | \nOnly primitives + string | \nAny types | \n
| Static nature | \nImplicitly static | \nCan be static or instance | \n
| Mutability | \nNever | \nOnly in the constructor | \n
| Access | \nAs
BlogsBook RecommendationsRead also |