2011-10-03 17 views
15

que tienen una función como esta:¿Cómo pasar la Lista de clase a la Lista de interfaz?

DoSomething(List<IMyInterface>) 

IMyInterface es una interfaz y una clase MiClase es la implementación de esta interfaz clase MiClase: IMyInterface

llamo DoSomething(List<MyClass>) y parece que no funciona. ¿Cómo podría pasar la lista de una clase a una lista de la interfaz de la clase como parámetro de la función? ¡Gracias!

+0

¿cuál es su código? – talnicolas

Respuesta

26

Si el código es simplemente iterar sobre la secuencia dentro del método (no añadir, eliminar, o acceder por índice), cambiar su método a una de las siguientes

DoSomething(IEnumerable<IMyInterface> sequence) 
DoSomething<T>(IEnumerable<T> sequence) where T : IMyInterface 

La interfaz IEnumerable<> es covariante (como de .NET 4) (primera opción). O puede usar la última firma si usa C# 3.

De lo contrario, si necesita operaciones indexadas, convierta la lista antes de pasarla. En la invocación, es posible que tenga

// invocation using existing method signature 
DoSomething(yourList.Cast<IMyInterface>().ToList()); 

// or updating method signature to make it generic 
DoSomething<T>(IList<T> list) where T : IMyInterface 

Lo que esta última firma le permitiría hacer es apoyar también permite añadir o eliminar de la lista (visible en la callsite), y también le permitirá utilizar la lista sin primero copiándolo.

Aún así, si todo lo que haces es iterar sobre la lista en un bucle, yo preferiría un método que acepte IEnumerable<>.

+0

Para operaciones indexadas y eliminación, ¿no funcionaría 'DoSomething (lista de IList ) donde T: IMyInterface'? (Sin la necesidad de copiar la lista.) – millimoose

+0

@Sli, sí, podría hacer que el método sea genérico. He actualizado para mostrar las opciones genéricas. –

+0

Una alternativa sería definir una interfaz IReadableList , y luego escribir una clase contenedora que implemente tanto eso como IList . Sin embargo, lamentablemente, otros códigos deberían modificarse para usar la clase contenedora. Se podría definir una conversión de ampliación de una lista a un ListWrapper , pero eso sería un tanto repulsivo y no sería ayudar al sistema reconocer que una lista se puede convertir en algo (un ListWrapper ) que implementa IReadableList . – supercat

7

Esto no es seguro en general porque las listas son mutables. Supongamos que alguien se pasa una referencia a un List<MyClass> como List<IMyInterface>, a continuación, que hacen:

void Foo(List<IMyInterface> list) 
{ 
    IMyInterface x = new MyOtherClassWhichAlsoImplementsIMyInterface(); 
    list.Add(x); 
} 

Ahora su List<MyClass> contiene una instancia de una clase que no es un MyClass. Esto violaría la seguridad del tipo. (Como se indicó en otras respuestas, puede evitar este problema pasando solo la interfaz IEnumerable<> de List, que proporciona acceso de solo lectura y por lo tanto es seguro).

Para obtener más información, consulte Using Variance in Interfaces for Generic Collections on MSDN. Vea también a good summary of covariance and contravariance and various C# features that support it.

0

Si solo tiene que pasar por la lista, declare el método con un IEnumerable. Si desea agregar elementos a la lista, lo que está solicitando no es seguro y, por lo tanto, es posible que no se permita su uso en C#.

Cuestiones relacionadas