Betrachten Sie die folgende Klasse:
%Vor% Beachten Sie, dass ich das generische Klassen-Argument TBase
auf eine Klasse eingeschränkt habe: where TBase : class
Ich habe auch das TDerived
generische Methodenargument auf TBase
oder etwas davon abgeleitet: where TDerived : TBase
.
Ich bekomme einen Fehler in der as TDerived
-Zeile:
Der Typparameter 'TDerived' kann nicht mit dem 'as' -Operator verwendet werden, da er weder eine Klassenbeschränkung noch eine 'class'-Integritätsregel
enthält
Ich verstehe, dass ich den Constraint class
hinzufügen muss, um den Fehler zu vermeiden, also bekomme ich:
Warum muss ich dies tun, wenn TBase
bereits auf eine Klasse beschränkt ist und TDerived
auf eine TBase
beschränkt oder davon abgeleitet ist?
UPDATE: Diese Frage war das Thema meines Blogs am 19. September 2011 . Danke für die tolle Frage!
Warum muss ich das tun, wenn TBase bereits als Klasse definiert ist und TDerived gezwungen ist, eine TBase zu sein oder davon abgeleitet zu sein?
Weil ein Werttyp von einem Referenztyp abgeleitet werden kann. int
wird von den Referenztypen object
und System.ValueType
abgeleitet und implementiert eine Anzahl von Schnittstellen. Das macht int
nicht zu einem Referenztyp.
Es ist absolut legal, dass Sie SomeMethod<int>
für eine Instanz von DerivedClassPool<object>
aufrufen, weil int von object abgeleitet ist.
Nun, dort sind Fälle, in denen Ihre Kritik gerechtfertigt wäre. Man kann Situationen konstruieren, in denen zwei Typparameter so zusammenhängen, dass beide logisch nur Referenztypen sein können, aber nur einer von ihnen von der Sprache als "vom Referenztyp bekannt" klassifiziert wird.
Als Übung für den Leser: Kannst du einen finden? Es könnte notwendig sein, Abschnitt 10.1.5 der Spezifikation für eine genaue Definition von "bekannt als Referenztyp" sorgfältig zu lesen.
Weil TBase
eine Schnittstelle sein könnte und daher TDerived
ein Werttyp sein könnte.
Tags und Links c# inheritance generics