2013-04-17 107 views
0

我们有几种不同的数据类型,它们都共享一个特定的基类。我们还有一个List<BaseClass>,其中包含这些子类对象的随机集合,没有特定的顺序。如何使用LINQ将基类对象集合转换为其各自子类的过滤列表?

使用LINQ/Lambda表达式,我们正在试图提取每个单独的子类型,由具体的子类的属性排序,然后将其存储在List<SubclassType>

这里一个强类型的值是什么我目前在做,但不是LINQ专家,我有一种感觉,有一种更简单的方法来实现这一点。 (我越来越觉得我在哪里,选择在某种程度上冗余,并导致更比需要经过收集,但我可能是错的。)

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(); 

不过,我有我做了一个感觉这些比他们需要的要复杂得多。这是最有效的方法吗?

+0

谢谢,@Anthony!我感觉这很容易。但我不能投票给你的答案,因为它不是'答案'! – MarqueIV

+0

啊!你现在做到了。您的评论已消失,并有新的答案!不会让我接受它(必须等待10分钟),但你得到了答案。 :) – MarqueIV

回答

5

你想利用OfType<T>过滤你的混合序列,并提取结果作为所需的类型。

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

,你可能希望探索一种类似的方法是Cast<T>,代替过滤和转换,简单地转换(并抛出如果转换不成功)。如果你知道,那么使用这种方式,所有较小派生类型的序列中的项目实际上是派生类型更多的。否则,如果您的意图是过滤可能混合的序列,请使用先前显示的方法(并且这肯定是您将要做的,考虑到您的问题)。

+0

虽然......快速的问题,你可以过滤在子类的属性上,或者你必须添加一个单独的'Where'子句后,导致另一个通过结果?我们现实世界的用例实际上是我们只想要某些具有特定属性集的SubItemX对象。 (例如,只有具有subItemX.foo == 1的SubItemX对象才是有用的东西。) – MarqueIV

+0

正如您可以使用OrderBy一样,您还可以在OfType的结果序列上应用Where或任何其他适用的扩展方法。请记住,在评估中这是懒惰的,在Where过滤器也开始生效之前,整个序列不需要通过OfType进行过滤。很显然,在OrderBy需要评估的时候,它需要完成所有的过滤,但是OfType和Where将很好地链接在一起。 –

+1

想象一下:“从allItems中获取第一个项目,它是一个SubItemX吗?好,现在item.foo等于1?好,我想要它,现在看看allItems中的第二个项目。合理?我在评论,因为我在解释你的问题,因为你不确定是否所有的序列都通过OfType过滤,只有这些结果中的所有*都通过Where。假设您使用标准的Linq-to-Objects提供程序,这不是如何实现的。 –

相关问题