Als Antwort auf eine weitere Frage Ich habe versucht, folgendes zu tun. Ich glaube nicht, dass ich diese Frage richtig interpretiert habe, aber ich frage mich, ob das Folgende irgendwie möglich ist (meine Versuche sind gescheitert) und wenn nicht warum nicht:
%Vor%Ich dachte, dies könnte mit einer generischen Schnittstelle mit einem kovarianten Typparameter funktionieren:
%Vor%Aber ich habe mich geirrt, das funktioniert auch nicht.
BEARBEITEN
Wie SLaks darauf hingewiesen hat: "Interfaces sind kovariant; Klassen sind nicht. (Danke SLaks). Also meine Frage ist warum? Was war das Denken hinter dem Design (eines für Eric Lippert denke ich) ist es nicht möglich, unerwünscht oder ist es auf einer "vielleicht ein Tag" -Liste?
Was war der Grund für die Designentscheidung, die Varianz generischer Klassen nicht zu implementieren? Ist es nicht möglich, unerwünscht oder ist es auf einer "vielleicht einen Tag" -Liste?
Sie sind in guter Gesellschaft; Jon Skeet und Bill Wagner haben mir vor ein paar Wochen dieselbe Frage gestellt. Ich habe einen Blogpost darüber geschrieben, aber kurz:
Die richtige Person, die nach einer endgültigen Antwort fragt, ist Andrew Kennedy bei Microsoft Research Cambridge, der ursprünglich einen großen Teil der generischen und der Varianzlogik entworfen und implementiert hat. Allerdings kann ich eine begründete Vermutung darüber ertragen, warum wir uns entschieden haben, die Abweichung von generischen Klassen zu vermeiden.
Die Kurzversion lautet: Die sichere Kovarianz von T erfordert, dass Operationen an T "nur lesen" sind. Die Kontravarianz von T erfordert, dass Operationen an T "nur schreiben" sind. Sie haben eine Klasse C<T>
, die Sie in T variant haben möchten. Angenommen, C hat ein Feld vom Typ T: Möchten Sie, dass das Feld nur lesbar oder nur beschreibbar
Unter welchen Umständen ist es sogar vage nützlich, ein Feld zu haben, das geschrieben, aber nicht gelesen werden kann? Nicht viele. Unter welchen Umständen ist es sinnvoll, ein Feld zu haben, das zwar gelesen, aber nicht beschrieben werden kann? Nur wenn das Feld schreibgeschützt markiert ist .
Kurz gesagt, sind kontravariante generische Klassen fast nie nützlich, weil Sie keine generischen Daten von ihnen lesen können, und kovariante Klassen sind meistens nur nützlich, wenn die Klasse ein unveränderlicher Datentyp ist .
Ich bin ein großer Fan von unveränderlichen Datentypen und ich denke, es wäre ein großartiges Feature, einen kovarianten unveränderlichen Stack erstellen zu können, ohne dass eine Schnittstelle benötigt wird. Aber kovariante generische persistente unveränderliche funktionale Datenstrukturen sind in C # noch nicht genau Mainstream, und sie waren sicherlich nicht, als Generika der CLR hinzugefügt wurden. Darüber hinaus haben wir keine andere unterstützende Infrastruktur als schreibgeschützte Felder, um den Begriff "Dies ist ein unveränderlicher Datentyp" in C # oder der CLR auszudrücken. Wenn wir kovariante Klassentypen für unveränderliche Klassen machen würden, wäre es schön, viele Funktionen zu machen, die unveränderliche Klassen unterstützen, nicht nur diese obskuren.
So kann ich sehen, wie diese Funktion den Schnitt in CLR 2.0 / C # 2.0 nicht gemacht hat. Wenn wir es heute wieder entwerfen würden, wenn funktionelles Programmieren etwas populärer ist, dann vielleicht. Aber wir haben nicht vor, es in absehbarer Zeit zu tun.
Ich werde in den nächsten Monaten einen Blogeintrag schreiben, der eine ausführlichere Antwort geben wird.
Die direkte Konvertierung von Klasse zu Klasse funktioniert nicht, aber wenn Sie Ihre IB-Schnittstelle für den Variablentyp verwenden, sollten Sie gehen. Laut diesem MSDN-Kovarianz-FAQ-Blogbeitrag und die MSDN-Seite zu Covariance und Contravariance , Variantentyp-Parameter sind auf die generische Schnittstelle und den generischen Delegaten beschränkt Typen.
%Vor%Tags und Links .net c# generics covariance