Lassen Sie uns sagen, dass wir
interface IPersonRepository : IRepository<Person> { }
erklären möchten, dass erfordern würde, dass es eine generische Schnittstelle IRepository<EntityType>
mit einem Typ-Parameter ist.
interface IRepository<EntityType> where EntityType : Entity<KeyType>
{
EntityType Get(KeyType id);
}
Am Ende der ersten Zeile, beziehen Sie sich auf eine Sache KeyType
genannt, die noch definiert erklärt worden ist. Es gibt keinen Typ namens "KeyType".
obwohl dies funktionieren würde:
interface IRepository<EntityType> where EntityType : Entity<int>
{
EntityType Get(int id);
}
Oder diese:
interface IRepository<EntityType> where EntityType : Entity<string>
{
EntityType Get(string id);
}
Aber man kann beide widersprüchlichen Definitionen nicht zur gleichen Zeit natürlich hat. 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, können Sie, wenn Sie es machen Generika in den Schlüsseltyp:
interface IRepository<KeyType, EntityType> where EntityType : Entity<KeyType>
{
EntityType Get(KeyType id);
}
Es ist ein alternativer Ansatz:
interface IRepository<KeyType>
{
EntityType<KeyType> Get(KeyType id);
}
Jetzt können Sie definieren
class PersonRepository : IRepository<int>
{
public EntityType<int> Get(int id) { ... }
}
Offensichtlich würden Sie damit nicht zufrieden sein, denn Sie möchten angeben, dass die Get-Methode einezurückgeben muss, nicht irgendein Entity<int>
.
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: Das Spezifizieren von int
für den Typparameter führt nicht genügend Informationen.
Wenn wir sagen,
class PersonRepository : IRepository<int, Person>
{
public Person Get(int id) { ... }
}
Es in der Tat Redundanz ist: Angabe des Typs Parameter int
redundant ist, wenn der Typ-Parameter 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:
class PersonRepository : IRepository<EntityType: Person>.
{
public Person Get(int id) { ... }
}
Während theoretisch möglich, fürchte ich, dass dies eine Menge Komplexität der Sprachspezifikation und dem Compiler hinzufügen würde, für sehr wenig Gewinn. Gibt es überhaupt einen Gewinn? Sie würden sicherlich keine Tastenanschläge speichern! Vergleichen Sie diese zwei:
// current syntax
class PersonRepository : IRepository<int, Person>
{
public Person Get(int id) { ... }
}
// proposed syntax
class PersonRepository : IRepository<EntityType: Person>
{
public Person Get(int id) { ... }
}
Die Sprache ist was es ist, und es sieht nicht so schlecht zu mir.
Wie soll es den 'KeyType' wissen? Können Sie die vollständige Syntax Ihrer Erwartungen zeigen? Ihre letzte Schnittstellendefinition ist nicht vollständig. –
Ich glaube nicht, dass es möglich ist. Der Compiler ist nicht "schlau" genug. Ich werde es aber nicht zur Antwort machen, denn "Ich kann mir keinen Weg vorstellen, wie du es tun kannst" ist nicht Beweis genug, dass du es nicht kannst. – Falanwe
Ich nehme an, die letzte Zeile des Codes sollte sein 'Schnittstelle IPersonRepository: IRepository {...} ' –
Rawling