Задать вопрос
@Smilleey

Как из списка базового класса сделать список наследуемового класса?

Добрый день. споткнулся на следующей проблеме:
Есть основной класс:
public class A 
{
public string a { get; set; }
//Всего около 100 свойств
}
Есть наследственный класс:
public class B : A
{
public string b { get; set; }
//Всего около 10 дополнительных свойств
}

Есть код, который создаёт List<A>, теперь есть необходимость из List<A> создать List<B>, однако, ни один из найденных примеров к желаемому не приводит:
List<A> listA = getListA();
List<B> listB = listA.OfType<B>().ToList();
// Не ругается, но список пустой
List<A> listA = getListA();
List<B> listB = listA.Cast<B>().ToList();
// Выдаёт Exception: Ivalid Cast

Буду признателен за советы. Спасибо.
  • Вопрос задан
  • 263 просмотра
Подписаться 1 Оценить 3 комментария
Пригласить эксперта
Ответы на вопрос 3
@Free_ze
Пишу комментарии в комментарии, а не в ответы
*Какая-то беда с дизайном.*

Кастовать вниз по иерархии (downcast) напрямую объекты A в B нельзя, потому что A - это не B. Потому что B содержит какое-то дополнительное состояние (b), которого нет в A и компилятору неизвестно, каким оно должно быть в текущем виде (A конструировался иначе, чем B и как получить валидный B из A - известно лишь программисту).
Об этом вам пытается рассказать рантайм (Invalid Cast).

Что касается методов, которые не приводят к желаемому:
Enumerable.OfType<T>() - фильтрует по типу и законно возвращает пустой список (у вас список A, там действительно нет B)
Enumerable.Cast<T>() - последовательно делает каст, который невозможен.

Можно попытаться скопировать объекты в новый список:
listA.Select(x => new B{ a = x.a }).ToList();

Но это прокатит лишь в том случае, если мы сможем достать из A необходимые данные для конструирования объекта B. Важно понимать, что это будут именно ДРУГИЕ объекты. Если A некопируем по своей природе, то этот фокус не пройдет.
Ответ написан
@Sterk
Программист
Создать в классе B конструктор принимающий класс А и инициализирующий свои поля значениями из А. Затем
var listB = listA.Select(a=>new B(a)).ToList();
Ответ написан
AxisPod
@AxisPod
С архитектурой явная проблема. По хорошему в таком случае надо работать с интерфейсами по возможности и использовать ковариантность/контравариантность.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы