neggenbe
neggenbe

Reputation: 1885

Containers of inherited objects

I have a simple class structure

abstract class A {
List<A> containerList;
...
}
class B : A {....}
class C : A {....}

I make sure that the containerList contains only elements of class B or C (as the list is filled in these child classes and A is abstract).

Now, I'd like, somehow, to have a base property / method in A which would cast itself to whatever the real type of the object is, i.e. B or C. Having an abstract method is just fine, but it is important to get a Collection<T> of B or C objects, as I have bindings that will depend on it.

Upvotes: 1

Views: 51

Answers (3)

Ren&#233; Vogt
Ren&#233; Vogt

Reputation: 43886

You could use generics like that (though it looks a little strange):

public abstract class A<T> where T : A<T>
{
    protected List<A<T>> containerList;
    public Collection<T> ContainerList
    {
        get { return new Collection<T>(containerList.OfType<T>().ToList()); }
    }
}

public class B : A<B>
{
   //...
}

public class C : A<C>
{
   //...
}

But since containerList should only contain elements of the derived type, you can make it completely generic too like that:

protected List<T> containerList;

and could ommit the OfType() call:

public Collection<T> ContainerList { get { return new Collection<T>(containerList); }}

One drawback is that someone could have the idea to make a class D like that:

public class D : A<B>
{}

and would now have a class D with a ContainerList of type Collection<B>. But if it's that what he wants...

Upvotes: 2

D Stanley
D Stanley

Reputation: 152566

Now, I'd like, somehow, to have a base property / method in A which would cast itself to whatever the real type of the object is, i.e. B or C.

I think you're mixing casting and converting. A Cast is a compile-time construct that just determines how methods and properties are bound at compile-time. It does not change the underlying object.

There's no conversion necessary because the object is already either a B or a C - since A is abstract you can't have an object that is actually an A.

So a method that returns the underlying collection as either a collection of Bs or Cs would just be:

public IEnumerable<B> GetBs()
{
    return containerList.OfType<B>();
}

public IEnumerable<C> GetCs()
{
    return containerList.OfType<C>();
}

If you want one generic method where the caller determines the type, you can do:

public IEnumerable<T> GetTs<T>() where T:A
{
    return containerList.OfType<T>();
}

Upvotes: 2

Jeremy Kato
Jeremy Kato

Reputation: 467

Instead of casting the objects in the list, you could use the is keyword (documentation link). When you need to operate on your List, just ask before doing your operation if (containerList[i] is B).

Upvotes: 0

Related Questions