2017-09-28 2 views
8

Ich lerne C# Generika und mache Dummy-Code zu Testzwecken. Also teste ich die in Generic Modifier, die angibt, dass der Typparameter kontravariant ist.Verwenden von generischen Kontravarianten mit IList und IEnumerable

Angesichts der unter Schnittstelle:

[CS1961] Ungültige Varianz:

public interface IInterfaceTest<in T> 
{ 
    void Method(T value); 
    void Method(IList<T> values); 
    void Method(IEnumerable<T> values); 
} 

Beim Kompilieren, ich die Fehlermeldung bekommen Der Typ-Parameter 'T' invariant sein müssen gültige auf 'IInterfaceTest.Method (IList)'. "T" ist kontravariant.

Der Fehler bezieht sich nur auf die Zeile void Method(IEnumerable<T> values). Wenn diese Zeile entfernt wird, funktioniert alles einwandfrei.

Also meine Frage ist: Warum kann ich die generische kontra mit IEnumerable verwenden, aber nicht mit IList? Habe ich etwas vergessen?

Danke.

+5

'IList ' ist nicht und kann nicht kovariant sein. – SLaks

+2

@SLaks: Ich denke OP bekommt das, aber warum? (Das wird mir auch helfen) – Stefan

+6

Weil es veränderbar ist. https://stackoverflow.com/a/2033921/34397 – SLaks

Antwort

4

Die Frage, warum es nicht erlaubt ist, für IList<T> wurde bereits in den Kommentaren und verknüpften Fragen beantwortet: IList<T> ist invariant in T und so ein kontravarianten Tnicht hier auch immer verwendet werden.

Was mich zuerst verwirrt hat, ist die Tatsache, dass Method(IEnumerable<T>) hier erlaubt ist. Die seltsame Sache ist, dass Varianz ist "drehte sich um", wenn Sie die T als Typ Argument für eine andere generische Art verwenden.

Stellen Sie sich das vor.

public interface ITestInterface<in T> 
{ 
    void Method(IEnumerable<T> e); 
    IEnumerable<T> GetMethod(); // illegal 
} 
public class Animal {} 
public class Lion : Animal [} 
public class Gnu : Animal {} 

ITestInterface<Animal> animals; 
ITestInterface<Lion> lions; 
ITestInterface<Gnu> gnus; 

Nun ist die Kontravarianz ITestInterface<in T> in T sagt uns, dass Sie

lions = animals; 

tun können, und wenn Sie lions.Method(e) aufrufen, können Sie nur eine IEnumerable<Lion> bieten. So kann der Code Method nur Lion s aufzählen, die alle Animals als animals.Method() erwartet. Alles ist gut.

Auf der anderen Seite ist die IEnumerable<T> GetMethod() illegal, weil:

gnus = animals; 

legal ist, und jetzt gnu.GetMethod() würde eine IEnumerable<Animal> zurück, wo Sie eine IEnumerable<Gnu> erwarten würde. Und wenn Sie iterierten, konnten überraschende Tiere in dieser Reihenfolge warten.

+2

Die Varianz in Bezug auf "T" wird für _Eingaben_, die eine Beziehung mit "T" haben, "umgedreht". Ausgaben müssen die gleiche Varianz in Bezug auf "T" haben. Zum Beispiel wäre "Aktion GetMethod()" gültig, weil "Aktion <-T>" mit "T" auf dieselbe Weise variiert wie "ITestInterface <-T>". Ansonsten gute Antwort. –

Verwandte Themen