Understanding the readonly Keyword in C#
In C#, the readonly keyword means a field can be assigned only once. Many developers interpret this as “unchangeable,” but it behaves quite differently for value types versus reference types.
This post explores how readonly behaves with both, and how references are fixed while their contents might still be mutable.
Readonly with Value Types
readonly int number = 10;
number = 20; // ❌ Compile-time error - cannot reassign
When applied to value types (like int, float, bool), readonly prevents the value from ever being changed after it’s set.
Since value types directly hold data, readonly locks the value itself.
Readonly with Reference Types
private readonly string[] wordList;
For reference types (like arrays or objects), readonly prevents the reference (memory address) from being reassigned. But the contents of that reference are still mutable.
Initialization in Constructor Only
public WordWarrior()
{
wordList = new string[] { "apple", "banana" }; // ✅ Allowed in constructor
}
public void ResetWords()
{
wordList = new string[] { "grape", "lemon" }; // ❌ Not allowed outside constructor
}
Readonly fields must be initialized inside the constructor and cannot be changed afterward.
Reference Reassignment is Blocked
readonly string[] currentWords = new string[] { "sun", "moon", "stars" };
string[] newWords = new string[] { "ocean", "mountain" };
currentWords = newWords; // ❌ Not allowed
You cannot assign a different object to a readonly reference. The address is fixed.
Internal Data is Still Mutable
wordList[0] = "updated"; // ✅ Allowed
The reference can’t change, but the data it points to can be modified freely. So readonly isn’t the same as immutability.
Key Takeaways
readonlyprevents reassignment of a field once initialized.- With value types, it locks the actual value.
- With reference types, it locks the address but not the internal state.
- Only constructors can initialize
readonlyfields.
How Is It Different from const?
const values are fixed at compile time and must be simple types like numbers or strings. They must be initialized at declaration.
readonly allows initialization at runtime (in constructors) and supports more complex types like arrays or objects.
const string[] colors = { "red", "green" }; // ❌ Not allowed
Use const for truly fixed values. Use readonly for fixed references to objects whose internal state might change.
Summary
The readonly keyword is not just about preventing changes. For value types, it locks the value. For reference types, it locks the reference, not the object’s state. Use const for compile-time constants, and readonly when you need a one-time assignment for more complex types.
