Ich habe viel über Kovarianzprobleme in C # gehört / gelesen und wollte ein paar Fragen stellen & amp; Szenarien so hoffentlich kann ich meine Verwirrung in der Sache klären.
In den folgenden Beispielen wird vorausgesetzt, dass immer Folgendes definiert ist:
%Vor%Mein erstes Beispiel:
%Vor%Das sollte funktionieren, richtig? Ich habe es ein paar Mal in C # getestet und es hat gut zusammengestellt & amp; lief gut (meine Tests für mein erstes Beispiel waren etwas mehr als das, da ich polymorphe Aufrufe hatte, die Zeug an die Konsole druckten).
Zweites Beispiel:
%Vor%In diesem zweiten Beispiel verstehe ich, dass dies nicht kompiliert werden sollte und die Wurzel der Kovarianzprobleme in .NET 4.0 ist. Bitte korrigieren Sie mich, wenn ich falsch liege. Ich bin mir auch bewusst, dass .NET 4.0 Kovarianz / Kontravarianz zwischen konkreten Typen, nur Interfaces, nicht zulässt.
Schließlich möchte ich einige Definitionen erhalten. Ich bin nicht ganz klar, was hinter diesen drei Begriffen steckt:
Was das letzte Wort betrifft, habe ich es oft in C ++ verwendet, um auf Änderungen zu verweisen, für die Regeln gelten. Zum Beispiel, wenn ich eine ganze Zahl habe und sie nur einen Wert zwischen 1 und 10 haben darf, ist die "Invarianz", dass sie nur zwischen 1 und 10 sein kann. Ich könnte das falsch verstehen und ich bin mir auch nicht sicher, ob Diese Definition passt gut zu C # für diese spezielle Diskussion.
Mein Ziel ist es, genau zu verstehen, was die Covarianz- oder Casting-Probleme mit generischen Schnittstellen in C # sind. Die Beispiele, die ich gepostet habe, sind mein Verständnis dafür, wo das Problem liegt. Wenn alle Beispiele kompilieren / funktionieren, stellen Sie bitte ein Beispiel vor, das die häufigsten Covarianz / Contravarianz / Casting-Probleme in C # reproduziert. Ich muss das wissen, damit ich das Problem identifizieren und anderen erklären kann.
Die Schnittstelle IList<T>
ist nicht als kovariant definiert, da sie eine Add
-Methode unterstützt, die das Objekt mutiert.
Betrachten Sie Folgendes:
%Vor% Sie könnten jetzt eine Banana
von apples
bekommen, was sicherlich nicht beabsichtigt ist. Daher unterstützt die IList
-Schnittstelle keine Kovarianz (und wird es auch nie) und sollte einen Kompilierungsfehler verursachen.
Sie sollten das gleiche Problem mit
haben %Vor%Ich bin mir nicht sicher, warum es für Sie zusammengestellt wurde.
Das Interface IEnumerable<out T>
kann kovariant sein (und es ist in .NET 4.0 und höher), weil IEnumerable
nur das Lesen von Elementen aus einer Sammlung unterstützt.
Die Scala-Sprache hat ein ähnliches Konzept von kovarianten und kontravarianten Objekten und das Kapitel von Programmierung in Scala das diskutiert Generika sollte auch als eine gute Einführung in die Covarianz in C # dienen.
Sehen Sie sich diesen Artikel für eine Erklärung von Kovarianz und Kontravarianz an.
Die CLR hatte bereits einige Unterstützung für Varianz in generischen Typen und mit c # 4 kommt die Syntax, um dies zu verwenden. Bei generischer Varianz wird die Varianz auf die Typparameter der Interfaces und Delegattypen angewendet.
Kovarianz bedeutet, einen zurückgegebenen Wert als allgemeineren Typ behandeln zu können, und ist möglich, wenn die Interface-Methode (n) nur diesen Typ zurückgibt. In diesem Beispiel kann die abgeleitete Schnittstelleninstanz als Basis neu zugewiesen werden, aber nicht umgekehrt.
%Vor%Bei der Kontravarianz geht es darum, einen Parametertyp als einen spezifischeren Typ zu behandeln. Dies ist möglich, wenn die Schnittstellenmethode (n) nur diesen Typ verwenden. In diesem Beispiel kann die Basisschnittstelleninstanz als abgeleitete Klasse neu zugewiesen werden, aber nicht umgekehrt.
%Vor%Invarianz tritt auf, wenn beide Fälle auftreten und die Schnittstellenmethode (n) den Typ zurückgeben und verbrauchen. Es kann keine Kovarianz oder Kontravarianz angewendet werden. Hier wird jegliche Verwendung wie oben nicht funktionieren, da der Parameter 'out T' Kovarianz oder 'in T' Kontravarianztyp nicht definiert werden darf, da die Methoden beide Fälle enthalten.
Bedenken Sie Folgendes:
%Vor%Keines Ihrer Beispiele wird so funktionieren wie sie sind. Kontravarianz / Kovarianz gilt für Interfaces und Delegaten, deren generischer Typ als 'in' / 'out' deklariert wurde, IList ist invariant.
Da die Schnittstelle IEnumerable<T>
kovariant von .NET 4 ist, können Sie dies ab 4, aber nicht 3.5 tun. Die Verwendung von Früchten als IList hier funktioniert nicht, wenn man Früchte deklariert - es ist nicht kovariant.
Hier ist die Definition von IEnumerable<T>
Tags und Links c# covariance contravariance invariants