2009-04-21 5 views
21

¿Es posible definir una función que adopte un parámetro que debe implementar dos interfaces?¿Es posible hacer que un parámetro implemente dos interfaces?

(Las dos interfaces son los que me acabo de acordar de la parte superior de mi cabeza; no los que me quieren usar)

private void DoSomthing(IComparable, ICollection input) 
{ 

} 
+0

Puede usar [el mismo truco que para declarar una variable miembro] (http://stackoverflow.com/a/4940249/429091), aunque este enfoque requiere la implementación de clases para optar por el patrón. – binki

Respuesta

49

Puede:

1) Definir una interfaz que recibe ambas interfaces necesarias:

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

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

2) Utilice los genéricos:

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

en VB.Net: Privado Sub DoSomthing (Of ​​T As {IComparable, ICollection }) (ByVal input As T) ...End Sub – Pondidum

+0

¿Hay alguna ganancia usando una de estas soluciones sobre tener dos parámetros separados? Intuitivamente parece que sería útil, pero estoy luchando por pensar en un ejemplo concreto. – CurtainDog

+0

No puedo pensar en uno por el momento, pero sí quería hacerlo hace unos días. y tener un parámetro parece mejor que llamar a DoSomthing (testData, testData) y pasar la misma instancia dos veces. – Pondidum

5

Puede heredar otro interfaz de esas dos interfaces y hacer que su parámetro de implementar que interfaz.

+1

solo funciona si puede cambiar TODAS las clases que implementen ambas interfaces para implementar la nueva interfaz. –

+0

Bueno, no TODOS necesariamente. Solo los que necesita usar como parámetro para ese método. –

2

Bueno, sí y no.

Puede, como Steve ha sugerido, crear otra, tercera, interfaz que desciende de las dos que desea, y usar eso para el tipo de parámetro.

Sin embargo, esto también hará que sea un requisito que la clase que se está utilizando implemente también esa tercera interfaz.

En otras palabras, esto no funcionará:

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 

Sin embargo, puede engañar al compilador en lo que quiere por medio de los genéricos.

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

Ahora funcionará. Todavía no estoy 100% seguro de que no le dará otros problemas, sin embargo, tendría que pensarlo.

1

El enfoque de función genérico mencionado anteriormente es bueno, con una gran advertencia: para encasillar un objeto para que se pueda pasar a una rutina con múltiples restricciones genéricas, se debe conocer un tipo que cumpla esas restricciones y es un tipo padre del objeto que se está lanzando. Una rutina que acepte dicho objeto conocerá dicho tipo (se pasó como un parámetro de tipo genérico), pero no hay una buena manera para que una clase conserve dicha información y la use más adelante. Si una variedad de tipos no relacionados implementan IFoo e IBar, sería difícil diseñar una rutina que pudiera aceptar un número de instancias de objetos no relacionadas, almacenarlas en una lista o algo así, y luego pasar todos los elementos de la lista a una rutina con un parámetro genérico IFoo + IBar.

Si tal escenario pudiera ser necesario, el mejor enfoque sería tener una contraparte no genérica para cada rutina genérica que aceptaría, p. un parámetro de tipo IFoo y lo envía a un IBar según sea necesario. Uno podría almacenar todos los artículos en una lista <IFoo> y pasarlos a la rutina. Uno perdería la seguridad de tipo del método genérico, pero a veces la seguridad de tipo perfecta no es alcanzable.

Cuestiones relacionadas