How to downcast objects at run-time?

For example, ControlsCollection class returns Control type objects. I would like to access properties of TextBox and DropDownList type objects. In this case that would be Text and SelectedIndex respectively. So far I used casting at design-time, but I had to know what object types will be stored in the collection in advance.

It is not always possible to know what type of object will be stored in a collection at a run-time. What is a convinent way to downcast objects dynamically at run-time? If I use GetType() method I can get its Type, but how to downcast it from there and access a derived class object members?

The problem extends with method definitions. If a parameter is of a base class type it accepts derived class objects. But how to access derived class object members within the method that is passed as a parameter of a base class type. Of course, the assumption is that you do not know what subclass objects will be passed at the run-time.

What is the best way to deal with this type of downcasting?

Comments

  • Maybe using the "is" and "as" operators would help.

    Basically, you will be creating a big if/else if/else block, something like:

    [code]
    TextBox tb = new TextBox();
    DropDownList ddl = new DropDownList();
    DoSomethingWith(tb);
    DoSomethingWith(ddl);
    [/code]
    and
    [code]
    void DoSomethingWith(Control ctrl)
    {
    // is it a text box?
    if(ctrl is TextBox)
    {
    // yes,
    TextBox tb = (TextBox)ctrl;
    // do something with tb
    }
    // is it a drop down list?
    else if(ctrl is DropDownList)
    {
    // yes,
    DropDownList ddl = (DropDownList)ctrl;
    // do something with ddl
    }
    // etc
    else
    {
    }
    }
    [/code]
    You need to make sure you check from bottom to top if your classes is part of a class hierarchy, that's if you do something like:
    [code]
    // base, derived classes
    class Base {};
    class Derived : Base {};
    Base b = new Base();
    DoSomething(b);
    Derived d = new Derived();
    DoSomething(d);

    // and this code
    void DoSomething(object obj)
    {
    if(obj is Base)
    {
    Base b = (Base)obj;
    }
    else if(obj is Derived)
    {
    // will never get executed! since obj is base always
    Derived d = (Derived)obj;
    }
    }
    [/code]

    The "as" operator can be used to write the first DoSomething like this:
    [code]
    void DoSomethingWith(Control ctrl)
    {
    // is it a text box?
    TextBox tb = ctrl as TextBox;
    if(tb != null)
    {
    // yes, do something with tb
    }
    else
    {
    // is it a drop down list?
    DropDownList ddl = ctrl as DropDownList;
    if(ddl != null)
    {
    // yes, do something with ddl
    }
    else
    {
    // etc.
    }
    }
    }
    [/code]
    As you can see from the code, "as" returns null if the cast does not work (much like C++ dynamic_cast).

    : For example, ControlsCollection class returns Control type objects. I would like to access properties of TextBox and DropDownList type objects. In this case that would be Text and SelectedIndex respectively. So far I used casting at design-time, but I had to know what object types will be stored in the collection in advance.
    :
    : It is not always possible to know what type of object will be stored in a collection at a run-time. What is a convinent way to downcast objects dynamically at run-time? If I use GetType() method I can get its Type, but how to downcast it from there and access a derived class object members?
    :
    : The problem extends with method definitions. If a parameter is of a base class type it accepts derived class objects. But how to access derived class object members within the method that is passed as a parameter of a base class type. Of course, the assumption is that you do not know what subclass objects will be passed at the run-time.
    :
    : What is the best way to deal with this type of downcasting?
    :
    :

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

In this Discussion