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

Static Constructor ใน C# เรียกเมื่อไหร่ และวิธีใช้

Static Constructor คืออะไร?

Constructor מיוחדสำหรับ Initialize Static Members หรือ ทำ Action ที่ต้องทำครั้งเดียว

เมื่อไหร่ถูกเรียก?

  • ก่อนสร้าง Instance แรก ของ Class
  • ก่อนเข้าถึง Static Member แรก (Field, Property, Method)
  • รับประกัน: รันครั้งเดียวต่อ AppDomain, Thread-Safe
  • ไม่สามารถคาดเดา/ควบคุม Timing ได้แม่นยำ

คุณสมบัติ

  • ไม่มี Access Modifier (public, private ห้ามใช้)
  • ไม่มี Parameter
  • Class/Struct มีได้สูงสุด 1 ตัว
  • ไม่สืบทอด (Inherit) ไม่ได้, Overload ไม่ได้
  • ไม่สามารถเรียกโดยตรงได้ (CLR เรียกให้อัตโนมัติ)

Syntax


class MyClass
{
    static MyClass()
    {
        // Initialization Code
        Console.WriteLine("Static Constructor Executed");
    }
    
    public static int StaticField = 10;
    
    public MyClass() // Instance Constructor
    {
        Console.WriteLine("Instance Constructor");
    }
}

ตัวอย่างการทำงาน


using System;

class Demo
{
    static Demo()
    {
        Console.WriteLine("Static Constructor Called");
        InitializeStaticData();
    }
    
    static void InitializeStaticData()
    {
        Console.WriteLine("Initializing static data...");
    }
    
    public Demo()
    {
        Console.WriteLine("Instance Constructor Called");
    }
    
    public static void StaticMethod()
    {
        Console.WriteLine("Static Method Called");
    }
}

class Program
{
    static void Main()
    {
        Console.WriteLine("--- Before any access ---");
        
        // Static Constructor ยังไม่รัน
        
        Console.WriteLine("--- Access Static Field ---");
        Console.WriteLine(Demo.StaticField); // Static Constructor รันที่นี่
        
        Console.WriteLine("--- Create Instance 1 ---");
        new Demo(); // Static Constructor ไม่รันซ้ำ
        
        Console.WriteLine("--- Call Static Method ---");
        Demo.StaticMethod(); // Static Constructor ไม่รันซ้ำ
        
        Console.WriteLine("--- Create Instance 2 ---");
        new Demo();
        
        Console.ReadLine();
    }
}

Output

--- Before any access ---
--- Access Static Field ---
Static Constructor Called
Initializing static data...
10
--- Create Instance 1 ---
Instance Constructor Called
--- Call Static Method ---
Static Method Called
--- Create Instance 2 ---
Instance Constructor Called

Use Cases (กรณีใช้งาน)

  1. Initialize Static Collections: Cache, Lookup Tables
  2. Load Configuration: อ่าน Config File ครั้งเดียว
  3. Native Library Init: P/Invoke Setup
  4. Singleton Pattern (Legacy): Thread-Safe Initialization

class Config
{
    public static string ConnectionString { get; private set; }
    public static int MaxRetry { get; private set; }
    
    static Config()
    {
        // Load from appsettings.json / Environment Variables
        ConnectionString = File.ReadAllText("conn.txt");
        MaxRetry = int.Parse(Environment.GetEnvironmentVariable("MAX_RETRY") ?? "3");
    }
}

Exception Handling

⚠️ Exception ใน Static Constructor = TypeInitializationException
- Type จะ Unusable ตลอด Age ของ AppDomain
- Retry ไม่ได้ ต้อง Restart Process
- ต้อง Try/Catch ภายใน Static Constructor เอง

static MyClass()
{
    try
    {
        RiskyInitialization();
    }
    catch (Exception ex)
    {
        // Log, Set Fallback Values
        _fallback = true;
        // ไม่ Re-throw ไม่งั้น Type จะตาย
    }
}

Static Constructor vs Static Field Initializer

Static Field InitializerStatic Constructor
static int X = Compute();static MyClass() { X = Compute(); }
Simple, InlineComplex Logic, Multiple Statements
Exception → TypeInitializationExceptionException → TypeInitializationException
Order: ตามลำดับ DeclarationOrder: ก่อน First Access

ทั้งคู่รันก่อน First Access แต่ Static Constructor ให้ Control มากกว่า