Question

This may seem kind of "homework-ish" and/or trivial, but it is for a real business purpose; it's just the easiest way I could think of to explain what I'm conceptually trying to do.

Suppose I have an Animal class, and some other classes (Bird, Cat, Kangaroo). Each of these inherits from Animal.

Animal might look like this:

public class Animal
{
    public Animal()
    {

    }

    public string Name { get; set; }
    public string AnimalType { get; set; }
    public List<Animal> Friends { get; set; }
}

Kangaroo might look like this:

public class Kangaroo : Animal
{
    public Kangaroo()
    {

    }

    public int TailLengthInches { get; set; }
}

Suppose the kangaroo has two friends, a bird and a cat. How could I add those to the list of "Animal" friends (as type Animal), but preserve the ability to access the properties of the derived classes? (as in, I still need to be able to work with properties that are specific to the type of animal, like FeatherColor for the bird, for example, even though they will be considered just "animals".

The reason I am trying to do this is that when I later get the list of the animal's "friends", it is vital that I know what type of animal the friend is. Depending on the animal type (whether it is a bird, cat, etc) I want to do something different (show a different template in on an ASP.NET page, actually, but I don't need help with that specifically).

I guess it boils down to this...if I have a list of Animal, how do I know what the derived type was for each of the objects in the list, so I can cast them back to their derived type or do something else that allows me to get to the specific, different properties that are on each derived type?

Thanks!

Was it helpful?

Solution

You can use LINQ to filter on the type you're looking for

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

OTHER TIPS

Try casting it:

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

You can use typeof to get the actual type, or use the is or as operators to test and optionally cast:

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

(I haven't used else clauses here, which could cause errors if you're testing against types which might be in a hierarchy e.g. if you had both Kangaroo and Marsupial clauses, you probably would NOT want both to be executed!)

You can also do this with the is operator, which looks nicer, but will make FxCop cry:

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

In general, by the way, you probably want to look for an opportunity to put a virtual method on Animal and implement that method polymorphically, rather than having monster if-statements which result in brittle coupling to a specific set of derived classes.

Use the 'is' keyword.

if (animal is Bird) ...

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");
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top