2009-04-21 12 views
21

Kann eine Funktion definiert werden, die einen Parameter akzeptiert, der zwei Schnittstellen implementieren muss?Kann ein Parameter zwei Schnittstellen implementieren?

(Die beiden Schnittstellen sind diejenigen, die ich nur die Spitze von meinem Kopf erinnerte ab, nicht die, die ich verwenden möchte)

private void DoSomthing(IComparable, ICollection input) 
{ 

} 
+0

Sie können [den gleichen Trick wie für die Deklaration einer Membervariable] (http://stackoverflow.com/a/4940249/429091) verwenden, obwohl dieser Ansatz das Implementieren von Klassen erfordert, um sich für das Muster zu entscheiden. – binki

Antwort

49

Sie können:

1) Definieren Sie eine Schnittstelle, die beide erforderlichen Schnittstellen erbt:

public interface ICombinedInterface : IComparable, ICollection {... } 

private void DoSomething(ICombinedInterface input) {... } 

2) Verwenden Sie Generika:

private void DoSomething<T>(T input) 
    where T : IComparable, ICollection 
{...} 
+3

in VB.Net: Private Sub-DoSomthing (von T als {IComparable, ICollection }) (ByVal-Eingabe als T) ...End Sub – Pondidum

+0

Gibt es einen Gewinn mit einer dieser Lösungen gegenüber zwei separaten Parametern? Intuitiv scheint es, als wäre es nützlich, aber ich habe Mühe, an ein konkretes Beispiel zu denken. – CurtainDog

+0

Ich kann im Moment nicht an einen denken, aber ich wollte das vor ein paar Tagen machen. Ein Parameter sieht besser aus als DoSomthing (testData, testData) aufzurufen und die gleiche Instanz zweimal zu übergeben. – Pondidum

5

Sie können eine andere Schnittstelle aus diesen beiden Schnittstellen erben und Ihre Parameter machen implementieren, dass Schnittstelle.

+1

funktioniert nur, wenn Sie ALLE Klassen ändern können, die beide Schnittstellen implementieren, um die neue Schnittstelle zu implementieren. –

+0

Nun, nicht alle von ihnen unbedingt. Nur diejenigen, die Sie als Parameter für diese Methode verwenden müssen. –

2

Nun, ja und nein.

Sie können, wie Steve vorgeschlagen hat, eine weitere, dritte Schnittstelle erstellen, die von den zwei gewünschten abstammt, und diese für den Parametertyp verwenden.

Dies erfordert jedoch auch, dass die verwendete Klasse auch diese dritte Schnittstelle implementiert.

Mit anderen Worten, wird dies nicht funktionieren:

public interface I1 { } 
public interface I2 { } 
public class C : I1, I2 { } 

public interface I3 : I1, I2 { } 
public class YourClass 
{ 
    public void Test(I3 i) { } 
} 

... 
YourClass yc = new YourClass(); 
C c = new C(); 
yc.Test(c); // won't work, C does not implement I3 

Sie können jedoch den Compiler tricksen, was Sie von Generika durch wollen.

public class YourClass 
{ 
    public void Test<T>(T i) where T: I1, I2 { } 
} 

Jetzt wird es funktionieren. Ich bin mir immer noch nicht 100% ig sicher, dass es dir keine anderen Probleme geben wird, ich müsste darüber nachdenken.

1

Der oben erwähnte generische Funktionsansatz ist ein guter, mit einem großen Vorbehalt: Um ein Objekt typisieren zu können, so dass es an eine Routine mit mehreren generischen Einschränkungen übergeben werden kann, muss man einen Typ kennen, der diese Bedingungen erfüllt ist ein übergeordneter Typ des Objekts, das umgewandelt wird. Eine Routine, die ein solches Objekt akzeptiert, wird einen solchen Typ kennen (wurde als generischer Typparameter übergeben), aber es gibt keine gute Möglichkeit für eine Klasse, solche Informationen zu erhalten und später zu verwenden. Wenn eine Vielzahl von nicht miteinander verwandten Typen sowohl IFoo als auch IBar implementiert, wäre es schwierig, eine Routine zu entwerfen, die eine Anzahl von nicht verwandten Objektinstanzen akzeptieren, sie in einer Liste oder etwas speichern und dann alle Elemente in der Liste an eine Routine übergeben kann mit einem generischen IFoo + IBar-Parameter.

Wenn ein solches Szenario erforderlich sein könnte, wäre der beste Ansatz, ein nicht-generisches Gegenstück für jede generische Routine zu haben, die z. ein Parameter des Typs IFoo und wandle ihn bei Bedarf in einen IBar um. Man könnte dann alle Elemente in einer Liste <IFoo> speichern und sie an die Routine übergeben. Man würde die Typ-Sicherheit der generischen Methode verlieren, aber manchmal ist eine perfekte Typ-Sicherheit nicht erreichbar.

Verwandte Themen