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

你说的曾经没有我的故事 提交于 2019-12-11 05:38:13

问题


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.


回答1:


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.




回答2:


it looks like your example should work, but you could try extracting the Draw method (and any others you need for polymorphism) into an Inerface, then implementing the interface in each of the classes you want in the list.




回答3:


As DarkSquirrel stated, you can declare the parent class's functions as virtual. This should allow your code to run the specialized code




回答4:


What specialized type are you trying to execute

if you have

class Bar {
  public virtual void Draw() {
    DO STUFF!
  } 
}

class Foo : Bar {
  override public virtual Draw() {
    DO MORE STUFF!
  }
}

then somewhere in your code

Bar[] data = new Bar[] { new Foo(), new Bar()};
foreach (Bar elem in data) {
  elem.Draw();
}

The first elem will execute the overriden code in Foo for the first elem and the code in Bar for the second. Even if you cast an item down the code executed in the methods will still be the code in original object (and elem.GetType() will return Foo for a Foo type.



来源:https://stackoverflow.com/questions/6391501/how-can-i-store-and-use-an-array-of-different-types-derived-from-a-common-base-t

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!