Dies ist nicht möglich, da sich die öffentliche Schnittstelle von MyGenericClass ändern würde, je nachdem, welcher Typ T ist.
Wenn Sie viele verschiedene Klassen haben, die alle die gleiche Schnittstelle bereitstellen, können Sie MyGenericClass deklarieren, um diese Schnittstelle verfügbar zu machen, und in der Implementierung aller Funktionen die Aufrufe an obj delegieren
Sie könnten etwas wie
tun %Vor%Bearbeiten: Jetzt verstehe ich die Frage
Die spezifische Frage, warum können Sie das nicht tun:
%Vor%Und Sie können dies tun:
%Vor%Der Grund ist, dass die CLR in der Lage ist, eine einzige Version des Codes für MyGenericClass zu kompilieren, die für jeden für T angegebenen Referenztyp funktioniert.
Es kann dies für den zweiten Fall tun, weil es ruhig T
durch object
ersetzen und passende Umwandlungen einfügen kann, ungefähr äquivalent zu:
Aber für die Vererbungsversion funktioniert dieser Trick nicht.
Auch viele nützliche Einrichtungen wären unmöglich durch Schnittstellenbeschränkungen zu beschreiben. Wenn Sie von einem Typ erben, können Sie viel mehr tun, als nur Methoden aufzurufen - Sie können sie auch überschreiben. Betrachten Sie dieses hypothetische Beispiel:
%Vor%Was ich dort machen möchte, ist etwas wie ein "Mix-in", bei dem MyGenericDerived Definitionen für virtuelle Funktionen in welcher Basis auch immer liefert. Aber wie weiß der Compiler, dass T eine Methode namens MyVirtual haben wird, die außer Kraft gesetzt werden kann? Ich müsste T einschränken. Wie würde ich das über Schnittstellen ausdrücken? Es ist unmöglich. Die Verwendung von Schnittstellen zur Beschreibung von Einschränkungen ist keine angemessene Lösung, wenn Sie die Vererbung von Typparametern zulassen. Das ist ein weiterer Grund, warum es heute nicht in der Sprache existiert.
Das .NET-Typsystem lässt keine Typdeklarationen des Formulars zu, das Sie versuchen. Ein Grund, warum dies nicht erlaubt ist, sollte intuitiv sein: Wie würde MyGenericClass<T>
handeln, wenn T
eine versiegelte Klasse ist (z.B. System.String
)?
Wenn Sie diese Funktionalität absolut benötigen (und Sie wissen, dass der Typ T
, den Sie verwenden, nicht versiegelt ist), können Sie Proxies zur Laufzeit generieren, indem Sie die Klassen im Namensraum Reflection.Emit
verwenden. Es ist auch möglich, diesen Effekt mit AOP-Tools wie PostSharp zu erreichen.
Sie werden alle möglichen Ts benötigen, um eine Schnittstelle zu implementieren, so dass Sie wissen, dass obj.XYZ () sinnvoll ist, dann können Sie
machen %Vor%Ich habe MyGenericClass auch dazu gebracht, Ixyz zu implementieren, da es offensichtlich die richtige Methode verfügbar macht, aber vielleicht sollte das am besten weggelassen werden, da es
erlaubt %Vor%was wahrscheinlich nie eine gute Idee sein wird.
Das ist so ziemlich Duck-Tipping, aber Sie könnten Reflexion verwenden. Wenn Sie die generische Klasse mit einem Verweis auf das obj erstellen, verwenden Sie reflection, um eine Methode mit der richtigen Signatur zu finden. Solange Sie einen Verweis auf die Methode speichern, ist die Leistung nicht zu schlecht.
%Vor%Natürlich müssten Sie viel mehr für die Fehlerprüfung und dergleichen hinzufügen, aber das ist der Kern dessen, was Sie tun könnten. Vergessen Sie außerdem nicht, den System.Reflection-Namespace Ihrer using-Klausel hinzuzufügen.
Tags und Links c# inheritance generics