Ich habe nicht an der PDC 2008 teilgenommen, aber ich habe einige Neuigkeiten gehört, dass C # 4.0 angekündigt wurde, um generische Kovarianz und Kontravarianz zu unterstützen. Das heißt, List<string>
kann zugewiesen werden List<object>
. Wie kann das sein?
In Jon Skeets Buch C # in Depth wird erklärt, warum C # -Generika Kovarianz und Kontravarianz nicht unterstützen. Es dient hauptsächlich zum Schreiben von sicherem Code. Jetzt wurde C # 4.0 geändert, um sie zu unterstützen. Würde es Chaos bringen?
Weiß jemand, dass die Details zu C # 4.0 eine Erklärung geben können?
c#
c#-4.0
covariance
contravariance
generic-variance
Morgan Cheng
quelle
quelle
Antworten:
Varianz wird nur auf sichere Weise unterstützt - tatsächlich unter Verwendung der Fähigkeiten, über die die CLR bereits verfügt. Die Beispiele, die ich in dem Buch gebe, in dem versucht wird, a
List<Banana>
alsList<Fruit>
(oder was auch immer es war) zu verwenden, funktionieren also immer noch nicht - aber einige andere Szenarien werden es tun.Erstens wird es nur für Schnittstellen und Delegaten unterstützt.
Zweitens muss der Autor der Schnittstelle / des Delegaten die Typparameter als
in
(für Kontravarianz) oderout
(für Kovarianz) dekorieren . Das offensichtlichste Beispiel ist,IEnumerable<T>
dass Sie nur Werte "herausnehmen" können - Sie können keine neuen hinzufügen. Das wird werdenIEnumerable<out T>
. Das schadet der Typensicherheit überhaupt nicht, aber Sie können beispielsweiseIEnumerable<string>
eine Methode zurückgeben, die als zurückgegeben deklariert wurdeIEnumerable<object>
.Kontravarianz ist schwieriger, konkrete Beispiele für die Verwendung von Schnittstellen zu nennen, aber mit einem Delegierten ist es einfach. Bedenken Sie,
Action<T>
dass dies nur eine Methode darstellt, die einenT
Parameter akzeptiert. Es wäre schön, wenn Sie aAction<object>
as nahtlos konvertierenAction<string>
könnten - jede Methode, die einenobject
Parameter verwendet, ist in Ordnung, wenn sie mit a dargestellt wirdstring
, statt. Natürlich weist C # 2 bereits eine gewisse Kovarianz und Kontravarianz von Delegaten auf, jedoch über eine tatsächliche Konvertierung von einem Delegatentyp in einen anderen (Erstellen einer neuen Instanz) - Beispiele finden Sie auf P141-144. C # 4 wird dies allgemeiner machen und (glaube ich) vermeiden, eine neue Instanz für die Konvertierung zu erstellen. (Es wird stattdessen eine Referenzkonvertierung sein.)Hoffe das klärt es ein bisschen auf - bitte lass es mich wissen, wenn es keinen Sinn ergibt!
quelle
List<Banana>
als verwenden könnenIList<Fruit>
", wie @ Ark-kun sagte? Wenn ja, wie ist dies möglich, obwohl der Typparameter derIList<T>
Schnittstelle nicht als kovariant definiert ist (neinout T
, sondern einfachT
).Nicht, dass Jon es noch nicht behandelt hätte, aber hier sind einige Links zu Blogs und Videos von Eric Lippert. Er macht es gut, es mit Beispielen zu erklären.
https://blogs.msdn.microsoft.com/ericlippert/2007/10/16/covariance-and-contravariance-in-c-part-one/
Die Videos:
https://www.youtube.com/watch?v=3MQDrKbzvqU
https://www.youtube.com/watch?v=XRIadQaBYlI
https://www.youtube.com/watch?v=St9d2EDZfrg
quelle