Ich weiß, wie man einen Typparameter zu einem Subtyp eines anderen Typs macht:
%Vor%Gibt es eine Möglichkeit, einen Typparameter zu einem Supertyp eines anderen Typs zu zwingen?
%Vor% Momentan muss ich T1 und T2 zur Laufzeit mit IsSubclassOf
in IncludeMappingOf
vergleichen. Eine kompilierungssichere Lösung wäre vorzuziehen. Irgendwelche Ideen?
BEARBEITEN: Das Beispiel wurde so geändert, dass es weniger Design-Smelly ist.
HINWEIS: Die verknüpfte Frage ist ziemlich ähnlich, aber es gibt keine passende Antwort. Hoffentlich wird diese Frage auch etwas beleuchten.
BEARBEITEN # 2:
Einfacheres Beispiel:
%Vor%Compiler: Der Argumenttyp 'T2' ist nicht dem Parametertyp 'T1' zuweisbar. Ja, ich weiß, dass ich versuche, den Compiler dazu zu bringen, nur Fälle zuzulassen, in denen T2 dem Parametertyp T1 zuweisbar ist!
Sie können Erweiterungsmethoden verwenden, um Ihren Wünschen zu entsprechen. Mit Ihrem Halter Beispiel wäre es:
%Vor%Damit kann Ihr Beispielcode ohne Fehler kompiliert werden:
%Vor%Das Mapping-Beispiel wird dadurch erschwert, dass es sich um eine Schnittstelle handelt. Es kann erforderlich sein, der Schnittstelle eine Implementierungsmethode hinzuzufügen, wenn es keine Möglichkeit gibt, die Erweiterungsmethode von der vorhandenen Schnittstelle zu implementieren. Das bedeutet, dass Sie immer noch eine Laufzeitprüfung benötigen, aber Anrufer können die gute Syntax und die Überprüfung der Kompilierzeit erhalten. Das wäre etwa so:
%Vor% Leider hat die IncludeMappingOf
keinen Parameter vom Typ T1
, so dass die Typparameter nicht abgeleitet werden können. Sie müssen beide Typen beim Aufruf angeben:
Dies kann oft umgangen werden, indem die API so geändert wird, dass sie einen Parameter enthält (d. h. truckMapping.IncludeMappingOf(vehicleMapping)
), die Methode / Klasse des Parameters ändert oder flüssige APIs Ketten erzeugt (d. h. mapping.Of<Vehicle>().Include()
).
Während w0lfs Antwort eine direkte Lösung bietet, möchte ich einige Hintergrunderklärungen geben.
Wenn du etwas wie
schreibst %Vor%oder
%Vor% Die Einschränkungen der Form A : B
müssen A
als einen der generischen Typparameter für die deklarierte Klasse, Schnittstelle, Methode usw. haben.
Der Fehler, dem Sie gegenüberstehen, ist nicht , weil Sie einen generischen Typparameter der aktuellen Deklaration auf der rechten Seite des Doppelpunkts platziert haben (das ist legal) - weil Sie ein generisches Objekt platziert haben Geben Sie den Parameter einer äußeren Deklaration (nicht der aktuellen Deklaration) auf der linken Seite des Doppelpunkts ein.
Wenn Sie für einige Deklarationen eine Einschränkung A : B
bilden möchten, muss A
in diese Deklaration eingefügt werden und der Bereich von A
muss kleiner oder gleich dem Bereich von B
sein. Der Grund dafür ist eine pragmatische Spracheinschränkung, die für jeden generischen Typparameter T
alle Überlegungen zu Constraints vom Typ T
auf die einzelne Deklaration, in die T
eingeführt wird, isoliert.
Tags und Links c# generics type-constraints