2016-01-29 9 views
12

komplette Frage vor Code:Warum ist IEnumerable (T) nicht als Erweiterungsmethode Empfänger akzeptiert

Warum ist IEnumerable<T>where T : ITest nicht als Empfänger einer Erweiterungsmethode akzeptiert, die this IEnumerable<ITest> erwartet?

Und nun der Code:

Ich habe drei Arten:

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

Und zwei Erweiterungsmethoden:

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()); 
    } 
} 

Der Compilerfehler I (auf der markierten Linie) erhalten :

CS1929: 'IEnumerable<T>' keine Definition für 'ToInfoObjects' enthalten und die beste Erweiterung -Methodenüberladung 'Extensions.ToInfoObjects(IEnumerable<ITest>)' erfordert einen Empfänger vom Typ 'IEnumerable<ITest>'

Warum ist das so? Der Empfänger der Erweiterungsmethode ToInfoObjects ist eine IEnumerable<T> und durch die generische Typ-Einschränkung muss TITest implementieren.

Warum wird dann der Empfänger nicht akzeptiert? Meine Vermutung ist die Kovarianz der IEnumerable<T>, aber ich bin mir nicht sicher.

Wenn ich ToInfoObjects ändern, um IEnumerable<T> where T : ITest zu erhalten, dann ist alles in Ordnung. auf ToInfoObjects

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()); 
    } 

Hinweis:

Antwort

13

Bedenken Sie:

public struct ValueElement : ITest { } 

und diese:

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. 

Damit nicht jede für Method auch für ToInfoObjects gestattet. Wenn Sie die Bedingung class zu T in Method hinzufügen, wird Ihr Code kompiliert.

+0

Wirklich gute Antwort. Respekt. – Vasilievski

+0

Nun, da du es gesagt hast, scheint es für mich offensichtlich zu sein. T könnte der Werttyp gewesen sein und natürlich würde es nicht funktionieren. Vielen Dank. Als Follow-up möchte ich [Link zum Grund] (http://stackoverflow.com/questions/12454794/why-covariance-and-contravariance-do-not-support-value-type) warum co (ntra) Varianz funktioniert nicht mit Werttypen. –

-1

Sie können folgendes tun.

+0

Vielen Dank für Ihren Vorschlag, aber ich weiß, was ich tun kann, um das Problem zu lösen, und noch mehr, ich habe es im ursprünglichen Beitrag geschrieben. Was ich wollte, ist zu wissen, warum das Problem passiert, nicht, wie es gelöst werden soll. –

+0

@KornelijePetak Oh, tut mir leid, dass ich deiner Frage nicht genug Aufmerksamkeit geschenkt habe. –