泛型類別操作未知型別 T 時,若需呼叫 T 的特定方法(如比較),必須在編譯期保證 T 擁有該能力。where T : IComparable<T> 即為此契約。
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;
}
public class Node : IComparable> where T : IComparable
{
private T _data;
private Node _next;
private Node _prev;
public Node(T data) => _data = data;
public T Data => _data;
public Node Next => _next;
public int CompareTo(Node other) => _data.CompareTo(other._data);
public bool Equals(Node other) => _data.Equals(other._data);
// 遞迴插入:維持升序
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; // 維持原頭節點
}
}
public override string ToString()
{
string output = _data.ToString();
if (_next != null) output += ", " + _next.ToString();
return output;
}
}
public class LinkedList where T : IComparable
{
private Node _head;
public T this[int index]
{
get
{
int ctr = 0;
var node = _head;
while (node != null && ctr <= index)
{
if (ctr == index) return node.Data;
node = node.Next;
ctr++;
}
throw new ArgumentOutOfRangeException();
}
}
public void Add(T data)
{
_head = _head == null ? new Node(data) : _head.Add(new Node(data));
}
public override string ToString() => _head?.ToString() ?? string.Empty;
}
public class Test
{
public void Run()
{
var intList = new LinkedList();
var rand = new Random();
Console.Write("Adding: ");
for (int i = 0; i < 10; i++)
{
int n = rand.Next(10);
Console.Write($"{n} ");
intList.Add(n);
}
var empList = new LinkedList();
empList.Add(new Employee("John"));
empList.Add(new Employee("Paul"));
empList.Add(new Employee("George"));
empList.Add(new Employee("Ringo"));
Console.WriteLine("\nIntegers: " + intList);
Console.WriteLine("Employees: " + empList);
}
}
LinkedList where T : IComparable
→ Node where T : IComparable
→ T.CompareTo(T) // 編譯期保證合法
_head = _head.Add(...) 更新頭指標鏈表不支援隨機存取,索引器需從頭遍歷,適合頻繁插入刪除、稀少隨機存取場景。
| 約束類型 | 語法 | 適用場景 |
|---|---|---|
| 介面約束 | where T : IInterface | 需要特定行為契約 |
| 基類約束 | where T : BaseClass | 需要共享基類功能 |
| 建構式約束 | where T : new() | 需無參數建構實例 |
| 實值型別約束 | where T : struct | 堆疊分配、免 GC |
| 參考型別約束 | where T : class | 可為 null、參考語意 |
| 非受控型別約束 | where T : unmanaged | 可用 stackalloc、指標運算 |
// 錯誤:非泛型 IComparable 無法提供型別安全
public class BadNode : IComparable> where T : IComparable
// 正確:泛型 IComparable 保證 CompareTo 參數型別正確
public class GoodNode : IComparable> where T : IComparable