2016-01-29 26 views
12

Kompletna pytanie przed kodu:Dlaczego IEnumerable (T) nie są akceptowane jako odbiornik metodę rozszerzenia

Dlaczego IEnumerable<T>where T : ITest nie są akceptowane jako odbiornik metodę rozszerzenia że spodziewa this IEnumerable<ITest>?

A teraz kod :

Mam trzy typy:

public interface ITest { } 
public class Element : ITest { } 
public class ElementInfo : ITest { } 

A dwa przedłużacze metod:

public static class Extensions 
{ 
    public static IEnumerable<ElementInfo> Method<T>(
     this IEnumerable<T> collection) 
     where T : ITest 
    { 
→  return collection.ToInfoObjects(); 
    } 

    public static IEnumerable<ElementInfo> ToInfoObjects(
     this IEnumerable<ITest> collection) 
    { 
     return collection.Select(item => new ElementInfo()); 
    } 
} 

Błąd kompilatora mam (na zaznaczonej linii) :

CS1929: 'IEnumerable<T>' nie zawiera definicji 'ToInfoObjects' i najlepsze rozszerzenie metoda przeciążenie 'Extensions.ToInfoObjects(IEnumerable<ITest>)' wymaga odbiornika typu 'IEnumerable<ITest>'

Dlaczego tak jest? Odbiornikiem metody rozszerzania ToInfoObjects jest IEnumerable<T>, a po ograniczeniu rodzaju ogólnego T musi zaimplementować ITest.

Dlaczego odbiornik nie jest akceptowany?? Domyślam się, że jest kowariancja z IEnumerable<T>, ale nie jestem pewien.

Jeśli zmienię ToInfoObjects na IEnumerable<T> where T : ITest, wszystko będzie dobrze.

Odpowiedz

13

Rozważ to:

public struct ValueElement : ITest { } 

a to:

IEnumerable<ValueElement> collection = ... 
collection.Method(); //OK, ValueElement implement ITest, as required. 
collection.ToInfoObjects() //Error, IEnumerable<ValueElement> is not IEnumerable<ITest> 
          //variance does not work with value types. 

Tak, że nie każdy rodzaj pozwoliło Method pozwoliło również na ToInfoObjects. Jeśli dodasz class ograniczenie do T w Method, Twój kod się skompiluje.

+0

Naprawdę dobra odpowiedź. Poszanowanie. – Vasilievski

+0

Teraz, kiedy to powiedziałeś, wydaje mi się oczywiste. T mógł być typem wartości i oczywiście nie działałby. Dziękuję Ci bardzo. Jako kontynuację, chciałbym [link do przyczyny] (http://stackoverflow.com/questions/12454794/why-covariance-and-contravariance-do-not-support-value-type) dlaczego co (ntra) Wariancja nie działa z typami wartości. –

-1

można wykonać następujące czynności:

public static IEnumerable<ElementInfo> Method<T>(
     this IEnumerable<T> collection) 
     where T : ITest 
    { 
     return collection.ToInfoObjects(); 
    } 

    public static IEnumerable<ElementInfo> ToInfoObjects<T>(
     this IEnumerable<T> collection) 
    { 
     return collection.Select(item => new ElementInfo()); 
    } 

Zawiadomienie o ToInfoObjects.

+0

Dzięki za sugestię, ale wiem, co mogę zrobić, aby rozwiązać problem, a nawet więcej, napisałem go w oryginalnym poście. Chciałem tylko dowiedzieć się, dlaczego pojawia się problem, a nie jak go rozwiązać. –

+0

@KornelijePetak Och, przepraszam, że nie poświęcam wystarczająco dużo uwagi na twoje pytanie. –