2011-08-04 51 views
12

我要寻找以下情况优雅的解决方案的倍数:联盟在C#中列出

我有一个包含像

class MyClass{ 
... 
public List<SomeOtherClass> SomeOtherClassList {get; set;} 
... 
} 

列表一类叫做Model第三类包含一个List<Myclass>这是我从外部操作的那个。

现在我想用一种方法来扩展Model类,该方法返回所有MyClass实例上的所有独特的SomeOtherClass实例。

我知道有Union()方法和foreach循环我可以很容易地解决这个问题,我真的这样做。但是,由于我对所有C#3 +特性都很陌生,因此我很好奇如何使用Linq或不使用Linq来实现更优雅。

我已经找到了一种方法,这似乎相当笨拙的我,但它的工作原理:

 List<SomeOtherClass> ret = new List<SomeOtherClass>(); 
     MyClassList.Select(b => b.SomeOtherClasses).ToList().ForEach(l => ret = ret.Union(l).ToList()); 
     return ret; 

注:b.SomeotherClasses属性返回List<SomeOtherClasses>

这段代码距离完美还有一段距离,因为我必须弄清楚使用C#3以及哪些不是最好的风格。所以,我列出了一些关于该片段的想法,我很乐意收到一些评论。除此之外,我很乐意听到一些评论如何进一步改进此代码。

  • 临时名单ret会一直在C#2也许做法的一部分,但它是正确的,我应该能够辞职此列表使用方法链接呢?或者我错过了这一点?
  • 是否真的需要使用中间体ToList()方法?我想要的是对选择的每个成员执行进一步的操作。
  • 那些ToList()操作的成本是多少?他们是不错的风格?必要?

谢谢。

+0

这里独特的含义是什么?我的意思是,你是否在你的'List '中存储了多个对同一个对象的引用? –

回答

25

您正在寻找SelectMany() + Distinct()

List<SomeOtherClass> ret = MyClassList.SelectMany(x => x.SomeOtherClasses) 
             .Distinct() 
             .ToList(); 

SelectMany()将压平的“名单表”到一个列表中,那么你可以随便挑出来的,而不是使用个人之间联盟在这列举了不同的条目子列表。

一般而言,您将希望避免使用Linq的副作用,您的原始方法是滥用此修改ret这不是查询的一部分。

ToList()是必需的,因为每个标准查询操作符返回一个新的枚举并且不修改现有的枚举,因此您必须将最终的枚举结果转换回列表。 ToList()的成本是枚举的完整迭代,在大多数情况下,可以忽略不计。当然,如果你的班级可以使用IEnumerable<SomeOtherClass>来代替,你根本不需要转换成列表。

+0

完美,这正是我所期待的。 它会解决问题,它也会删除中间的.ToList()步骤。谢谢,我今天学到了一些东西。星期五很好。 :-) –

0

你应该看看SelectMany。这样的事情应该生成你的“平”的文章:

MyClassList.SelectMany(b => b.SomeOtherClasses) 

它会返回一个IEnumerable<SomeOtherClass>您可以进一步筛选/过程。