承上篇,C++ Template 成功解決策略介面型別綁定問題。本文嘗試用 C# 2.0 Generics 達成相同目標,並探討兩者關鍵差異:C# Generic 屬於「受限泛型」,需透過 where 子句約束型別參數。
策略介面改為泛型:
interface IShape<T> {
void draw(T grapher);
}
具體策略類別必須宣告:
class Triangle<T> : IShape<T> where T : IGrapher {
public void draw(T grapher) {
Console.WriteLine("Draw {0:s} in Triangle", grapher.getText());
}
}
where T : IGrapher 表示型別參數 T 必須實作 IGrapher 介面。這是 C# Generic 與 C++ Template 最大不同:C++ 編譯期鴨子型別,C# 則要求明確介面約束。
interface IGrapher {
string getText();
}
確保所有傳入策略的物件皆擁有 getText() 方法,編譯器才允許呼叫。
| 特性 | C++ Template | C# Generic |
|---|---|---|
| 型別檢查時機 | 編譯期實例化時 | 定義期即檢查約束 |
| 型別限制 | 無(鴨子型別) | 需透過 where 约束 |
| 程式碼膨脹 | 會產生多份實例碼 | 單一份 IL 共享 |
| 執行效能 | 零額外負擔 | 略有 boxing/unboxing 考量 |
雖然 C# Generic 較嚴謹,但也帶來更好的型別安全與 IntelliSense 支援。