2010-10-27 19 views
14

Nel codice qui sotto:Domanda su C# covarianza

interface I1 { } 
class CI1: I1 { } 

List<CI1> listOfCI1 = new List<CI1>(); 

IEnumerable<I1> enumerableOfI1 = listOfCI1; //this works 

IList<I1> listofI1 = listOfCI1; //this does not 

sono in grado di assegnare la mia "listOfCI1" per un IEnumerable<I1> (a causa di covarianza)

Ma perché non sono io in grado di assegnare a un IList<I1>? Del resto, non si può nemmeno effettuare le seguenti operazioni:

List<I1> listOfI12 = listOfCI1; 

Non dovrebbe covarianza mi permetterà di assegnare un tipo di derivato ad un tipo di base?

risposta

24

In poche parole, IList<T> non è covariante, mentre IEnumerable<T> è. Ecco perché ...

Supponiamo che IList<T>sia covariante. Il codice sottostante non è chiaramente sicuro per tipo ... ma dove vorresti che fosse l'errore?

IList<Apple> apples = new List<Apple>(); 
IList<Fruit> fruitBasket = apples; 
fruitBasket.Add(new Banana()); // Aargh! Added a Banana to a bunch of Apples! 
Apple apple = apples[0]; // This should be okay, but wouldn't be 

Per sacco di dettagli sulla varianza, vedere Eric Lippert di blog post series su di esso, o guardare il video del mio parlare di varianza da NDC.

In sostanza, la varianza è sempre e solo permesso dove è garantito per essere sicuri (e in un certo senso la rappresentazione-conservazione, motivo per cui non è possibile convertire in IEnumerable<int>IEnumerable<object> - la conversione di boxe non conserva rappresentazione).

+0

A proposito, quel discorso è stato grandioso. –

+0

@Arnis: Grazie - mi sono divertito anch'io, anche se non sono riuscito a mostrare il video Hokey Cokey che avevo registrato ... –

+2

Jon, così ha aggiunto il team BCL (IEnumerable : IEnumerable), perché IEnumerable non ti consente di aggiungere nuovi membri (cioè il suo immutabile) rendendolo sicuro. Ma d'altra parte non ha aggiunto "out" su IList perché è mutabile (rendendo possibile aggiungere un'implementazione diversa all'elenco sottostante?) –

3

No.

In caso contrario, si dovrebbe quindi essere in grado aggiungere una diversa implementazione di I1 ad una lista che dovrebbe contenere solo C1 s.

1

IList<T> l'interfaccia non è covariante.

5

dichiarazioni confronta (MSDN)

public interface IEnumerable<out T> : IEnumerable 

public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable 

si vede che parola magica out? Ciò significa che la covarianza è attiva.

+3

In particolare, significa che 'IEnumerable ' è covariante * per 'T' *. Un'interfaccia può essere variante in alcuni parametri di tipo ma non in altri. –