Warum kann ich nicht zuordnen eine Liste<Abgeleitet> Liste<Base>?
Definierte ich die folgende Klasse:
public abstract class AbstractPackageCall
{
...
}
Ich auch durch die Definition einer Unterklasse dieser Klasse:
class PackageCall : AbstractPackageCall
{
...
}
Es gibt auch mehrere andere subclases von AbstractPackageCall
Nun möchte ich den folgenden Aufruf:
List<AbstractPackageCall> calls = package.getCalls();
Aber ich bekomme immer diese exception:
Error 13 Cannot implicitly convert type 'System.Collections.Generic.List<Prototype_Concept_2.model.PackageCall>' to 'System.Collections.Generic.List<Prototype_Concept_2.model.AbstractPackageCall>'
Was ist hier das problem? Dies ist die Methode Package#getCalls
internal List<PackageCall> getCalls()
{
return calls;
}
Es heißt Kovarianz/Kontravarianz mit Generika. Check out dies, SO Frage.
Wenn Sie zurückkehren können, eine
Sie können auch daran interessiert sein, Lesen Sie diese zwei Seiten. Lesen Sie diese aus co-/contra - Varianz auf, die für mich C# 4.0 die FUNKTION im FOKUS – TEIL 4 – CO - UND CONTRA-VARIANZ FÜR GENERISCHE DELEGAT-UND INTERFACE-TYPEN und natürlich Eric Lippert hat eine Menge Beiträge zu dem Thema.
Danke für die vielen Antworten, endlich habe ich glaube ich verstehe das Konzept der Kovarianz.
Wenn Sie zurückkehren können, eine
IEnumerable<AbstractPackageCall>
statt List<AbstractPackageCall>
dann funktioniert das wie IEnumerable<>
unterstützt Kovarianz.Sie können auch daran interessiert sein, Lesen Sie diese zwei Seiten. Lesen Sie diese aus co-/contra - Varianz auf, die für mich C# 4.0 die FUNKTION im FOKUS – TEIL 4 – CO - UND CONTRA-VARIANZ FÜR GENERISCHE DELEGAT-UND INTERFACE-TYPEN und natürlich Eric Lippert hat eine Menge Beiträge zu dem Thema.
Danke für die vielen Antworten, endlich habe ich glaube ich verstehe das Konzept der Kovarianz.
InformationsquelleAutor | 2011-01-10
Du musst angemeldet sein, um einen Kommentar abzugeben.
Der einfachste Weg, um zu verstehen, warum dies nicht erlaubt ist, ist das folgende Beispiel:
Die Letzte Aussage würde ruinieren die Typ-Sicherheit .NET.
Arrays jedoch erlauben diese:
Jedoch, indem Sie ein
Banana
infruits
würde noch Pause geben Sicherheit, so dafür .NET zu tun hat, eine Art check auf jedem array einfügen und werfen eine Ausnahme, wenn es nicht tatsächlich einApple
. Dies ist möglicherweise eine (kleine) performance-hit werden, aber dies kann umgangen werden, indem erstellen einstruct
wrapper geben, wie diese überprüfung geschieht nicht für Wert-Typen (weil Sie keine Erben von etwas). Auf den ersten, ich habe nicht verstanden, warum diese Entscheidung getroffen wurde, aber Sie stoßen sehr oft, warum diese nützlich sein kann. Am häufigsten istString.Format
nimmt, dieparams object[]
und Arrays, die übergeben werden können, in diesem.In .NET 4 gibt es aber typsichere Kovarianz und Kontravarianz, die Ihnen erlaubt, um einige Aufgaben wie diese, aber nur, wenn Sie nachweislich sicher sind. Was ist nachweislich sicher?
Den oben genannten Werken .NET 4, da
IEnumerable<T>
wurdeIEnumerable<out T>
. Dieout
bedeutet, dassT
kann immer nur kommen aus vonfruits
ist und dass es keine Methode in allen aufIEnumerable<out T>
dass immerT
als parameter, so können Sie nie falsch pass eineBanana
inIEnumerable<Fruit>
.Kontravarianz ist viel das gleiche, aber ich vergesse immer die genauen details auf. Es überrascht nicht, dafür gibt es jetzt die
in
Schlüsselwort für Typ-Parameter.Das ist eine Super Antwort, mit der rechten gibt. Fair play, um Ihnen für die Zeit nehmen
InformationsquelleAutor JulianR
Nun, wenn Sie wollen, um den folgenden Aufruf:
Nenne ich Verallgemeinerung.
Können Sie auch diese spezifischer:
Implementieren diese mit extension-Methode:
InformationsquelleAutor Artur Mustafin
, Warum das, was Sie versucht hat nicht funktioniert
Du fragst den compiler zur Behandlung einer
List<PackageCall>
alsList<AbstractPackageCall>
, was er nicht ist. Es ist eine andere Sache, dass jedesPackageCall
Instanzen ist in der Tat einAbstractPackageCall
.Was arbeiten würden anstatt
, Warum das, was Sie versuchen, wird nie erlaubt werden, zu arbeiten
Obwohl jedes Element innerhalb der Rückgabewert von
package.getCalls()
stammt ausAbstractPackageCall
wir nicht behandeln können die ganze Liste alsList<AbstractPackageCall>
. Hier ist, was passieren würde, wenn wir könnten:Wenn wir das tun könnten, dann könnten wir hinzufügen, eine
SomeOtherConcretePackageCall
zu einemList<PackageCall>
.InformationsquelleAutor Jon
Weil
List<PackageCall>
erbt nicht vonList<AbstractPackageCall>
. Sie können dieCast<>()
Erweiterung Methode, wie:Dies ist die Fehlermeldung die ich bekomme, wenn ich versuche diese
Ja, nur Feste auf meine Antwort.
InformationsquelleAutor Brian Ball
Können Sie diese Konvertierung durchführen, da ein
List<AbstractPackageCall>
kann alles enthalten, ergibt sich ausAbstractPackageCall
, während einList<PackageCall>
nicht-es können nur Dinge enthalten, die sich ausPackageCall
.Berücksichtigen, wenn dieser Besetzung durften:
Den Sie gerade Hinzugefügt eine
AnotherPackageCall
in eineList<PackageCall>
- aberAnotherPackageCall
nicht ableiten ausPackageCall
! Das ist, warum diese Konvertierung ist nicht erlaubt.InformationsquelleAutor cdhowie