Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

Final Variables ใน C# (readonly / const)

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

Featureconstreadonly
Evaluation TimeCompile-timeRuntime
StaticImplicit staticInstance or Static
Allowed TypesPrimitives, String, Enum, NullAny Type
AssignmentAt Declaration OnlyDeclaration or Constructor
VersioningBurned into Caller AssemblyResolved at Runtime
Use CaseUniversal 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 State
  • init: Immutable Properties สำหรับ DTOs/Records
  • หลีกเลี่ยง const สำหรับค่าที่อาจเปลี่ยน (Versioning Risk)