首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 4.0 泛型協變與逆變深度解析:從陣列陷阱到安全型別參數

     編輯:關於C#

核心概念

  • 不變性:必須完全匹配型別
  • 協變性:可用衍生型別代替基底型別(輸出位置:回傳值、out 參數)
  • 逆變性:可用基底型別代替衍生型別(輸入位置:方法參數、in 參數)

C# 歷史演進

陣列與 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 objects = strings; // 合法,因 IEnumerable

Action actObj = o => Console.WriteLine(o);
Action actStr = actObj; // 合法,因 Action (逆變)

限制條件

版本特性
C# 1.0陣列、ArrayList 非安全協變(執行時才檢查)
C# 2.0泛型集合不變(編譯期保證型別安全)
C# 4.0介面/委托支援 out/in 宣告協變/逆變