Search code examples
c#typespolymorphismradix

How can I store and use an array of different types derived from a common base type?


The title may need a bit of explanation, so here's what i'm trying to do:

  • Common base type for UI elements, e.g. BasePanel
  • More specialised elements can be defined, derived from BasePanel. For example, buttons and textboxes.
  • A list of elements will be stored (of type BasePanel, so that specialised ones can be stored)
  • This list will be looped through each frame and drawn (ignoring optimisation at the moment)

Example usage:

class UIButton : BasePanel
{
    public override void Draw(blah)
    {
        // Specialised drawing code
    }
}

foreach (BasePanel Element in StoredElements)
{
    Element.Draw(blah);
}

The problem with this is that it won't run the specialised code; it will just run the BasePanel code. How can I improve this so that it will run the specialised code instead? Could I store the type of the element on the BasePanel, and then cast to it at runtime?

I've tried storing the BasePanel in a Container class which stores the original type, but I can't access the method - for example:

foreach(ElementContainer Container in StoredElements)
{
    Type t = Container.OriginalType;
    object el = Container.Element;

    Convert.ChangeType(el, t); //Can't use the returned object!

    t Element = (t)Convert.ChangeType(el, t); //This would be perfect, but it doesn't work.
}

Thanks for any help. This has made my brain explode.


Solution

  • It works 100% for me with the following code:

    class BasePanel
    {
        public virtual void Draw(string blah)
        {
            Console.WriteLine("Base: " + blah);
        }
    }
    
    class UIButton : BasePanel
    {
        public override void Draw(string blah)
        {
            Console.WriteLine("UIButton: " + blah);
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            List<BasePanel> list = new List<BasePanel>();
    
            list.Add(new BasePanel());
            list.Add(new UIButton());
            list.Add(new BasePanel());
            list.Add(new UIButton());
            list.Add(new UIButton());
    
            foreach (var b in list)
            {
                b.Draw("just a string");
            }
        }
    }
    

    What is wrong with yours comes from your drawing code/logic.