Difference Between const and readonly in C#
If you’ve been writing C# for a while, you’ve definitely used both const and readonly. They look similar, they both represent “values that shouldn’t change,” and they both help make your code safer.
But under the hood, they behave very differently — and choosing the wrong one can lead to bugs, versioning issues, and unexpected runtime behavior.
This guide breaks down the differences with definitions, examples, IL behavior, performance notes, and real-world scenarios.
What Is const?
const defines a compile-time constant.
Key characteristics
- Value is baked into the assembly at compile time
- Must be assigned at declaration
- Only supports primitive types + string
- Cannot be changed
- Faster access (inlined)
- Changing a const in a library requires recompiling all dependent projects
Example
public const int MaxItems = 100;
This value is fixed forever at compile time.
What Is readonly?
readonly defines a runtime constant.
Key characteristics
- Value is assigned at runtime
- Can be set in:
- Declaration
- Constructor
- Supports any type (objects, lists, structs, etc.)
- Not inlined — stored in memory
- Changing a readonly value in a library does NOT require recompilation of consumers
Example
public readonly int MaxItems;
public MyClass()
{
MaxItems = 100;
}
Side‑by‑Side Comparison
| Feature | const | readonly |
|---|---|---|
| When value is set | Compile-time | Runtime |
| Can be changed later | ❌ No | ❌ No (after construction) |
| Allowed types | Primitives + string | Any type |
| Assigned in constructor | ❌ No | ✔️ Yes |
| Inlined by compiler | ✔️ Yes | ❌ No |
| Requires recompilation of dependent assemblies | ✔️ Yes | ❌ No |
| Use for | Fixed values | Configurable runtime values |
IL (Intermediate Language) Behavior
const
Compiler replaces all references with the literal value.
ldc.i4.s 100
readonly
Compiler loads the field at runtime.
ldfld int32 MyClass::MaxItems
This is why changing a const in a shared library can break consumers — they still hold the old literal value.
Real‑World Scenarios
Scenario 1: Mathematical constants
Use const.
public const double Pi = 3.14159;
These values never change.
Scenario 2: API base URLs
Use readonly.
public static readonly string BaseUrl =
Environment.GetEnvironmentVariable("API_URL");
This value depends on environment — cannot be const.
Scenario 3: Configuration values
Use readonly.
public readonly int CacheDuration;
public Settings(int duration)
{
CacheDuration = duration;
}
Scenario 4: Versioning
If you expose constants in a shared library:
public const int Timeout = 30;
And later change it to:
public const int Timeout = 60;
All dependent projects must be recompiled or they will still use 30.
Use readonly instead.
Interview‑Ready Summary
-
const= compile-time constant -
readonly= runtime constant -
constis inlined;readonlyis stored in memory -
constonly supports primitive types + string -
readonlysupports any type - Use
constfor values that never change - Use
readonlyfor values that may vary per environment or runtime
Top comments (0)