Schnittstelle für eine Methode, die ihren eigenen Typ zurückgibt

8

Ich habe eine Situation, in der ich eine Klasse habe

%Vor%

Nun kann ich eine Schnittstelle dafür erstellen

%Vor%

Was sollten die Fragezeichen ersetzen? Jede Klasse sollte ihren eigenen Typ zurückgeben, nicht Foo.

Die folgenden Lösungen funktionieren, sehen aber nicht sauber aus. Ich verstehe nicht, warum ich dieselbe Klasse zweimal angeben muss, und es gibt nichts wie "das" für den aktuellen Typ

So benutze ich es später

%Vor%     
Andrey 15.06.2010, 13:39
quelle

7 Antworten

10

Sie fragen:

  

Die folgenden Lösungen funktionieren, sehen aber nicht sauber aus. Ich verstehe nicht, warum ich dieselbe Klasse zweimal angeben muss, und es gibt nichts wie "das" für den aktuellen Typ

Der Grund, warum Sie es zweimal angeben müssen, liegt daran, dass C # nicht über die Funktion verfügt, die Sie benötigen. Was Sie wollen, ist etwa so:

%Vor%

Aus Sicht der Typsicherheit sollte dies funktionieren (es heißt Rückgabetyp-Kovarianz ). In der Tat unterstützen andere Programmiersprachen wie C ++ oder Java dies, siehe dieses Beispiel auf Wikipedia . Leider wird Rückgabetyp-Kovarianz von C # nicht unterstützt (nicht einmal C # 4.0, was die Kovarianz für Generika einführte), weshalb Sie die in den anderen Antworten dargestellte "Generika-Problemumgehung" verwenden müssen.

Kovariante Rückgabetypen sowie ein "This" -Typ sind vorgeschlagene Features für neue Versionen von C #:

Heinzi 15.06.2010, 14:00
quelle
8

Sie könnten einen generischen Typ hinzufügen und ihn mit dem Schnittstellentyp einschränken:

%Vor%

Sie würden dies wie folgt implementieren:

%Vor%

Update , wenn Sie sich nicht um den konkreten Rückgabetyp von Foo kümmern, können Sie Folgendes tun:

%Vor%

Was ist implementiert wie:

%Vor%

Dann in Ihrer generischen Klasse:

%Vor%

GenericClass<Foo>.Rar(); wird eine konkrete Implementierung von Foo sein.

    
GenericTypeTea 15.06.2010 13:42
quelle
4

Ich denke, dass die wirkliche Frage ist: Warum brauchen Sie den abgeleiteten Typ in der Schnittstelle? Interface ist genau deshalb - Abstraktion von den konkreten Klassen. Wenn es nur für die Bequemlichkeit ist, also müssen Sie nach dem Aufruf von Bar () nicht nach Foo umwandeln, können Sie die Schnittstelle explizit implementieren:

%Vor%

Stellen Sie sich die Frage: Warum stellen Sie eine Schnittstelle vor, wenn Sie den konkreten Typ möchten?

    
Stefan 15.06.2010 14:07
quelle
2

Um dies zu erreichen, können Sie eine abstrakte Basisklasse plus explizite Member-Implementierung verwenden. Deklarieren Sie zunächst Ihre Schnittstelle wie folgt:

%Vor%

Deklarieren Sie eine generische abstrakte Klasse, die IFoo explizit implementiert, und deklarieren Sie auch eine abstrakte Methode, die Bar () "überlädt", aber generisch:

%Vor%

Definieren Sie nun Ihre konkreten Klassen wie folgt:

%Vor%

Der Vorteil dieses Ansatzes besteht darin, dass Sie nicht-generische IFoo-Referenzen verwenden können, um konkrete Instanzen zu halten . Wenn Sie Ihre Schnittstelle generisch machen, können Sie diese beispielsweise nicht deklarieren:

%Vor%     
Humberto 15.06.2010 13:47
quelle
0
%Vor%

Ihre Implementierung wäre dann:

%Vor%     
Justin Niessner 15.06.2010 13:42
quelle
0

Sie müssen die Schnittstelle wie folgt generisch machen:

%Vor%     
SLaks 15.06.2010 13:42
quelle
0

Nicht sicher, was Sie erreichen möchten, aber es könnte so gemacht werden:

%Vor%

Oder so:

%Vor%     
CkH 15.06.2010 13:49
quelle

Tags und Links