Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Static Constructor trong C# dùng làm gì?

Static constructor được dùng để khởi tạo bất kỳ static data nào, hoặc thực hiện một action cụ thể cần thực hiện chỉ một lần duy nhất. Nó được gọi tự động trước khi instance đầu tiên được tạo hoặc bất kỳ static members nào được tham chiếu.

Static constructors hữu ích khi tạo wrapper classes cho unmanaged code, khi constructor có thể gọi phương thức LoadLibrary. Static constructors cũng là nơi tiện lợi để enforce run-time checks trên type parameter không thể kiểm tra tại compile time qua constraints.

Đặc điểm của Static Constructor

  • Static constructor không nhận access modifiers hoặc có parameters.
  • Một class hoặc struct chỉ có thể có một static constructor.
  • Static constructors không thể được inherited hoặc overloaded.
  • Static constructor không thể được gọi trực tiếp và chỉ được gọi bởi common language runtime (CLR). Nó được invoke tự động.
  • User không kiểm soát được khi nào static constructor được thực thi trong chương trình.
  • Static constructor được gọi tự động để khởi tạo class trước khi instance đầu tiên được tạo hoặc bất kỳ static members nào được tham chiếu. Static constructor chạy trước instance constructor. Static constructor của type được gọi khi static method gán cho event hoặc delegate được invoke chứ không phải khi nó được gán. Nếu static field variable initializers có mặt trong class của static constructor, chúng sẽ được thực thi theo thứ tự văn bản xuất hiện trong khai báo class ngay trước khi static constructor thực thi.
  • Nếu bạn không cung cấp static constructor để khởi tạo static fields, tất cả static fields được khởi tạo giá trị mặc định như liệt kê trong Default values of C# types.
  • Nếu static constructor ném exception, runtime sẽ không invoke nó lần hai, và type sẽ vẫn uninitialized cho lifetime của application domain. Thường gặp TypeInitializationException khi static constructor không thể instantiate type hoặc unhandled exception xảy ra trong static constructor. Đối với implicit static constructors không được định nghĩa explicit trong source code, troubleshooting có thể yêu cầu inspect intermediate language (IL) code.
  • Sự hiện diện của static constructor ngăn chặn việc thêm BeforeFieldInit type attribute. Điều này giới hạn runtime optimization.
  • Field khai báo static readonly chỉ có thể được gán như một phần của khai báo hoặc trong static constructor. Khi explicit static constructor không bắt buộc, hãy khởi tạo static fields tại declaration thay vì qua static constructor để tối ưu runtime tốt hơn.

Ví dụ cơ bản

using System; 

namespace DemoApplication { 
    public class Program { 
        static void Main(string[] args) { 
            Car user = new Car(); 
            Car user1 = new Car(); 
            Console.ReadLine(); 
        } 
    } 
    
    public class Car { 
        static Car() { 
            Console.WriteLine("Static constructor called"); 
        } 
        
        public Car() { 
            Console.WriteLine("Default constructor called"); 
        } 
    } 
}

Output

Static constructor called
Default constructor called
Default constructor called

Trong ví dụ trên ta thấy static constructor chỉ được gọi một lần.

Ví dụ thực tế: Khởi tạo shared resource

using System; 
using System.Threading; 

namespace DemoApplication { 
    public class Car { 
        protected static readonly DateTime globalStartTime; 
        protected int RouteNumber { get; set; } 
        
        static Car() { 
            globalStartTime = DateTime.Now; 
            Console.WriteLine($"Static constructor called. Global start time: {globalStartTime.ToLongTimeString()}"); 
        } 
        
        public Car(int routeNum) { 
            RouteNumber = routeNum; 
            Console.WriteLine($"Car {RouteNumber} is created."); 
        } 
        
        public void Drive() { 
            TimeSpan elapsedTime = DateTime.Now - globalStartTime; 
            Console.WriteLine($"Car {this.RouteNumber} is starting its route {elapsedTime.Milliseconds} minutes after global start time {globalStartTime.ToShortTimeString()}."); 
        } 
    } 
    
    class TestCar { 
        static void Main() { 
            Car car1 = new Car(1); 
            Car car2 = new Car(2); 
            car1.Drive(); 
            Thread.Sleep(25); 
            car2.Drive(); 
            Console.ReadLine(); 
        } 
    } 
}

Output

Static constructor called. Global start time: 7:09:06 AM
Car 1 is created.
Car 2 is created.
Car 1 is starting its route 25 minutes after global start time 7:09 AM.
Car 2 is starting its route 50 minutes after global start time 7:09 AM.

Static Constructor vs Instance Constructor

Đặc điểm Static Constructor Instance Constructor
Tên static ClassName() public ClassName()
Tham số Không có Có thể có
Access modifier Không có public, private, protected...
Số lượng Tối đa 1 Có thể nhiều (overload)
Khi chạy Trước instance đầu tiên hoặc static member đầu tiên Mỗi lần new Instance()
Dùng cho Khởi tạo static fields, shared resources Khởi tạo instance fields

Use Cases phổ biến

  • Khởi tạo logging configuration
  • Setup connection strings / configuration
  • Load unmanaged libraries (DLLImport)
  • Khởi tạo singleton pattern
  • Register types trong DI container
  • Validation logic phức tạp cho generic type parameters