2009-09-21 3 views
9

У меня есть несколько классов:IList <Type> к IList <BaseType>

class Vehicle 
{ 
} 

class Car : Vehicle 
{ 
} 

У меня есть список из производного класса: IList<Car> cars;

Я хотел бы, чтобы преобразовать список базового класса, и имеет проверено: IList<Vehicle> baseList = cars as IList<Vehicle>;

Но я всегда получаю null. Также

cars is IList<Vehicle> evaluates to be false. 

Конечно, я могу добавить элементы в список, если я следующее:

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

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

И я получу свой список, но я знаю, что должен быть лучший способ. Любые мысли?

+1

Связано с http://stackoverflow.com/questions/981570/c-no-implict-conversion-from-classchild-to-classbase и http://stackoverflow.com/questions/1296892/c-interface-implementation - и-generic-collections - по крайней мере. –

+0

Роберт Харви: Конечно, есть альтернативный путь; он мог бы создать реализацию IList , которая в основном представляет собой оболочку поверх существующего IList . Таким образом, ему не пришлось бы бросать все элементы, только те, которые необходимы. –

ответ

18

Использование IEnumerable<T>.Cast:

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

В качестве альтернативы, вы можете быть в состоянии избежать превращения в список в зависимости от того, как вы хотите, чтобы обработать список источников автомобиля.

+0

@Robert Harvey: .Net Framework 3.5 выпущена почти два года назад.Я думаю, что можно с уверенностью предположить, что у всех это есть сейчас, если у них нет веских оснований. –

+5

Обратите внимание, что это приводит к новому списку, а не к тому же списку. – configurator

12

Такого рода полиморфизм, который позволяет отливать IList<Car> к IList<Vehicle> небезопасен, поскольку это позволит вам вставить Truck в вашем IList<Car>.

+0

Он не пытается использовать его, но создает новый экземпляр списка. – recursive

+5

Ух, нет. Он пытается назначить (базовый тип) (базовый тип) из списка (ссылки на а) производного типа и задается вопросом, почему он получает нуль. Если бы он пытался создать новый экземпляр, это сработало бы хорошо. – Novelocrat

+1

О, право. Я не читал достаточно близко. – recursive

3

Вот несколько подходов с использованием 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)); 
4

Вы столкнулись с проблемой, что существует ограниченное со- и контрвариантность в C#. В C# 4.0 есть интересный подход, описанный here at the very ending. Тем не менее, это создает некоторые другие ограничения, связанные с проблемой грузовика в ответ от Novelocrat.

0

Если вы должны использовать IList все пути, то вам не повезло и ответы выше, могут помочь вам. Однако, если вы можете использовать IList, который выставляется как IEnumerable, а затем просто повторно отправлен в пункт назначения IList, это сработало бы, так как IEnumerable может принять такую ​​практику.

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

Хотя, так как компилятор не может обеспечить эти вещи, вы должны вручную убедиться, что типы и базовые типы действительно совпадают, конечно.

Смежные вопросы