在C#中联合多个列表

Dr.*_*lch 13 c# linq extension-methods list

我正在为以下情况寻找一个优雅的解决方案:

我有一个包含List的类

class MyClass{ 
...
 public List<SomeOtherClass> SomeOtherClassList {get; set;}
...
}
Run Code Online (Sandbox Code Playgroud)

第三类叫做Model持有List<Myclass>一个我从外部操作的那个.

现在我想用一个方法扩展Model类,该方法返回所有MyClass实例上的所有唯一SomeOtherClass实例.

我知道有Union()方法和foreach循环我可以很容易地解决这个问题,我实际上做了.但是,由于我是所有C#3 +功能的新手,我很好奇如何在有或没有Linq的情况下更优雅地实现这一点.

我找到了一种方法,对我来说似乎相当笨拙,但它有效:

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

注意:该b.SomeotherClasses属性返回一个List<SomeOtherClasses>.

这段代码远非完美,而且有些问题来自于我必须弄清楚什么是使用C#3的好风格,什么不是.所以,我提出了一个关于该片段的小清单,我很乐意得到一些评论.除此之外,我很高兴听到一些评论如何进一步改进此代码.

  • 临时列表ret可能是C#2中的一种方法的一部分,但是我应该能够使用方法链来重新签名这个列表是否正确?或者我错过了这一点?
  • 是否真的需要使用中间ToList()方法?我想要的只是对选择中的每个成员执行进一步操作.
  • 那些ToList()操作的成本是多少?他们风格好吗?必要?

谢谢.

Bro*_*ass 28

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

List<SomeOtherClass> ret =  MyClassList.SelectMany( x => x.SomeOtherClasses)
                                       .Distinct()
                                       .ToList();
Run Code Online (Sandbox Code Playgroud)

SelectMany() 将"列表列表"压缩到一个列表中,然后您可以选择此枚举中的不同条目,而不是使用各个子列表之间的联合.

一般来说,你会希望避免使用Linq的副作用,你的原始方法有点滥用我的修改ret,这不是查询的一部分.

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