C# ไม่มี final เหมือน Java — ใช้ readonly (Runtime Constant) หรือ const (Compile-time Constant) แทน
const — Compile-time Constant
- ค่าต้องทราบตอน Compile (Literal หรือ Constant Expression)
- Implicit
static— เข้าถึงผ่าน Class Name - Value Types และ String เท่านั้น
- ไม่สามารถเปลี่ยนได้เลย
public class MathConstants {
public const double PI = 3.14159265359;
public const int MaxRetries = 3;
// public const DateTime StartDate = DateTime.Now; // ❌ Error: Not Compile-time Constant
}
readonly — Runtime Constant
- กำหนดค่าได้แค่ครั้งเดียว: ตอนประกาศ หรือ ใน Constructor
- Instance หรือ Static ได้
- ทุก Type ได้ (รวม Reference Types, Structs)
- Runtime Value — เหมาะกับ Configuration, Injected Dependencies
public class Employee {
public readonly int Id;
public readonly string Name;
public readonly DateTime HireDate;
public Employee(int id, string name) {
Id = id; // Set ใน Constructor
Name = name; // Set ใน Constructor
HireDate = DateTime.Now; // Runtime Value OK
}
// void ChangeId() { Id = 10; } // ❌ Compile Error: Readonly
}
Comparison
| Feature | const | readonly |
|---|---|---|
| Evaluation Time | Compile-time | Runtime |
| Static | Implicit static | Instance or Static |
| Allowed Types | Primitives, String, Enum, Null | Any Type |
| Assignment | At Declaration Only | Declaration or Constructor |
| Versioning | Burned into Caller Assembly | Resolved at Runtime |
| Use Case | Universal Constants (PI, MaxInt) | Configuration, DI, Runtime Values |
Versioning Issue with const
// Assembly A (Library)
public class Config {
public const int MaxConnections = 100;
}
// Assembly B (Consumer) - Compiled against A
Console.WriteLine(Config.MaxConnections); // Inlined to 100 in B's IL!
// Later: Assembly A changes to 200, Rebuild A only
// B still sees 100 until Rebuild B — Versioning Problem!
readonly ไม่มีปัญหานี้ — อ่านค่าตอน Runtime
Static Readonly (Singleton-like Constants)
public class AppSettings {
public static readonly string ConnectionString = LoadFromConfig();
public static readonly TimeSpan Timeout = TimeSpan.FromSeconds(30);
private static string LoadFromConfig() => "Server=...";
}
Modern: init-only Properties (C# 9+)
public class Person {
public string Name { get; init; } // Set ได้ตอน Object Initializer
public int Age { get; init; }
// ไม่สามารถ Set หลัง Construction ได้
}
// Usage
var p = new Person { Name = "John", Age = 30 };
// p.Name = "Jane"; // ❌ Compile Error
สรุป
const: Universal Constants (Math, Physics, Fixed Limits)readonly: Runtime Constants, Configuration, DI, Instance Stateinit: Immutable Properties สำหรับ DTOs/Records- หลีกเลี่ยง
constสำหรับค่าที่อาจเปลี่ยน (Versioning Risk)