2011-08-04 88 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>您可以進一步篩選/過程。