Generische Typinferenz in C #

9

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:

%Vor%

und lassen Sie den Compiler herausfinden, dass IPersonRepository KeyType ist. Ist es möglich?

    
proskor 22.09.2014, 09:06
quelle

3 Antworten

1

Nehmen wir an, wir möchten

deklarieren %Vor%

Das würde erfordern, dass es eine generische Schnittstelle mit einem Typparameter IRepository<EntityType> gibt.

%Vor%

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.

    
Kris Vandermotten 22.09.2014, 09:39
quelle
1

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.

    
Martijn 23.09.2014 20:37
quelle
0

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)

    
Patrick Hofman 22.09.2014 09:39
quelle

Tags und Links