執行結果展示
Adding: 2 1 2 6 1 5 9 0 5
Retrieving collections…
Integers: 0,1,1,1,2,2,5,5,6,9
Employees: George, John, Paul, Ringo
約束設計核心
Employee 實作 IComparable<Employee>
public class Employee : IComparable
{
private string _name;
public Employee(string name) => _name = name;
public int CompareTo(Employee other) => _name.CompareTo(other._name);
public bool Equals(Employee other) => _name == other._name;
public override string ToString() => _name;
}
Node 約束鏈:節點與資料雙重約束
// 節點本身可比較,且要求資料型別 T 也可比較
public class Node : IComparable> where T : IComparable
{
public T Data { get; }
public Node Next { get; private set; }
public Node Prev { get; private set; }
public int CompareTo(Node other) => Data.CompareTo(other.Data); // 安全:編譯期保證 T 實作 IComparable
}
LinkedList 繼承約束
public class LinkedList where T : IComparable
{
private Node _head;
public void Add(T data)
{
var newNode = new Node(data);
_head = _head == null ? newNode : _head.Add(newNode);
}
}
遞迴插入邏輯
public Node Add(Node newNode)
{
if (this.CompareTo(newNode) > 0) // 新節點較小,插入前方
{
newNode.Next = this;
if (this.Prev != null)
{
this.Prev.Next = newNode;
newNode.Prev = this.Prev;
}
this.Prev = newNode;
return newNode; // 新頭節點
}
else // 插入後方
{
if (this.Next != null)
this.Next.Add(newNode); // 遞迴
else
{
this.Next = newNode;
newNode.Prev = this;
}
return this; // 維持原頭節點
}
}
約束帶來的安全性保證
| 無約束風險 | 有約束保證 |
| 執行時才發現型別不支援比較 | 編譯期直接報錯 |
需防禦性檢查 is IComparable | 直接呼叫 CompareTo 無需判斷 |
| 文件說明易過時 | 型別系統強制執行契約 |
進階約束模式
// 多重約束
public class Repository where T : class, IEntity, new()
// 建構式約束
public class Factory where T : new()
// 實值/參考型別約束
public class StructProcessor where T : struct
public class ClassProcessor where T : class
// 不受約束型別參數
public class Unconstrained { }
最佳實踐總結
- 集合、資料結構、演算法庫 必須 使用約束確保型別能力
- 優先使用
IComparable<T> 而非非泛型 IComparable
- 約束應盡可能精確(
where T : IComparable<T> 優於 where T : IComparable)
- 公開 API 的約束即文件,減少執行時驚喜