Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can you use LINQ to cast from a collection of base class objects to a filtered list of their respective subclasses?

Tags:

c#

lambda

linq

We have several different data types that all share a particular base class. We also have a List<BaseClass> that contains a random collection of those subclass objects in no particular order.

Using Linq/Lambda expressions, we're trying to extract each individual subclass type, ordered by a property of that specific subclass, then store it in a strongly-typed value of List<SubclassType>

Here's what I'm currently doing, but not being a LINQ expert, I have a feeling there's a much easier way to achieve this. (I'm getting the feeling my Where and Select are somehow redundant and cause more-than-needed passes over the collection, but I could be wrong.)

class baseItem{}

class subItemX : baseItem
{
    public int XSortValue{ get; set; }
}

class subItemY : baseItem
{
    public int YSortValue{ get; set; }
}

List<MyBaseClass> allItems = GetAllItems(); // Random collection of subclass objects.

// Is there an easier/less verbose way to achieve these two?
List<SubItemX> xItemsOnly = allItems
    .Where(baseItem => baseItem is SubItemX)
    .Select(baseItem => baseItem as SubItemX)
    .OrderBy(subItemX => subItemX.XSortValue)
    .ToList();

List<SubItemY> yItemsOnly = allItems
    .Where(baseItem => baseItem is SubItemY)
    .Select(baseItem => baseItem as SubItemY)
    .OrderBy(subItemY => subItemY.YSortValue)
    .ToList();

However, I have a feeling I've made these much more complicated than they need to be. Is this the most efficient way?

like image 739
Mark A. Donohoe Avatar asked Oct 25 '25 07:10

Mark A. Donohoe


1 Answers

You want to utilize OfType<T> to filter your mixed sequence and extract your results as the desired type.

var xItemsOnly = allItems.OfType<SubItemX>().OrderBy(s => s.XSortValue).ToList();

A similar method that you may wish to explore is Cast<T> that instead of filtering and converting, simply converts (and throws if a conversion does not succeed). Use this if you know all of the items in a sequence of a lesser derived type are actually of the more derived type. Otherwise, if your intent is to filter a possibly-mixed sequence, use the OfType<T> method previously displayed (and that is certainly what you would do, given your question).

like image 145
Anthony Pegram Avatar answered Oct 27 '25 20:10

Anthony Pegram



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!