2010-04-28 12 views
8

Wenn wir unsere Schnittstellen in C# 4.0 definieren, dürfen wir jeden generischen Parameter als in oder out kennzeichnen. Wenn wir versuchen, einen generischen Parameter als out zu setzen, und das zu einem Problem führen würde, löst der Compiler einen Fehler aus, der uns das nicht erlaubt.Kovarianz und Kontravarianz-Inferenz in C# 4.0

Frage:

Wenn der Compiler hat Weisen Folgern, was gültige Verwendungen für beide covariance sind (out) und contravariance (in), warum wir Schnittstellen als solche zu kennzeichnen müssen? Wäre es nicht genug, die Schnittstellen wie immer zu definieren, und wenn wir versuchen, sie in unserem Client-Code zu verwenden, einen Fehler melden, wenn wir versuchen, sie auf unsichere Weise zu verwenden?

Beispiel:

interface MyInterface<out T> { 
    T abracadabra(); 
} 
//works OK 

interface MyInterface2<in T> { 
    T abracadabra(); 
} 
//compiler raises an error. 
//This makes me think that the compiler is cappable 
//of understanding what situations might generate 
//run-time problems and then prohibits them. 

Auch

ist es nicht, was Java funktioniert in der gleichen Situation? Von was ich mich erinnere, tun Sie nur etwas wie

IMyInterface<? extends whatever> myInterface; //covariance 
IMyInterface<? super whatever> myInterface2; //contravariance 

Oder mische ich Dinge?

Dank

Antwort

8

Wenn der Compiler Weisen Folgern hat, was gelten Verwendungen für beide Kovarianz (out) und Kontra (in), warum haben wir Schnittstellen als solche zu kennzeichnen?

Ich bin mir nicht ganz sicher, ob ich die Frage verstehe. Ich denke, du fragst zwei Dinge.

1) Kann der Compiler die Varianzanmerkungen ableiten?

und

2) Warum C# Call-Website Varianz nicht unterstützen wie Java tut?

Die Antwort auf die erste ist:

interface IRezrov<V, W> 
{ 
    IRezrov<V, W> Rezrov(IRezrov<W, V> x); 
} 

Ich lade Sie ableiten, um zu versuchen, was alle rechtlichen möglich Varianz Anmerkungen sind auf V und W. Sie könnten eine Überraschung.

Wenn Sie eine eindeutige Best Variance Annotation für diese Methode nicht herausfinden können, warum glauben Sie, dass der Compiler?

Weitere Gründe hier:

http://blogs.msdn.com/ericlippert/archive/2007/10/29/covariance-and-contravariance-in-c-part-seven-why-do-we-need-a-syntax-at-all.aspx

Allgemeiner: Ihre Frage zeigt fallacious Argumentation. Die Fähigkeit, billig zu prüfen, ob eine Lösung korrekt ist, bedeutet logischerweise nicht, dass es eine billige Möglichkeit gibt, eine korrekte Lösung zu finden. Zum Beispiel kann ein Computer leicht überprüfen, ob p * q == r für zweitausendstellige Primzahlen p und q wahr oder falsch ist. Das bedeutet nicht, dass es einfach ist, r zu nehmen und p und q zu finden, so dass die Gleichheit erfüllt ist.Der Compiler kann leicht überprüfen, ob eine Varianzannotation korrekt oder falsch ist. das bedeutet nicht, dass es eine korrekte Varianzannotation unter den möglichen Milliarden möglicher Anmerkungen finden kann.

Die Antwort auf die Sekunde ist: C# ist nicht Java.

+0

Ich denke, seine zweite Frage war eher wie "Wie unterscheidet sich C# Varianz Annotationen von Javas Wildcard-Typen?" – Gabe

+1

@Gabe: C# tut * Deklaration-Site * Varianz. Java macht * Call-Site * Varianz. Call-Site-Varianz ist eine interessante Idee, um sicher zu sein, aber es fühlt sich komisch an, eine Typ-Variante zu haben, basierend darauf, wie sie an einer bestimmten Site verwendet wird, im Gegensatz zu dem, wie sie definiert ist. –

+0

Ja, ich bekomme jetzt das Problem mit der Java-Nutzung. Es hat den Vorteil, dass man die Parameter der Schnittstelle nicht als "in" oder "out" angeben muss, aber dann könnte ein Client ihm etwas Nutzen geben, das später möglicherweise nicht überliefert wird, wenn ich meine Schnittstelle aktualisieren möchte. –

0

OK, hier ist die Antwort auf das, was fragte ich (von Eric Antwort): http://blogs.msdn.com/ericlippert/archive/2007/10/29/covariance-and-contravariance-in-c-part-seven-why-do-we-need-a-syntax-at-all.aspx

Zuerst scheint es mir, dass die Varianz sollte etwas sein, das Sie bewusst in Ihre Interface Design oder delegieren. Es macht nur Start geschieht ohne Kontrolle durch die Benutzer arbeitet gegen dieses Ziel, und auch kann brechen Änderungen einführen. (Mehr auf diejenigen, die in einem späteren Beitrag!)

Doing so automagically bedeutet auch, dass wie der Entwicklungsprozess geht weiter und Methoden Schnittstellen hinzugefügt werden, die Varianz der Schnittstelle unerwartet ändern können. Dies könnte unerwartete und weitreichende Änderungen an anderer Stelle im Programm einführen.

Ich habe mich entschieden, es hier explizit zu machen, weil, obwohl sein Link die Antwort auf meine Frage hat, der Beitrag selbst nicht.