Come è la covarianza generica & amp; Contro-varianza implementata in C # 4.0?
-
05-07-2019 - |
Domanda
Non ho partecipato a PDC 2008, ma ho sentito alcune notizie che C # 4.0 è stato annunciato per supportare la covarianza e la contro-varianza generiche. In altre parole, List < string >
può essere assegnato a List < object >
. Come potrebbe essere?
Nel libro di Jon Skeet C # in profondità , viene spiegato perché i generici di C # non supportano la covarianza e la contro-varianza. È principalmente per la scrittura di codice sicuro. Ora, C # 4.0 è cambiato per supportarli. Porterebbe il caos?
Qualcuno sa che i dettagli su C # 4.0 possono dare qualche spiegazione?
Soluzione
La varianza sarà supportata solo in modo sicuro - in effetti, usando le abilità che il CLR possiede già. Quindi gli esempi che do nel libro di come provare a usare un Elenco < Banana >
come un Elenco < Fruit >
(o qualunque cosa fosse) non funzioneranno ancora - ma alcuni altri scenari lo faranno.
In primo luogo, sarà supportato solo per interfacce e delegati.
In secondo luogo, richiede all'autore dell'interfaccia / delegato di decorare i parametri di tipo come in
(per contravarianza) o out
(per covarianza). L'esempio più ovvio è IEnumerable < T >
che ti permette sempre e solo di prendere valori "quot & out" di esso - non ti consente di aggiungerne di nuovi. Questo diventerà IEnumerable < out T >
. Ciò non pregiudica affatto la sicurezza dei tipi, ma ti consente di restituire un IEnumerable < string >
da un metodo dichiarato per restituire IEnumerable < object >
per esempio.
La contraddizione è più difficile fornire esempi concreti sull'uso delle interfacce, ma è facile con un delegato. Considera Azione < T >
- che rappresenta solo un metodo che accetta un parametro T
. Sarebbe bello poter convertire senza problemi usando un Action < object >
come Action < string >
- qualsiasi metodo che accetta un oggetto
il parametro andrà bene quando viene presentato con una stringa
. Naturalmente, C # 2 ha già una certa covarianza e contraddizione dei delegati, ma tramite una conversione effettiva da un tipo di delegato a un altro (creando una nuova istanza) - vedere P141-144 per esempi. C # 4 renderà questo più generico e (credo) eviterà di creare una nuova istanza per la conversione. (Sarà invece una conversione di riferimento.)
Spero che questo chiarisca un po '- per favore fatemi sapere se non ha senso!
Altri suggerimenti
Non che Jon non l'abbia già trattato, ma ecco alcuni link a blog e video di Eric Lippert. Fa un buon lavoro nel spiegarlo con esempi.
https://blogs.msdn.microsoft.com/ericlippert/2007/10/16/covariance-and-contravariance-in-c-part-one/
I video:
https://www.youtube.com/watch?v=3MQDrKbzvqU