Đặc điểm Static Class
- Chỉ chứa thành viên static (fields, methods, properties, constructors).
- Không thể khởi tạo instance (
new StaticClass()→ compile error). - CLR đảm bảo chỉ có một "instance" logic per AppDomain.
- Static constructor chạy một lần duy nhất trước khi truy cập thành viên static đầu tiên.
Ví dụ chứng minh với biến đếm
using System;
static class Demo
{
public static int Count = 0;
// Static constructor - chạy 1 lần duy nhất
static Demo()
{
Console.WriteLine("Static Constructor called");
}
}
class Program
{
static void Main()
{
// Truy cập static member lần đầu → trigger static constructor
Demo.Count++;
Demo.Count++;
Console.WriteLine($"Count = {Demo.Count}"); // Output: 2
// Tạo thêm reference khác - vẫn cùng một "instance"
var ref1 = Demo.Count;
var ref2 = Demo.Count;
Demo.Count += 10;
Console.WriteLine($"Count = {Demo.Count}"); // Output: 12
Console.ReadKey();
}
}
Kết quả
Static Constructor called Count = 2 Count = 12
Phân tích
- Static Constructor chỉ in ra một lần → chứng minh class chỉ được khởi tạo một lần.
- Biến
Count được chia sẻ toàn ứng dụng → tăng từ 0 → 2 → 12. - Không có
new Demo()→ không thể tạo instance thứ 2.
So sánh: Static Class vs Singleton Pattern
| Đặc điểm | Static Class | Singleton |
|---|---|---|
| Instance | Không có instance (chỉ type) | Có 1 instance (lazy/eager) |
| Kế thừa | Không thể kế thừa | Có thể kế thừa (nếu không sealed) |
| Interface | Không implement interface | Có thể implement interface |
| Dependency Injection | Khó (cần wrapper) | Dễ dàng register singleton |
| Lazy initialization | Tự động (first access) | Có kiểm soát (Lazy<T>, double-check) |
| Dispose/Cleanup | Không có | Có thể implement IDisposable |
Static Class trong thực tế
// Utility class - phổ biến nhất
public static class StringExtensions
{
public static bool IsNullOrEmpty(this string s) => string.IsNullOrEmpty(s);
public static string ToSlug(this string s) => s.ToLower().Replace(" ", "-");
}
// Configuration holder
public static class AppConfig
{
static AppConfig()
{
// Load config once
ConnectionString = File.ReadAllText("conn.txt");
ApiKey = Environment.GetEnvironmentVariable("API_KEY");
}
public static string ConnectionString { get; private set; }
public static string ApiKey { get; private set; }
}
// Extension methods container
public static class LinqExtensions
{
public static IEnumerable DistinctBy(this IEnumerable source, Func keySelector)
{
return source.GroupBy(keySelector).Select(g => g.First());
}
}
Lưu ý quan trọng
Static class ≠ Singleton instance. Static class không có instance, không có this, không thể truyền làm tham số, không thể ép kiểu. Chỉ là container cho static members.
Thread Safety
- Static constructor: Thread-safe bởi CLR (chạy 1 lần).
- Static fields: KHÔNG thread-safe cho read/write đồng thời → dùng
lock,Interlocked,ConcurrentDictionary.
// Thread-safe counter
static class Counter
{
private static int _count = 0;
public static int Increment() => Interlocked.Increment(ref _count);
public static int Decrement() => Interlocked.Decrement(ref _count);
public static int Value => Volatile.Read(ref _count);
}