首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 2.0 泛型約束完整指南:where 子句、介面約束、建構函式約束與實務陷阱

     編輯:關於C語言

問題情境:泛型型別參數的方法受限

public class Dictionary<K, V>
{
    public void Add(K key, V value)
    {
        if (key.CompareTo(x) < 0) { }  // 編譯錯誤:K 不保證有 CompareTo
    }
}

K 可能為任何型別,僅能呼叫 object 定義的方法(ToString 等)。

嘗試 1:強制轉型

if (((IComparable)key).CompareTo(x) < 0) { }

編譯通過,但執行期若傳入未實作 IComparable 的型別 → InvalidCastException。

C# 2.0 解法:泛型約束

使用 where 關鍵字編譯期強制檢查:

public class Dictionary<K, V> where K : IComparable
{
    public void Add(K key, V value)
    {
        if (key.CompareTo(x) < 0) { }  // 安全呼叫
    }
}

傳入未實作 IComparable 的型別 → 編譯錯誤,提前攔截。

進階約束組合

public class EntityTable<K, E>
    where K : IComparable<K>, IPersistable  // 多介面約束
    where E : Entity, new()                // 基類別 + 無參建構函式
{
    public void Add(K key, E entity)
    {
        if (key.CompareTo(x) < 0) { }
        E newEntity = new E();  // 允許建立實例
    }
}

約束類型總表

語法含義
where T : BaseClassT 必須繼承自 BaseClass(最多一個類別)
where T : InterfaceT 必須實作介面(可多個)
where T : new()T 必須有 public 無參建構函式
where T : classT 必須為參考型別
where T : structT 必須為值型別(排除 Nullable)
where T : UT 必須為 U 或其衍生型別(型別參數約束)
where T : notnullT 不可為可為 null 的型別 (C# 8.0+)
where T : unmanagedT 為非受控型別 (C# 7.3+)
where T : default覆寫繼承而來的約束 (C# 9.0+)

約束的代價:犧牲通用性

// 若 List 约束 T : IComparable
List<MyClass> list = new List<MyClass>();  // MyClass 未實作 IComparable → 編譯失敗
// 即使不呼叫 Sort() 也無法使用

設計時需權衡:約束提供型別安全與功能,但限制適用型別範圍。

實務建議

  • 盡可能使用介面約束而非基類別,保持鬆耦合
  • new() 約束適用於 Factory 模式、物件池
  • 避免過度約束,必要時提供無約束的基底類別
  • C# 7.0+ 可用 where T : unmanaged 進行高效能記憶體操作

原文參考

原文:不得不提的C#2.0泛型約束

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved