Proverò a chiarire la risposta di Anthony Pegram.
Il tipo generico è covariante su alcuni argomenti di tipo quando restituisce valori di detto tipo (ad es. Func<out TResult>
Restituisce istanze di TResult
, IEnumerable<out T>
restituisce istanze di T
). Cioè, se qualcosa restituisce istanze di TDerived
, puoi anche lavorare con tali istanze come se fossero di TBase
.
Il tipo generico è contraddittorio su alcuni argomenti di tipo quando accetta valori di detto tipo (ad es. Action<in TArgument>
Accetta istanze di TArgument
). Cioè, se qualcosa ha bisogno di istanze di TBase
, puoi anche passare in istanze di TDerived
.
Sembra abbastanza logico che i tipi generici che accettano e restituiscono istanze di un certo tipo (a meno che non sia definito due volte nella firma del tipo generico, ad es. CoolList<TIn, TOut>
) Non sono covarianti né contraddittori sull'argomento di tipo corrispondente. Ad esempio, List
è definito in .NET 4 come List<T>
, non List<in T>
o List<out T>
.
Alcuni motivi di compatibilità potrebbero aver fatto sì che Microsoft ignorasse quell'argomento e rendesse gli array covarianti sull'argomento del tipo di valori. Forse hanno condotto un'analisi e hanno scoperto che la maggior parte delle persone utilizza array solo come se fossero di sola lettura (ovvero usano solo inizializzatori di array per scrivere alcuni dati in un array) e, come tali, i vantaggi prevalgono sugli svantaggi causati da un possibile runtime errori quando qualcuno tenterà di utilizzare la covarianza durante la scrittura nell'array. Quindi è permesso ma non incoraggiato.
Per quanto riguarda la tua domanda originale, list.ToArray()
crea una nuova LinkLabel[]
con i valori copiati dall'elenco originale e, per sbarazzarti di un avviso (ragionevole), dovrai passare Control[]
a AddRange
. list.ToArray<Control>()
farà il lavoro: ToArray<TSource>
accetta IEnumerable<TSource>
come argomento e restituisce TSource[]
; List<LinkLabel>
implementa la sola lettura IEnumerable<out LinkLabel>
, che, grazie alla IEnumerable
covarianza, potrebbe essere passata al metodo accettando IEnumerable<Control>
come argomento.
LinkLabel
(tipo specializzato) aControl
(tipo base).