从基类对象列表中识别派生类型

时间:2010-01-15 21:06:13

标签: c# class inheritance types derived

这可能看起来像“家庭作业”和/或微不足道,但它是出于真正的商业目的;这是我能想到解释我在概念上试图做的最简单的方法。

假设我有一个Animal类和其他一些类(Bird,Cat,Kangaroo)。其中每一个都来自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; }
}

假设袋鼠有两个朋友,一只鸟和一只猫。我怎么能将这些添加到“动物”朋友列表(作为动物类型),但保留访问派生类属性的能力? (如,我还需要能够与特定于动物的类型,像FeatherColor为鸟性质的工作,例如,即使他们将被视为仅仅是“动物”。

我想这样做的原因是,当我后来获得的动物的“好友”列表中,至关重要的是,我知道朋友是什么类型的动物。根据动物类型(无论是鸟,猫等),我想要做一些不同(表现出不同的模板在ASP.NET页面上,其实,但我并不需要提供帮助的具体)。

我想它归结为这个......如果我有动物的名单了,我怎么知道是什么派生类型是为每个在列表中的对象,所以我可以投他们回到自己的派生类型或做一些其他的事情,让我可以到达每个派生类型的特定的不同属性?

谢谢!

5 个答案:

答案 0 :(得分:8)

您可以使用LINQ过滤您正在寻找的类型

animals.Friends = new List<Animal> { new Kangaroo(), new Bird() };
foreach ( var kangaroo in animals.Friends.OfType<Kangaroo>()) {
  kangaroo.Hop();
}

答案 1 :(得分:2)

尝试投射它:

var friendBird = friend as Bird;
if (friendBird != null)
{
    // It's a bird, so do something with it
)

答案 2 :(得分:1)

您可以使用typeof获取实际类型,或使用isas运算符来测试和选择投射:

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条款,如果您正在测试可能在层次结构中的类型,这可能会导致错误,例如,如果您同时拥有Kangaroo和Marsupial子句,那么您可能不希望两者都有被执行!)

您也可以使用is运算符执行此操作,该运算符看起来更好,但会让FxCop哭:

foreach (Animal a in Friends)
{
  if (a is Kangaroo)
  {
    ((Kangaroo)a).JumpAround();
  }
}

顺便说一句,顺便说一句,您可能希望寻找机会在Animal上放置虚拟方法并以多态方式实现该方法,而不是使用怪物if语句导致与特定方法的脆弱耦合派生类的集合。

答案 3 :(得分:0)

使用'is'关键字。

如果(动物是鸟)   ...

答案 4 :(得分:0)

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