2009-09-21 2 views
9

Ho un paio di classi:IList <Type> a IList <BaseType>

class Vehicle 
{ 
} 

class Car : Vehicle 
{ 
} 

Ho una lista della classe derivata: IList<Car> cars;

Vorrei convertire l'elenco alla sua classe base, e hanno provato: IList<Vehicle> baseList = cars as IList<Vehicle>;

Ma ottengo sempre null. Anche

cars is IList<Vehicle> evaluates to be false. 

Certo, posso aggiungere gli elementi a un elenco se faccio la seguente:

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

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

E io ottenere la mia lista, ma so che ci deve essere un modo migliore. Qualche idea?

+1

correlati a http://stackoverflow.com/questions/981570/c-no-implict-conversion-from-classchild-to-classbase e http://stackoverflow.com/questions/1296892/c-interface-implementation -and-generic-collections-question almeno. –

+0

Robert Harvey: Certo che esiste un modo alternativo; potrebbe creare un'implementazione di IList che è fondamentalmente un wrapper su un IList esistente . In questo modo, non avrebbe dovuto gettare tutti gli elementi, solo quelli necessari. –

risposta

18

Uso IEnumerable<T>.Cast:

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

In alternativa, si può essere in grado di evitare la conversione in lista a seconda di come si desidera elaborare l'elenco auto sorgente.

+0

@Robert Harvey: .Net Framework 3.5 è stato rilasciato quasi due anni fa.Penso che sia sicuro presumere che tutti lo abbiano ormai a meno che non abbiano una buona ragione per non farlo. –

+5

Si noti che questo risulta in un nuovo elenco, non un riferimento alla stessa lista. – configurator

12

Quella sorta di polimorfismo che consente lanci IList<Car>-IList<Vehicle> è pericoloso, perché sarebbe permetterà di inserire un Truck nella vostra IList<Car>.

+0

Non sta provando a lanciarlo, ma crea una nuova istanza di lista. – recursive

+5

uh, no. Sta provando ad assegnare un (riferimento ad un) elenco del tipo base da un (riferimento ad un) elenco del tipo derivato, e chiedendosi perché ottiene null. Se cercasse di creare una nuova istanza, funzionerebbe correttamente. – Novelocrat

+1

Oh, giusto. Non ho letto abbastanza vicino. – recursive

3

Qui ci sono un paio di approcci utilizzando 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

Stai affrontando il problema che v'è co- limitata e controvarianza in C#. C'è un approccio interessante in C# 4.0, descritto here at the very ending. Tuttavia, crea alcune altre limitazioni correlate al problema del camion nella risposta di Novelocrat.

0

Se è necessario utilizzare IList tutto il modo, allora siete fuori di fortuna e le risposte di cui sopra può aiutare. Tuttavia, se è possibile utilizzare uno 012 castato come IEnumerable e quindi semplicemente ri-castato a destinazione come IList, funzionerebbe, dal momento che IEnumerable può accettare tale pratica.

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

Anche se, dal momento che il compilatore non può far rispettare queste cose, si deve fare manualmente in modo che i tipi e tipi di base in effetti corrispondono, naturalmente.