建構函式預設為 `public`,允許外部自由建立實例。將建構函式標記為 `private` 或 `protected`,能從語言層面控制物件的建立方式,是實作單例模式、工廠模式、靜態工具類別的基石。本文深入解析私有建構函式的特性、限制與實戰應用模式。
public class Animal
{
private Animal() { Console.WriteLine("Animal ctor"); }
}
public class Dog : Animal // 編譯錯誤 CS0122:'Animal.Animal()' 因保護層級而無法存取
{
}

public class Program
{
static void Main()
{
Animal a = new Animal(); // 編譯錯誤 CS0122
}
}
public class Animal
{
private Animal() { }
}

public sealed class Singleton
{
private static volatile Singleton _instance;
private static readonly object _lock = new object();
private Singleton()
{
Console.WriteLine("Singleton 建構函式執行");
// 初始化昂貴資源:資料庫連線、設定檔載入等
}
public static Singleton Instance
{
get
{
if (_instance == null)
{
lock (_lock)
{
if (_instance == null)
_instance = new Singleton();
}
}
return _instance;
}
}
public void DoWork() => Console.WriteLine("執行業務邏輯");
}
// 使用
Singleton.Instance.DoWork();
public class DatabaseConnection
{
public string ConnectionString { get; }
public int Timeout { get; }
private DatabaseConnection(string connStr, int timeout)
{
ConnectionString = connStr;
Timeout = timeout;
}
/// <summary>建立預設連線</summary>
public static DatabaseConnection CreateDefault()
=> new DatabaseConnection("Server=.;Database=Test;Integrated Security=true;", 30);
/// <summary>建立唯讀複本連線</summary>
public static DatabaseConnection CreateReadOnlyReplica()
=> new DatabaseConnection("Server=Replica;Database=Test;Integrated Security=true;", 10);
/// <summary>從組態區段建立</summary>
public static DatabaseConnection FromConfiguration(string sectionName)
{
var config = ConfigurationManager.ConnectionStrings[sectionName];
return new DatabaseConnection(config.ConnectionString, 30);
}
}
// 使用:語意清晰,無法誤用
var conn1 = DatabaseConnection.CreateDefault();
var conn2 = DatabaseConnection.CreateReadOnlyReplica();
var conn3 = DatabaseConnection.FromConfiguration("ProductionDB");
public static class MathUtils
{
// C# 靜態類別隱含私有建構函式,無法實例化、無法繼承
// 但若為非靜態類別需手動加私有建構函式:
// private MathUtils() { } // 明確防止實例化
public static double CalculateDistance(Point a, Point b)
=> Math.Sqrt(Math.Pow(a.X - b.X, 2) + Math.Pow(a.Y - b.Y, 2));
public static bool IsPrime(int n)
{
if (n < 2) return false;
for (int i = 2; i * i <= n; i++)
if (n % i == 0) return false;
return true;
}
}
public class ExpensiveResource
{
private static readonly ConcurrentDictionary _cache
= new ConcurrentDictionary();
public string ResourceKey { get; }
public byte[] Data { get; }
private ExpensiveResource(string key)
{
ResourceKey = key;
Data = LoadFromDiskOrNetwork(key); // 昂貴操作
}
public static ExpensiveResource GetOrCreate(string key)
{
return _cache.GetOrAdd(key, k => new ExpensiveResource(k));
}
public static void Invalidate(string key) => _cache.TryRemove(key, out _);
public static void Clear() => _cache.Clear();
}
public abstract class EntityBase
{
public int Id { get; protected set; }
protected EntityBase() { } // 衍生類別可呼叫,外部不可 new
protected EntityBase(int id) => Id = id;
}
public class User : EntityBase
{
public string Name { get; set; }
public User() : base() { } // 必須明確呼叫 base()
public User(int id, string name) : base(id) { Name = name; }
}
// 外部無法 new EntityBase(),但可 new User()
var user = new User(1, "Tom");
public class Config
{
public required string ApiKey { get; init; }
public required string Endpoint { get; init; }
public int Timeout { get; init; } = 30;
}
// 呼叫端必須提供 required 屬性
var cfg = new Config { ApiKey = "key", Endpoint = "https://api" };
public record UserDto(int Id, string Name, string Email);
// 自動產生:建構函式、不可變屬性、with-expression、ToString、Equality
var user = new UserDto(1, "Tom", "tom@example.com");
var updated = user with { Name = "Tommy" };
| 需求 | 建構函式 | 類別修飾詞 | 適用模式 |
|---|---|---|---|
| 全域唯一實例 | private | sealed class | Singleton |
| 語意化建構、驗證邏輯 | private | class | Static Factory |
| 純靜態方法、無狀態 | private (隱含) | static class | Utility Class |
| 基底類別、需繼承 | protected | abstract class | Template Method |
| 不可變資料傳輸 | public (自動) | record | DTO / Value Object |
私有建構函式是「封裝物件建立邏輯」的核心工具。它不只是語法限制,更是設計意圖的宣示:此類別的實例建立受控、有條件、有語意。善用私有建構函式搭配靜態工廠方法、單例、物件池等模式,能寫出更安全、更具表達力、更易測試的 C# 程式碼。