2012-09-14 10 views
15

Powiel możliwe:
Why was IEnumerable<T> made covariant in C# 4?Dlaczego IEnumerable <T> jest zdefiniowany jako IEnumerable <out T>, nie IEnumerable <T>

Brałem spojrzeć na MSDN dla IEnumerable<T> ubterfejsu i zobacz:

public interface IEnumerable<out T> : IEnumerable 

Zastanawiam się, dlaczego T jest zdefiniowany jako out, dlaczego nie?

public interface IEnumerable<T> : IEnumerable 

Jaki jest tego powód?

+0

bo interfejs jest kowariantna – Jodrell

+1

wygląd tutaj http://stackoverflow.com/questions/6732299/why-was-ienumerablet-made-covariant-in-c-sharp-4 – Likurg

+0

[kowariancji i kontrawariancja] (http://msdn.microsoft.com/en-us/library/ee207183) – jrummell

Odpowiedz

20

Więcej informacji można znaleźć here.

Parametr out tworzy kowariancję parametru. Oznacza to, że możesz użyć typu lub dowolnego typu pochodnego. Zauważ, że out działa tylko w ten sposób w przypadku generycznych, ma inne znaczenie, gdy jest używany w sygnaturach metod (chociaż prawdopodobnie już to wiedziałeś).

Oto przykład wzięty z 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; 
    } 
} 

Jak widać, out w podpisie interfejs pozwala można przypisać ICovariant<String> do zmiennej ICovariant<Object>, jak String wywodzi Object. Bez słowa kluczowego out nie byłbyś w stanie tego zrobić, ponieważ typy byłyby różne.

Możesz przeczytać więcej o kowariancji (i powiązanej sprzeczności) here.

W innych odpowiedzi podkreśliło, IEnumerable został wykonany tylko w .NET kowariantna 4. Próba pisania kodu, takich jak:

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

zostanie skompilowany w .NET 4 i nowsze wersje, ale nie w poprzednich wersjach .

6

Covariance. Umożliwia to przypisanie kolekcji elementów bardziej szczegółowych lub wyprowadzonych, niż określono w parametrze generycznym.

IEnumerable<T> nie zawsze była kowariancyjna; było to nowością w .NET 4, a przyczyna zmiany została wyjaśniona here.

0

Aby osiągnąć ten cel:

class Base {} 
class Derived : Base {} 

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

typu out parametr specyfikator oznacza kowariancji.

W praktyce

Jeśli zdefiniuję dwa interfejsy.

ISomeInterface<T> 
{ 
} 

ISomeCovariantInterface<out T> 
{ 
} 

Następnie wdrażam je w ten sposób.

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

Potem próbuję skompilować ten kod,

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

IS ponieważ kowariantna interfejs pozwala instancji więcej pochodnych, gdzie jak standardowy interfejs nie.

+0

+1 Myślę, że jest to najczystsza odpowiedź na poziomie wprowadzającym. – TarkaDaal

Powiązane problemy