In C#, both const
and readonly
are used to define variables whose values cannot be changed after assignment. However, there are significant differences between the two in terms of behavior, usage, and when the value is assigned.
1. Declaration and Initialization
- Constants (
const
):- Must be declared and initialized at the time of declaration.
- The value is fixed at compile time and cannot be changed later.
const
is implicitlystatic
, meaning it belongs to the type, not the instance.- Can only hold primitive types, enums, or strings.
- Read-Only (
readonly
):- Can be initialized either at the time of declaration or in the constructor of the class.
- The value is set at runtime and can vary depending on the constructor used.
readonly
variables can be instance-level (non-static) or static.
Examples:
// const
public const int MaxValue = 100; // Must be initialized at declaration
// readonly
public readonly int MaxValue;
public MyClass() {
MaxValue = 100; // Initialized in the constructor
}
2. Value Assignment
- Constants (
const
):- Value is assigned at compile time.
- Cannot assign a value after declaration, and it is substituted directly into the compiled code.
- Read-Only (
readonly
):- Value is assigned at runtime.
- Can be assigned in the constructor and can vary depending on the instance or constructor logic.
3. Usage
- Constants (
const
): Used for values known at compile time and will never change (e.g., mathematical constants, app settings). - Read-Only (
readonly
): Used for values that may not be known until runtime (e.g., configurations, input-based values).
Examples:
// const usage
public const double Pi = 3.14159; // Known value at compile time
// readonly usage
public readonly int RuntimeValue;
public MyClass(int value) {
RuntimeValue = value; // Assigned during runtime
}
4. Static Context
- Constants (
const
): Implicitlystatic
and belongs to the type, not the instance. - Read-Only (
readonly
): Can be either instance-level orstatic
. Astatic readonly
can be assigned in a static constructor.
Examples:
// const (implicitly static)
public const int MaxConnections = 100;
// static readonly
public static readonly string AppName;
static MyClass() {
AppName = "My Application"; // Set at runtime in static constructor
}
5. Flexibility
- Constants (
const
):- Less flexible as they must be initialized at compile time.
- Can only be used with basic types (e.g.,
int
,string
,double
).
- Read-Only (
readonly
):- More flexible since the value can be set at runtime.
- Can hold complex types such as objects, arrays, and collections.
Example:
// readonly with complex types
public readonly DateTime CreatedAt;
public MyClass() {
CreatedAt = DateTime.Now; // Set during runtime
}
6. Memory Efficiency
- Constants (
const
):- Stored as part of the metadata in the compiled assembly.
- The value is substituted directly into the code wherever it’s used, leading to efficient memory usage but possible versioning issues if a library changes a constant value.
- Read-Only (
readonly
):- Stored as fields in memory, like normal variables.
- Because they are not substituted directly into the code, versioning issues are avoided.
Real-World Analogy
- Constants (
const
): Think of a birthdate. It is fixed and cannot change. Once set, it stays the same for the rest of your life.public const string Birthdate = "January 1, 1990";
- Read-Only (
readonly
): Think of an ID card number. It is assigned at some point in time (when the card is issued) but cannot change afterward.public readonly string IDNumber; public Person(string id) { IDNumber = id; // Set when issued }
Key Differences
Feature | const |
readonly |
---|---|---|
Initialization | Must be initialized at declaration | Can be initialized at declaration or in constructor |
Assignment | Assigned at compile time | Assigned at runtime |
Modification | Cannot be modified after declaration | Cannot be modified after initialization |
Types Allowed | Primitive types, strings, enums | All types, including complex types |
Implicitly Static | Yes | No (must be declared static ) |
Usage | Used for constants known at compile time | Used for values determined at runtime |
Important and Tricky Q&A
Q1: Can a const
be assigned a value in a constructor?
Answer: No, const
values must be assigned at the time of declaration, and they cannot be changed later. They are set at compile time.
Q2: Can a readonly
value be changed after initialization in the constructor?
Answer: No, once a readonly
value is initialized in the constructor, it cannot be modified afterward.
Q3: Why would you choose readonly
over const
?
Answer: Choose readonly
when you need to set the value at runtime (e.g., based on constructor logic or external input) or when working with non-primitive types. Use const
when the value is constant and known at compile time.
Q4: Can readonly
be static
?
Answer: Yes, readonly
can be either instance-level or static
. If it’s static, the value is shared across all instances and can only be assigned in a static constructor.
Q5: Can const
be used for complex types like arrays or objects?
Answer: No, const
can only be used for primitive types, strings, and enums. Use readonly
if you need to work with complex types like objects or arrays.
Conclusion
Use const
when the value is fixed at compile time and will never change. Use readonly
when the value is determined at runtime but should not be modified afterward. Understanding the differences between these two is crucial for writing maintainable and efficient code in C#.