Saya akan mencoba menjelaskan jawaban Anthony Pegram.
Tipe generik adalah kovarian pada beberapa argumen tipe ketika ia mengembalikan nilai-nilai dari tipe tersebut (misalnya Func<out TResult>
mengembalikan instance dari TResult
, IEnumerable<out T>
mengembalikan instance dari T
). Artinya, jika sesuatu mengembalikan instance TDerived
, Anda juga dapat bekerja dengan instance seperti seolah-olah berasal dari TBase
.
Tipe generik bersifat contravarian pada beberapa argumen tipe ketika ia menerima nilai dari tipe tersebut (mis. Action<in TArgument>
Menerima instance dari TArgument
). Artinya, jika sesuatu membutuhkan contoh TBase
, Anda juga dapat lulus dalam contoh TDerived
.
Tampaknya cukup logis bahwa tipe generik yang menerima dan mengembalikan instance dari beberapa tipe (kecuali jika didefinisikan dua kali dalam tanda tangan tipe generik, misalnya CoolList<TIn, TOut>
) tidak kovarian atau kontravarian pada argumen tipe yang sesuai. Misalnya, List
didefinisikan dalam .NET 4 sebagai List<T>
, bukan List<in T>
atau List<out T>
.
Beberapa alasan kompatibilitas mungkin menyebabkan Microsoft mengabaikan argumen itu dan membuat array kovarian pada argumen tipe nilai mereka. Mungkin mereka melakukan analisis dan menemukan bahwa kebanyakan orang hanya menggunakan array seolah-olah hanya dibaca (yaitu, mereka hanya menggunakan inisialisasi array untuk menulis beberapa data ke dalam array), dan, dengan demikian, kelebihannya melebihi kerugian yang disebabkan oleh kemungkinan runtime kesalahan ketika seseorang akan mencoba memanfaatkan kovarians saat menulis ke dalam array. Oleh karena itu diperbolehkan tetapi tidak dianjurkan.
Adapun pertanyaan asli Anda, list.ToArray()
menciptakan baru LinkLabel[]
dengan nilai-nilai disalin dari daftar asli, dan, untuk menyingkirkan (wajar) peringatan, Anda harus lulus dalam Control[]
untuk AddRange
. list.ToArray<Control>()
akan melakukan pekerjaan: ToArray<TSource>
menerima IEnumerable<TSource>
sebagai argumennya dan kembali TSource[]
; List<LinkLabel>
mengimplementasikan read-only IEnumerable<out LinkLabel>
, yang, berkat IEnumerable
kovarian, dapat diteruskan ke metode menerima IEnumerable<Control>
sebagai argumennya.
LinkLabel
(tipe khusus) keControl
(tipe dasar).