Sagen wir, es gibt diese generischen Typen in C #:
%Vor%und diese konkreten Typen:
%Vor% Nun ist die Definition von PersonRepository
überflüssig: Die Tatsache, dass KeyType
von Person
ist int
ist explizit angegeben, obwohl daraus abgeleitet werden kann, dass Person
ein Untertyp von% co_de ist %.
Es wäre schön, Entity<int>
folgendermaßen definieren zu können:
und lassen Sie den Compiler herausfinden, dass IPersonRepository
KeyType
ist. Ist es möglich?
Nehmen wir an, wir möchten
deklarieren %Vor% Das würde erfordern, dass es eine generische Schnittstelle mit einem Typparameter IRepository<EntityType>
gibt.
Am Ende der ersten Zeile verweisen Sie auf eine Sache namens KeyType
, die weder deklariert noch definiert wurde. Es gibt keinen Typ namens "KeyType".
Das würde aber funktionieren:
%Vor%Oder das:
%Vor%Aber Sie können natürlich nicht beide widersprüchlichen Definitionen gleichzeitig haben. Offensichtlich sind Sie damit nicht zufrieden, weil Sie Ihre IR-Repository-Schnittstelle so definieren möchten, dass sie auch mit anderen Schlüsseltypen funktioniert.
Nun, Sie können, wenn Sie es im Schlüsseltyp generisch machen:
%Vor%Es gibt einen alternativen Ansatz:
%Vor%Jetzt können Sie
definieren %Vor% Offensichtlich würden Sie damit nicht zufrieden sein, denn Sie möchten angeben, dass die Get-Methode ein Person
und nicht irgendein Entity<int>
zurückgeben muss.
Die generische Schnittstelle mit zwei Typparametern in der einzigen Lösung. Und tatsächlich gibt es eine erforderliche Beziehung zwischen ihnen, wie sie in der Einschränkung ausgedrückt wird. Aber hier gibt es keine Redundanz: Die Angabe von int
für den Typparameter enthält nicht genügend Informationen.
Wenn wir sagen
%Vor% Tatsächlich gibt es Redundanz: Angabe des Typparameters int
ist redundant, wenn der Typparameter Person
bereits angegeben wurde.
Es wäre möglich, mit einer Syntax zu arbeiten, die es ermöglicht, den KeyType abzuleiten. Zum Beispiel schlug Patrick Hoffman vor:
%Vor%Obwohl theoretisch möglich, befürchte ich, dass dies der Sprachspezifikation und dem Compiler für sehr wenig Gewinn viel Komplexität hinzufügen würde. Gibt es überhaupt einen Gewinn? Sie würden sicherlich keine Tastenanschläge speichern! Vergleichen Sie diese zwei:
%Vor%Die Sprache ist was es ist, und es sieht mir nicht schlecht aus.
Nein, das C # -Typsystem ist nicht ausreichend fortgeschritten, um das auszudrücken, was Sie wollen. Die benötigte Funktion wird höher kinded type genannt, die oft in stark typisierten funktionalen Sprachen (Haskell, OCaml, Scala) gefunden wird.
Wenn Sie zurückgehen, möchten Sie in der Lage sein,
zu schreiben %Vor%, aber in C # gibt es keine Möglichkeit, die Art EntityType auszudrücken oder mit anderen Worten, dass der type-Parameter einige generische Parameter hat und diesen generischen Parameter in Ihrem Code verwendet.
Randnotiz: Das Repository-Muster ist böse und muss in einem Feuer sterben.
Nein, das ist nicht möglich, das zu schreiben, da es den Typ nicht ableitet (der Compiler nicht).
Es sollte möglich sein, dies zu tun (Sie müssen jedoch Teil des C # -Compiler-Teams sein, um es zu bekommen), da kein anderer Wert möglich ist, den der Wert von KeyType
in den Typparameter für% co_de einfügt %. Sie können keinen abgeleiteten Typ oder einen Basisklassentyp eingeben.
Wie andere bereits bemerkt haben, könnte es Ihren Code komplizierter machen. Dies funktioniert auch nur in dem Fall, dass Entity
eine Klasse ist, wenn es eine Schnittstelle ist, kann es den Typ nicht ableiten, da es mehrere Implementierungen haben kann. (Vielleicht ist das der ultimative Grund, warum sie das nicht eingebaut haben)
Tags und Links c# generics type-inference