泛型 是「型別參數化」:在定義類別、方法、介面、委派時,將具體型別延遲到使用時才指定。如 List<T> 中的 T 為型別參數,實例化時決定為 int、string 或自訂類別。
InvalidCastException。object,大幅提升效能與減少 GC 壓力。
public class PersonCollection : IList
{
private ArrayList _list = new ArrayList();
public Person this[int i] { get { return (Person)_list[i]; } }
public int Add(Person p) { _list.Add(p); return _list.Count - 1; }
// 必須顯式實作 IList 介面,大量轉型程式碼...
object IList.this[int i] { get { return _list[i]; } set { _list[i] = (Person)value; } }
int IList.Add(object o) { return Add((Person)o); }
// 若要支援 Dog、Order 等類別,必須複製修改類別名稱...
}
List persons = new List();
persons.Add(new Person());
Person p = persons[0]; // 無轉型、型別安全
List dogs = new List();
dogs.Add(new Dog());
Dog d = dogs[0];
// 非泛型 ArrayList
ArrayList list = new ArrayList();
list.Add(5); // 裝箱:int → object
int i = (int)list[0]; // 拆箱:object → int
// 泛型 List
List list2 = new List();
list2.Add(5); // 無裝箱
int j = list2[0]; // 無拆箱
大量資料時,裝箱/拆箱產生大量暫存物件,觸發 Gen 0 GC,影響效能。泛型避免此問題。
static void Swap(ref T a, ref T b)
{
Console.WriteLine("Type: {0}", typeof(T));
T temp = a; a = b; b = temp;
}
public class Point
{
public T X { get; set; }
public T Y { get; set; }
public override string ToString() => $"[{X}, {Y}]";
}
| 約束 | 語法 | 說明 |
|---|---|---|
| 實值型別 | where T : struct | 不可為 Nullable |
| 參考型別 | where T : class | 類別、介面、委派、陣列 |
| 預設建構函式 | where T : new() | 需有 public 無參數建構函式 |
| 基底類別/介面 | where T : BaseClass / where T : IInterface | 限定繼承鏈 |
| 組合約束 | where T : class, IComparable, new() | 多重條件 |
List<int> 等封閉構造型別,CLR 以實際型別替換佔位符產生機器碼。
List<string>、List<object>)。List<int>、List<double> 各一份),確保正確的記憶體配置與指令。+、- 等運算子,需透過介面或 dynamic)。MyClass<int>.StaticField 與 MyClass<string>.StaticField 獨立)。typeof(T) 取得泛型定義(需 typeof(MyClass<>))。泛型不只是型別安全與效能工具,更實現了「橫向抽象」:將演算法與資料結構從具體型別解耦,類似 AOP 的關注點分離。繼承提供「縱向」關係(is-a),泛型提供「橫向」關係(演算法套用於任意型別)。這種抽象能力是現代靜態型別語言表達力的關鍵。
精通泛型約束、共變/反變、執行機制,能設計出高效能、高重用的程式庫。日常開發請優先使用 List<T>、Dictionary<TKey,TValue> 等內建泛型集合,避免 ArrayList、Hashtable 等非泛型類別。