2016-03-09 5 views
5

Ho combattuto contro la covarianza e la contravarianza per alcuni giorni e penso di aver capito qualcosa, ma speravo di ottenere conferma su questo perché non sono stato in grado di ottenere una risposta affermativa o negativa attraverso il mio attuale ricerca. Ho la seguente gerarchia di classe:Si prega di assistenza nel confermare se la mia comprensione della covarianza qui è corretta?

class Shape 
{ 
    public string Name { get; set; } 
} 
class Square : Shape 
{ 

} 

Quindi, questo è quello che ho quello che ho iniziato il programma con:

List<Square> squares = new List<Square>() { new Square { Name = "Square One" }, new Square { Name = "Square Two" } }; 
IEnumerable<Square> squaresEnum = squares; 

Ora sono le due domande che ho:

è la seguente possibile perché IEnumerable < T> è covariante:

IEnumerable<Shape> shapesEnumerable = squares; 

E, è il f susseguente NON possibile perché Lista < T> NON è covariante:

List<Shape> shapes = squares; 

Ecco il codice completo programma che è richiesto per qualsiasi cosa:

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<Square> squares = new List<Square>() { new Square { Name = "Square One" }, new Square { Name = "Square Two" } }; 
     IEnumerable<Square> squaresEnum = squares; 

     /* Does this work because IEnumerable<T> is covariant? */ 
     IEnumerable<Shape> shapesEnumerable = squares; 

     /* Does this NOT work because List<T> is NOT covariant */ 
     //List<Shape> shapes = squares; 

     Console.ReadKey(); 
    } 
} 
class Shape 
{ 
    public string Name { get; set; } 
} 
class Square : Shape 
{ 

} 

prega si potrebbe farmi sapere se sono in la pista giusta con questo?

+2

Sì; è corretto. – SLaks

+1

@SLaks Grazie mille! – macmatthew

risposta

2

Sì, siete sulla buona strada.

questo codice non era consentito, perché possiamo avere questa situazione difficile.

Possiamo creare nuova classe come THS:

classe Triangolo: Shape {}

Poi

IEnumerable<Shape> triangles = new List<Triangle>() 
{ 
     new Triangle { Name = "Triangle One" }, 
     new Triangle { Name = "Triangle Two" } 
}; 

E ora, se questo caso può essere ammessa

List<Shape> squares = new List<Square> { ... }; 

Possiamo sviluppare in questo modo

squares.AddRange(triangles); 

o altri problemi come questo.

Il compilatore NET è molto intelligente :)

1

questo è un buon caso di covarianza. IEnumerable<T> definisce T come out T, quindi un IEnumerable<Square> può essere assegnato a IEnumerable<Shape>. Il motivo per cui non è possibile farlo con List<T> è che non è un'interfaccia e solo le interfacce possono dichiarare co- e controvarianza.

Inoltre, non ha senso che List<T> abbia T essere covariante, in quanto viene anche utilizzato come input, evidenziato dall'esempio fornito da Arlyom Tonoyan. IEnumerable<T> può essere definito come tale poiché viene utilizzato solo come output.