2017-09-27 18 views
6

Powiedzmy mamy interfejs jakGeneric ograniczenie ignoruje CO-wariancji

public interface IEnumerable<out T> 
{ /*...*/ } 

że jest wspólnie wariant w T.

Potem mamy kolejny interfejs i klasa wdrożenia go:

public interface ISomeInterface {} 
public class SomeClass : ISomeInterface 
{} 

Teraz wspólnie wariancji pozwala nam wykonać następujące

IEnumerable<ISomeInterface> e = Enumerable.Empty<SomeClass>(); 

Więc IEnumerable<SomeClass>jest przypisywane do zmiennej (lub parametr metody) typu IEnumerable<ISomeInterface>.

Ale jeśli spróbujemy to w metoda rodzajowa:

public void GenericMethod<T>(IEnumerable<T> p) where T : ISomeInterface 
{ 
    IEnumerable<ISomeInterface> e = p; 
    // or 
    TestMethod(p); 
} 
public void TestMethod(IEnumerable<ISomeInterface> x) {} 

otrzymujemy Błąd kompilatora CS0266 mówi nam, że IEnumerable<T> nie mogą być konwertowane do IEnumerable<ISomeInterface>.

Ograniczenie wyraźnie stwierdza T pochodzi z ISomeInterface i od IEnumerable<T> jednoczesnego wariant, w T to zadanie powinien działać (jak przedstawiono powyżej).

Czy istnieje jakiś techniczny powód, dlaczego to nie może działać w sposób ogólny? A może cokolwiek, co przegapiłem, jest zbyt kosztowne, aby kompilator mógł to zrozumieć?

Odpowiedz

5

Zmień swoją GenericMethod i dodać rodzajowe ograniczenie class:

public void GenericMethod<T>(IEnumerable<T> p) where T : class, ISomeInterface 
{ 
    IEnumerable<ISomeInterface> e = p; 
    // or 
    TestMethod(p); 
} 

Covariance does not support structs, więc musimy powiedzieć, że chcemy tylko używać klas.

+1

Och, pobili mnie do tego. Teraz pamiętam, że przeczytałem coś o tym problemie strukturalnym/wariancyjnym kilka dni temu. Dziekuje za szybką odpowiedź. –

+0

@ RenéVogt chętnie pomoże – Backs