IList <Type>до IList <BaseType> - PullRequest
       14

IList <Type>до IList <BaseType>

9 голосов
/ 22 сентября 2009

У меня есть несколько классов:

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);
}

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

Ответы [ 7 ]

20 голосов
/ 22 сентября 2009

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

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

Кроме того, вы можете избежать преобразования в список в зависимости от того, как вы хотите обработать исходный список автомобилей.

11 голосов
/ 22 сентября 2009

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

4 голосов
/ 22 сентября 2009

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

3 голосов
/ 22 сентября 2009

Вот несколько подходов, использующих 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));
2 голосов
/ 22 сентября 2009

Вы также можете взглянуть на статью Кшиштофа о Cwalina, Симулированная ковариация для .NET Generics

1 голос
/ 22 сентября 2009
var vehicles = cars.OfType<IVehicle>()
0 голосов
/ 01 марта 2015

Если вы должны использовать 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;

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...