Определение производных типов из списка объектов базового класса
-
20-09-2019 - |
Вопрос
Это может показаться своего рода "домашним заданием" и / или тривиальным, но это для реальной бизнес-цели;это просто самый простой способ, который я мог придумать, чтобы объяснить, что я концептуально пытаюсь сделать.
Предположим, у меня есть класс Animal и некоторые другие классы (Птица, Кошка, кенгуру).Каждый из них наследуется от Животного.
Животное может выглядеть примерно так:
public class Animal
{
public Animal()
{
}
public string Name { get; set; }
public string AnimalType { get; set; }
public List<Animal> Friends { get; set; }
}
Кенгуру может выглядеть примерно так:
public class Kangaroo : Animal
{
public Kangaroo()
{
}
public int TailLengthInches { get; set; }
}
Предположим, у кенгуру есть два друга, птица и кошка.Как я мог бы добавить их в список друзей "Animal" (как тип Animal), но сохранить возможность доступа к свойствам производных классов?(например, мне все еще нужно иметь возможность работать со свойствами, специфичными для типа животного, например, с цветом перьев птицы, даже если они будут считаться просто "животными".
Причина, по которой я пытаюсь это сделать, заключается в том, что, когда я позже получу список "друзей" животного, мне жизненно важно знать, к какому типу животных относится этот друг.В зависимости от типа животного (будь то птица, кошка и т.д.) Я хочу сделать что-то другое (на самом деле, показать другой шаблон на странице ASP.NET, но мне не нужна помощь конкретно с этим).
Я предполагаю, что это сводится к следующему ... если у меня есть список Animal , как я могу узнать, какой производный тип был для каждого из объектов в списке, чтобы я мог привести их обратно к их производному типу или сделать что-то еще, что позволит мне получить доступ к конкретным, различным свойствам, которые есть у каждого производного типа?
Спасибо!
Решение
Вы можете использовать LINQ для фильтрации по типу, который вы ищете.
animals.Friends = new List<Animal> { new Kangaroo(), new Bird() };
foreach ( var kangaroo in animals.Friends.OfType<Kangaroo>()) {
kangaroo.Hop();
}
Другие советы
Попробуйте провести кастинг:
var friendBird = friend as Bird;
if (friendBird != null)
{
// It's a bird, so do something with it
)
Вы можете использовать typeof
чтобы получить фактический тип, или используйте is
или as
операторы для тестирования и, при необходимости, приведения:
foreach (Animal a in Friends)
{
Kangaroo k = a as Kangaroo;
if (a != null)
{
// it's a kangaroo
k.JumpAround();
}
Ostrich o = a as Ostrich;
if (o != null)
{
o.StickHeadInSand();
}
}
(я не использовал else
здесь предложения, которые могут вызвать ошибки, если вы тестируете типы, которые могут находиться в иерархии, например.если бы у вас были предложения «Кенгуру» и «Сумчатые», вы, вероятно, НЕ хотели бы, чтобы оба выполнялись!)
Вы также можете сделать это с помощью is
оператор, который выглядит красивее, но заставит FxCop плакать:
foreach (Animal a in Friends)
{
if (a is Kangaroo)
{
((Kangaroo)a).JumpAround();
}
}
А вообще, кстати, вы наверняка захотите поискать возможность поставить виртуальный метод на Animal
и реализовать этот метод полиморфно, вместо того, чтобы использовать чудовищные операторы if, которые приводят к хрупкой связи с определенным набором производных классов.
Используйте ключевое слово "is".
если (животное - это Птица) ...
animals.Friends = new List<Animal> { new Kangaroo(), new Bird() };
foreach (Animal animal in animals.Friends)
{
if (animal is Kangaroo)
Console.WriteLine("Kangaroo");
else if (animal is Bird)
Console.WriteLine("Bird");
}