Ich habe mit Generika herumgespielt und ich habe seltsame Sachen gesehen. Ich hoffe ihr habt eine Erklärung! Um alles einfacher zu machen, habe ich das "Problem" in ein Beispiel eingefügt:
%Vor%Also, ich habe zwei Tiere in meinem Labor: einen Hund und einen Vogel. Wenn ich diese Tiere "kicke", werden sie ein Geräusch machen. Der Drucker druckt den Ton und die Art des Tieres. Wenn ich das Programm starte, druckt es:
Kickvogel: Lab.Animal sagt 'Tweet!'
Tritthund: Lab.Animal sagt 'Rinde, bellen! Ich beiße dich! "
Druckstoßhund: Lab.Dog sagt 'Rinde, bellen! Ich beiße dich! "
Warum sagt mir der erste Tritt des Hundes, dass er vom Typ Lab.Animal
ist?
Und ... wie kann ich Lab.Dog
zurückgeben?
Der erste Tritt des Hundes sagt Ihnen, dass der Kompilierzeittyp vom Typ argument Lab.Animal war. Mit anderen Worten, Ihre Methode Animal.Kick
ist effektiv:
Typargumente werden nicht polymorph bestimmt - sie werden zur Kompilierungszeit bestimmt. Es wird komplizierter, wenn das Typargument eines Aufrufs tatsächlich der Typ -Parameter des aufrufenden Kontexts ist, aber es ist im Grunde die gleiche Art von Sache.
Um Lab.Dog
sagen zu können, müssten Sie den tatsächlichen Ausführungszeittyp des Objekts ermitteln, z. mit
Normalerweise werden Generika zur Kompilierungszeit bestimmt, aber sie sind auch eine Laufzeitfunktion. In diesem Fall verwenden Sie eine generische Typ-Inferenz, die die Variablen usw. verwendet, um den Typ abzuleiten.
In der Methode:
%Vor% alles, was in diesem Zusammenhang von this
bekannt ist, ist, dass es Animal
sein muss, so dass es ein implizites Anmial gibt, d. h. Printer.Print<Animal>(this, Sound)
Andere Optionen:
GetType()
, um den tatsächlichen Typ des Objekts zu finden dynamic
, um die Auflösung auf die Laufzeit zu verschieben (beachten Sie: keine ideale Verwendung von dynamic, aber es funktioniert)