How can I downcast a list of objects so that each of the objects in the list is downcast to an object of a derived class?
This is the scenario.
I have a base class with a List
of base items, and two classes inheriting from it:
public class BaseClass
{
public List<BaseItem> items;
protected BaseClass()
{
// some code to build list of items
}
}
public class DerivedClass : BaseClass
{
public DerivedClass : base() {}
}
public class AnotherDerivedClass : BaseClass
{
public AnotherDerivedClass : base() {}
}
public class BaseItem {}
public class DerivedItem : BaseItem {}
public class AnotherDerivedItem : BaseItem {}
The idea is to not have to duplicate the code needed to build the list of items. The BaseItem
has all the basic stuff I need, and I can always downcast BaseItem
to one of the derived items.
The problem arises when I have a list of them. The List
of BaseItem
is declared in the BaseClass
because all the derived classes have to have it. But when accessing it at runtime I can't seem to be able to downcast to the derived class.
Downcasting is not allowed without an explicit type cast. The reason for this restriction is that the is-a relationship is not, in most of the cases, symmetric. A derived class could add new data members, and the class member functions that used these data members wouldn't apply to the base class.
Downcasting is done using cast operator. To downcast an object safely, we need instanceof operator. If the real object doesn't match the type we downcast to, then ClassCastException will be thrown at runtime.
Downcasting is useful when the type of the value referenced by the Parent variable is known and often is used when passing a value as a parameter. In the below example, the method objectToString takes an Object parameter which is assumed to be of type String.
Downcasting is considered a code smell, and it is recommended to consider your design choices if you need to perform downcasting. You need to perform downcasting when you need to call subtype specific behaviour and all you have is an object of supertype.
Using LINQ:
var baseList = new List<BaseClass>();
var derivedList = baseList.Cast<DerivedClass>();
Note: Having to downcast usually is a 'smell' and indicates that the inheritance hierarchy is wrong, or wrongly implemented. The idea of having a base class is that you can treat all subclasses as superclass without having to downcast to individual subclass types.
Instead of Cast
you might want to use OfType
to 'fish out' certain derived classes from a collection of superclasses. But again, there should be no need to do that.
Ask yourself, why you need to have a subclass - maybe you need to move some functionality to base class?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With