2012-09-14 37 views
15

Eventuali duplicati:
Why was IEnumerable<T> made covariant in C# 4?Perché IEnumerable <T> è definito come IEnumerable <out T>, non IEnumerable <T>

stavo prendendo uno sguardo su MSDN per IEnumerable<T> definizione di interfaccia, e vedere:

public interface IEnumerable<out T> : IEnumerable 

Mi chiedevo perché T è definito come out, perché no?

public interface IEnumerable<T> : IEnumerable 

Qual è la ragione di questo?

+0

perché l'interfaccia è covariante – Jodrell

+1

un'occhiata qui http://stackoverflow.com/questions/6732299/why-was-ienumerablet-made-covariant-in-c-sharp-4 – Likurg

+0

[Covarianza e controvarianza] (http://msdn.microsoft.com/en-us/library/ee207183) – jrummell

risposta

20

Ulteriori informazioni possono essere trovate here.

Il out rende il parametro di tipo covariante. Cioè, puoi usare il tipo o qualsiasi tipo derivato. Notare che out funziona solo in questo modo con i generici, ha un significato diverso quando viene utilizzato nelle firme dei metodi (anche se probabilmente lo sapevate già).

Ecco l'esempio tratto dalla referenced page:

// Covariant interface. 
interface ICovariant<out R> { } 

// Extending covariant interface. 
interface IExtCovariant<out R> : ICovariant<R> { } 

// Implementing covariant interface. 
class Sample<R> : ICovariant<R> { } 

class Program 
{ 
    static void Test() 
    { 
     ICovariant<Object> iobj = new Sample<Object>(); 
     ICovariant<String> istr = new Sample<String>(); 

     // You can assign istr to iobj because 
     // the ICovariant interface is covariant. 
     iobj = istr; 
    } 
} 

Come si può vedere, la out nella firma interfaccia permette di assegnare un ICovariant<String> a una variabile ICovariant<Object>, come String deriva da Object. Senza la parola chiave out, non sarebbe possibile farlo, poiché i tipi sarebbero diversi.

È possibile leggere ulteriori informazioni sulla covarianza (e la controvarianza correlata) here.

Come altre risposte hanno sottolineato, IEnumerable stata fatta solo covariante in .NET 4. cercare di scrivere codice come:

IEnumerable<Object> strings = new List<string>(); 

compilerà in .NET 4 e versioni successive, ma non nelle versioni precedenti .

6

Covariance. Ciò consente ad una raccolta di assegnare elementi di un tipo più specifico o derivato rispetto a quanto specificato nel suo parametro generico.

IEnumerable<T> non era sempre covariante; questo era nuovo a .NET 4, e il motivo della modifica è spiegato here.

0

Per raggiungere questo:

class Base {} 
class Derived : Base {} 

List<Derived> list = new List<Derived>(); 
IEnumerable<Base> sequence = list; 
4

Il tipo out parametro specificatore denota covarianza.

In pratica,

Se definisco due interfacce.

ISomeInterface<T> 
{ 
} 

ISomeCovariantInterface<out T> 
{ 
} 

Quindi, li implemento in questo modo.

SomeClass<T> : ISomeInterface<T>, ISomeCovariantInterface<T> 
{ 
} 

Allora provo a compilare questo codice,

ISomeCovariantInterface<object> = new SomeClass<string>(); // works 
ISomeInterface<object> = new SomeClass<string>(); // fails 

La è perché l'interfaccia covariante permette casi più derivati, dove, come, l'interfaccia standard non lo fa.

+0

+1 Penso che questa sia la risposta di livello di introduzione più chiara. – TarkaDaal

Problemi correlati