const ↓Compile-time constant ↓Compiler knows the value ↓Implicitly staticreadonly ↓Runtime value ↓Assigned during initialization/construction ↓Cannot be reassigned afterward
Memory
const → compiler knows the value readonly → runtime can set it, but cannot reassign it afterward
const
readonly
Java equivalent
static final (compile-time constant)
final
Known at
Compile time
Runtime
Assignment
Declaration only
Declaration / constructor
Instance field
❌
✅
Implicitly static
✅
❌
Runtime values
❌
✅
Can reassign later?
❌
❌
Typical use
True constants
Object state / DI dependencies
private vs readonly
These solve different problems:
private vs readonly
private controls who can access the field. readonly controls whether the field can be reassigned.
private string _name; // can be changed internallyprivate readonly string _name; // cannot be reassigned after construction
Therefore:
private readonly string _connectionString;
means:
Only this class can access it, and it can only be assigned during initialization/construction.
Java → C#
private final String name; → private readonly string _name;static final int MAX = 10; → const int Max = 10;static final Guid id = → static readonly Guid Id = UUID.randomUUID(); Guid.NewGuid();
Getter vs Setter
Read-only property
public string Name { get; }public User(string name){ Name = name;}
Outside code:
user.Name; // ✅user.Name = "X"; // ❌
Good when the value should never change after construction.
Internally mutable property
public string Name { get; private set; }public User(string name){ Name = name;}
Outside:
user.Name = "X"; // ❌
Inside the class:
Name = "X"; // ✅
Don't confuse these
get; = publicly readable, not necessarily a readonly field.
get; private set; = outside cannot modify, but the class can.
readonly field = field cannot be reassigned after construction.
Why readonly is useful in ASP.NET Core
Common dependency-injection pattern:
public class OrderService{ private readonly IOrderRepository _repository; public OrderService(IOrderRepository repository) { _repository = repository; }}
The dependency is established when the object is created and should not be replaced later.
Production Rule
Use:
const→ value is genuinely a compile-time invariantreadonly→ value comes from runtime state but should not be reassignedget; private set;→ class needs to control future mutationsget;→ value should be established during construction and then exposed read-only
Public const and versioning
const values can be embedded into consuming assemblies at compile time. Changing a public constant in a library may therefore require consumers to be recompiled.
static readonly is preferable when the value is runtime-initialized or may change independently of consumers.