【问题标题】:Identifying derived types from a list of base class objects从基类对象列表中识别派生类型
【发布时间】:2011-01-05 16:43:01
【问题描述】:

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

假设我有一个 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 页面上显示不同的模板,但我不需要专门的帮助)。

我想这可以归结为...如果我有一个 Animal 列表,我怎么知道列表中每个对象的派生类型是什么,所以我可以将它们转换回它们的派生类型或做一些其他的事情来让我获得每个派生类型上特定的不同属性吗?

谢谢!

【问题讨论】:

  • 提示:要让代码正确显示,请使用编辑器中的 101010 按钮(或缩进四个空格)。

标签: c# class inheritance types derived


【解决方案1】:

您可以使用 LINQ 过滤您要查找的类型

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

【讨论】:

  • 这是一种非常优雅的处理方式。谢谢!
【解决方案2】:
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");
}

【讨论】:

    【解决方案3】:

    使用“是”关键字。

    如果(动物是鸟) ...

    【讨论】:

      【解决方案4】:

      您可以使用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 语句派生类。

      【讨论】:

        【解决方案5】:

        尝试投射它:

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

        【讨论】:

        • +1 用于使用as 关键字来避免is 关键字涉及的双重转换,然后再转换对象。
        • 由于 C# 7.0 使用 is 现在更好:)
        猜你喜欢
        • 2014-04-15
        • 2012-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-10
        • 2015-05-23
        相关资源
        最近更新 更多