陣列為可變且具協變性:D[] 可傳給參數為 B[] 的方法(D : B)。但方法內若寫入 D2(同樣繼承 B),執行期會拋 ArrayTypeMismatchException。
D[] array = new D[10]; // 填入 D 實例
DestroyCollection(array); // 參數為 B[]
void DestroyCollection(B[] storage)
{
for (int i = 0; i < storage.Length; i++) storage[i] = new D2(); // 執行期錯誤
}
.NET 2.0+ 泛型集合(List<T>、IEnumerable<T> 等)為不可變:IEnumerable<D> 無法隱性轉為 IEnumerable<B>,編譯期即報錯,避免上述執行期錯誤。
IEnumerable<int> items = Enumerable.Range(1, 50);
WriteItems(items); // CS1502/CS1503 編譯錯誤
void WriteItems(IEnumerable<object> seq) { ... }
out T(協變):用於輸出位置(如 IEnumerable<out T>),允許 IEnumerable<D> → IEnumerable<B>。in T(逆變):用於輸入位置(如 IComparer<in T>),允許 IComparer<B> → IComparer<D>。陣列協變性源自早期設計,保留相容性但不安全;泛型集合採不變性確保型別安全。C# 4.0 引入變異數註記,讓介面設計者明確宣告協變/逆變意圖,兼顧彈性與安全。