2008-10-10 46 views
11

假設我的對象處於完美工作狀態(即TDD讓我認爲它們工作正常)。以編程方式構建LINQ查詢,而無需本地變量欺騙我

我有這樣創建(除縮進正確)的列表:

var result = from v in vendors 
      from p in v.Products 
      orderby p.Name 
      select p; 

這工作 - 我得到的所有產品全部供應商。

現在我有一個條件列表,由用戶在運行時建立。讓我們來運用它們:

foreach (Attribute a in requiredAttributes) 
{ 
    result = result.Where(p => p.Attributes.Contains(a)); 
} 

這可能是原始的,但我認爲它會起作用。但是,在這個foreach循環完成後,當枚舉「result」時,它將包含所有在其Attributes屬性(也是集合)中具有requiredAttributes集合的LAST屬性的產品。

對我來說,這個味道像「a」被每個行程通過循環覆蓋,只有最後一個適用。

不知何故向IEnumerable寫了一個名爲ContainsAll(IEnumerable)的擴展方法,或者是那種效果,我該如何實現我想要的,這基本上是一個邏輯AND,只給出那些具有所有必需屬性的產品?

+0

感謝傢伙 - 我給予Jon的「接受答案」,因爲它似乎可能更適合「一般」情況。但我肯定會檢查出奧默的建議,不知道你能做到這一點。投票給所有人。 :) – 2008-10-10 06:30:56

+0

解決此問題的新方法是僅使用C#5。另見[在foreach中使用變量在C#5中進行了更改?](http://stackoverflow.com/a/12112959/18192) – Brian 2016-01-15 14:38:38

回答

19

(編輯爲清楚起見。)

問題是foreach循環,並且「一個」可變正被捕獲,然後將實際上每次改變。這裏有一個修改,它將有效地爲循環的每次迭代引入一個「新」變量,並捕獲該新變量。

foreach (Attribute a in requiredAttributes) 
{ 
    Attribute copy = a; 
    result = result.Where(p => p.Attributes.Contains(copy)); 
} 

奧馬爾的解決方案是一種清潔的,如果你可以使用它,但是這可能會幫助,如果你真正的代碼實際上是更復雜的:)

編輯:有更多的問題this closures article - 向下滾動到「比較捕捉策略:複雜性與權力」。

7
var result = from v in vendors 
      from p in v.Products 
      where requiredAttributes.All(a => p.Attributes.Contains(a)) 
      orderby p.Name 
      select p; 

HTH。

5

我沒有編寫它,但改變

foreach (Attribute a in requiredAttributes){  
    result = result.Where(p => p.Attributes.Contains(a)); 
} 

foreach (Attribute a in requiredAttributes){  
    Attribute b = a; 
    result = result.Where(p => p.Attributes.Contains(b)); 
} 

應該修復它太,我認爲。