Je vais essayer de clarifier la réponse d'Anthony Pegram.
Un type générique est covariant sur un argument de type lorsqu'il renvoie des valeurs de ce type (par ex. Func<out TResult>
renvoie des instances de TResult
, IEnumerable<out T>
renvoie des instances de T
). En d'autres termes, si quelque chose renvoie des instances de TDerived
vous pouvez aussi bien travailler avec de telles instances comme si elles étaient de TBase
.
Un type générique est contravariant sur un argument de type lorsqu'il accepte des valeurs de ce type (par ex. Action<in TArgument>
accepte les instances de TArgument
). En d'autres termes, si quelque chose a besoin d'instances de TBase
vous pouvez aussi passer dans les cas de TDerived
.
Il semble assez logique que les types génériques qui acceptent et renvoient des instances d'un certain type (sauf s'il est défini deux fois dans la signature du type générique, par ex. CoolList<TIn, TOut>
) ne sont ni covariants ni contravariants sur l'argument de type correspondant. Par exemple, List
est défini dans .NET 4 comme List<T>
no List<in T>
o List<out T>
.
Certaines raisons de compatibilité ont pu amener Microsoft à ignorer cet argument et à rendre les tableaux covariants sur leur argument de type de valeurs. Ils ont peut-être mené une analyse et constaté que la plupart des gens n'utilisent les tableaux que comme s'ils étaient en lecture seule (c'est-à-dire qu'ils n'utilisent les initialisateurs de tableaux que pour écrire des données dans un tableau) et, en tant que tels, les avantages l'emportent sur les inconvénients causés par d'éventuelles erreurs d'exécution lorsque quelqu'un essaie d'utiliser la covariance lors de l'écriture dans le tableau. C'est pourquoi elle est autorisée mais pas encouragée.
Quant à votre question initiale, list.ToArray()
crée un nouveau LinkLabel[]
avec des valeurs copiées à partir de la liste originale, et, pour se débarrasser de l'avertissement (raisonnable), vous devrez passer en Control[]
a AddRange
. list.ToArray<Control>()
fera l'affaire : ToArray<TSource>
accepte IEnumerable<TSource>
comme argument et renvoie TSource[]
; List<LinkLabel>
implémente la lecture seule IEnumerable<out LinkLabel>
qui, grâce à IEnumerable
covariance, pourrait être passé à la méthode acceptant IEnumerable<Control>
comme argument.