Je vais essayer de clarifier la réponse d'Anthony Pegram.
Le type générique est covariant sur un argument de type lorsqu'il renvoie des valeurs dudit type (par exemple, Func<out TResult>
renvoie des instances de TResult
, IEnumerable<out T>
renvoie des instances de T
). Autrement dit, si quelque chose renvoie des instances de TDerived
, vous pouvez également travailler avec de telles instances comme si elles étaient de TBase
.
Le type générique est contravariant sur certains arguments de type lorsqu'il accepte des valeurs dudit type (par exemple, Action<in TArgument>
accepte des instances de TArgument
). Autrement dit, si quelque chose nécessite des instances de TBase
, vous pouvez également passer des instances de TDerived
.
Il semble tout à fait logique que les types génériques qui acceptent et renvoient des instances d'un certain type (à moins qu'il ne soit défini deux fois dans la signature de type générique, par exemple CoolList<TIn, TOut>
) ne soient ni covariants ni contravariants sur l'argument de type correspondant. Par exemple, List
est défini dans .NET 4 comme List<T>
, pas List<in T>
ou List<out T>
.
Certaines raisons de compatibilité peuvent avoir amené Microsoft à ignorer cet argument et à rendre les tableaux covariants sur leur argument de type valeurs. Peut-être ont-ils mené une analyse et constaté que la plupart des gens n'utilisent que des tableaux comme s'ils étaient en lecture seule (c'est-à-dire qu'ils n'utilisent que des initialiseurs de tableau pour écrire certaines données dans un tableau), et, en tant que tels, les avantages l'emportent sur les inconvénients causés par une exécution possible. erreurs lorsque quelqu'un essaiera d'utiliser la covariance lors de l'écriture dans le tableau. Par conséquent, il est autorisé mais pas encouragé.
Quant à votre question d'origine, list.ToArray()
crée une nouvelle LinkLabel[]
avec des valeurs copiées de la liste d'origine, et, pour se débarrasser de l'avertissement (raisonnable), vous devrez passer Control[]
à AddRange
. list.ToArray<Control>()
fera le travail: ToArray<TSource>
accepte IEnumerable<TSource>
comme argument et retourne TSource[]
; List<LinkLabel>
implémente en lecture seule IEnumerable<out LinkLabel>
, qui, grâce à la IEnumerable
covariance, pourrait être passée à la méthode acceptant IEnumerable<Control>
comme argument.
LinkLabel
(type spécialisé) àControl
(type de base).