2009-09-21 12 views
9

tengo unas pocas clases:IList <Type> a IList <BaseType>

class Vehicle 
{ 
} 

class Car : Vehicle 
{ 
} 

Tengo una lista de la clase derivada: IList<Car> cars;

me gustaría convertir la lista de su clase base, y que tienen intentado: IList<Vehicle> baseList = cars as IList<Vehicle>;

Pero siempre consigo null. También

cars is IList<Vehicle> evaluates to be false. 

Por supuesto, puedo añadir los elementos a una lista si hago lo siguiente:

List<Vehicle> test = new List<Vehicle>(); 

foreach (Car car in cars) 
{ 
    test.Add(car); 
} 

Y me da mi lista, pero sé que tiene que haber una mejor manera. ¿Alguna idea?

+1

Relacionados con http://stackoverflow.com/questions/981570/c-no-implict-conversion-from-classchild-to-classbase y http://stackoverflow.com/questions/1296892/c-interface-implementation -and-generic-collections-question al menos. –

+0

Robert Harvey: Por supuesto que hay una manera alternativa; podría crear una implementación de IList que básicamente es un contenedor sobre un IList existente . De esta forma, no tendría que lanzar todos los elementos, solo los que se necesitan. –

Respuesta

18

Uso IEnumerable<T>.Cast:

IList<Vehicle> vehicles = cars.Cast<Vehicle>().ToList(); 

Como alternativa, puede ser capaz de evitar la conversión a la lista dependiendo de cómo se desea procesar la lista de coches de origen.

+0

@Robert Harvey: .Net Framework 3.5 ha sido lanzado hace casi dos años.Creo que es seguro suponer que todos lo tienen a menos que tengan una muy buena razón para no hacerlo. –

+5

Tenga en cuenta que esto da como resultado una nueva lista, no una referencia a la misma lista. – configurator

12

Ese tipo de polimorfismo que permite que lances IList<Car> a IList<Vehicle> es inseguro, porque permitiría que se inserta un Truck en su IList<Car>.

+0

No intenta lanzarlo, pero crea una nueva instancia de lista. – recursive

+5

uh, no. Está intentando asignar una lista (referencia a una) del tipo base de una lista (referencia a a) del tipo derivado, y preguntándose por qué obtiene el valor nulo. Si intentara crear una nueva instancia, esto funcionaría bien. – Novelocrat

+1

Oh, claro. No leí lo suficientemente cerca. – recursive

3

Aquí hay un par de aproximaciones usando LINQ:

IList<Derived> list = new List<Derived>(); 
list.Add(new Derived()); 

IList<Base> otherlist = new List<Base>(from item in list select item as Base); 
IList<Base> otherlist2 = new List<Base>(list.Select(item => item as Base)); 
1
var vehicles = cars.OfType<IVehicle>() 
4

Estás frente al problema que existe cooperación limitada y contravarianza en C#. Hay un enfoque interesante en C# 4.0, descrito here at the very ending. Sin embargo, crea algunas otras limitaciones que están relacionadas con el problema del camión en la respuesta de Novelocrat.

0

Si tiene que usar IList todo el camino, entonces estás de suerte y de las respuestas anteriores pueden ayudarle. Sin embargo, si puede usar un IList que se fundió como IEnumerable y luego simplemente recolocar en el destino como IList, eso funcionaría, ya que IEnumerable puede aceptar dicha práctica.

// At the source or at the model. 
IEnumerable<BaseType> list = new List<Type>(); 
// At the destination. 
IList<BaseType> castedList = (IList<BaseType>)list; 

Aunque, ya que el compilador no puede hacer cumplir estas cosas, es necesario realizar manualmente asegurarse de que los tipos y tipos de bases de hecho coinciden, por supuesto.

Cuestiones relacionadas