| 版本 | 特性 |
| C# 1.0 | 陣列、ArrayList 非安全協變(執行時才檢查) |
| C# 2.0 | 泛型集合不變(編譯期保證型別安全) |
| C# 4.0 | 介面/委托支援 out/in 宣告協變/逆變 |
陣列與 ArrayList 的非安全協變
object[] arr = new string[10]; // 編譯通過
arr[0] = 123; // 執行時拋 ArrayTypeMismatchException
ArrayList list = new ArrayList { "a", "b" };
Process(list); // void Process(ArrayList o) { o[0] = 123; } // 運行時出錯
編譯器無法攔截,風險轉移到運行時。
泛型集合的不變性
IEnumerable<object> seq = Enumerable.Range(1, 5); // 編譯錯誤 CS1503
// IEnumerable<int> 不繼承 IEnumerable<object>
雖 int : object,但 IEnumerable<int> 與 IEnumerable<object> 無繼承關係,編譯期阻擋潛在錯誤。
C# 4.0 突破:介面與委托的變異標註
// 協變:只輸出 T
interface IEnumerable { IEnumerator GetEnumerator(); }
// 逆變:只輸入 T
interface IComparer { int Compare(T x, T y); }
// 委托同理
delegate TResult Func(T arg);
實際受益
IEnumerable strings = new List();
IEnumerable
限制條件
- 僅限介面與委托,類別不支援
- 型別參數必須只出現在輸入或只出現在輸出位置
ref/out 參數不參與變異
- 值型別不參與(
IEnumerable 不轉 IEnumerable)
總結
C# 4.0 以編譯期靜態檢查取代運行時風險,在型別安全與靈活性間取得平衡。善用 out/in 設計 API,可大幅提升泛型復用性。
- 上一篇文章: 再談 C# 掃雷:MVC 風格架構與邏輯視圖分離設計心得
- 下一篇文章: C# 網路版鬥地主實戰(三):出牌權限傳遞機制完整實現
Copyright ©
程式碼之家 All Rights Reserved