Convert a List of BaseClass to a List of DerivedClass in C#

So there you are, you and your fantastic object-oriented design model. Abstracting away. Creating base classes and derived classes, and many tiers over each other. Now you start to deal with lists of these classes and you realize at some point you want to do some filtering. This situation comes up all the time for me, specifically when dealing with my derived classes. Here’s the scenario that I was in that required me to do some filtering and narrowing of my classes. I had a class diagram similar to something as basic as this:

BaseClass
Derived1 : BaseClass
Derived2 : BaseClass
Derived3 : BaseClass

We’re talking basic object-oriented design here. I had a special black box of sorts (not going to get into it…) that always required me to pass it a List<BaseClass>. It would then know how to deal with all of the sub-types. This black box would also return me a List<BaseClass> and I’d need to sort out the contents myself. This isn’t exactly anything special and its called covariance and contravariance. Say you wanted to take a List<BaseClass> and only want to really get a List<Derived1> from it. There are some options here. You can loop over all the object in the given list and create another list of just Derived1, in each iteration checking if the current object is Dervied1 and adding it to the return list. That’s old school. Another option (which I prefer) is to use the OfType<T> filtering extension method in LINQ to filter the list on a specific type. This is quite simple to use:

var foo = new List<Color>();
foo.Add(new Red());
foo.Add(new Red());
foo.Add(new Blue());
foo.Add(new Green());
foo.Add(new Blue());
foo.Add(new Green());
foo.Add(new Red());

// let's get back only the Reds. *drum roll*

foo.OfType<Red>(); // annnnd, done.

The OfType<T>() extension works by both narrowing a list from a BaseClass to a DerivedClass and widening it from a DerivedClass to a BaseClass as well:

var bar = new List<Red>();
bar.Add(new Red());
bar.Add(new Red());

bar.OfType<Color>(); // now its a List<Color> containing all Reds

More reading: Enumerable.OfType(Of TResult) Method

 

Mark Ursino

Mark is Sr. Director, CMS Practice Lead at Rightpoint and a Sitecore Technology MVP.

 

Leave a Reply

Your email address will not be published. Required fields are marked *