2015-09-22 19 views
0

項目我有被這些線引起我的代碼中的錯誤:排除用在哪裏,項目參考並不總是工作

var itemToExclude = _myList.First(); 
var nextList = _myList.Where(i => i != itemToExclude); 

其中itemToExclude仍然存在於nextList。 我通過使用Skip(1)而不是第二行來解決它,但是可能導致原始代碼無法工作?

使用的功能yield return這可能與它有關。

itemsToExclude是用類似

class RemainingItems 
{ 
    private readonly IEnumerable<MyObject> _myObjects; 
    public IEnumerable<MyObject> MyObjects { get { return _myObjects; } } 

    private readonly int _remaining; 
    public int Remaining { get { return _remaining; } } 

    public RemainingItems(IEnumerable<MyObject> myObjects, int remaining) 
    { 
     _myObjects = myObjects; 
     _remaining = remaining; 
    } 
} 
+0

因爲我不明確,你可能必須重寫Equals運算符,以便成功比較where子句中的兩個實體,雖然在匹配列表元素(複雜與否)時我不必這樣做。 – Tommy

+0

itemToExclude的類型是什麼? – Hogan

+0

也許是一種不能支持*反身性的'Equals'方法? –

回答

3

因爲myList通過產量的方法提供它會在您每次遍歷列表時,重建項目只讀屬性的類。

  1. 第一次迭代將_myList.First()
  2. 啓動第二次迭代將_myList.Where(...)

然後你開始:如果你不留意,它會在每個迭代上創建新的對象將對象與!=之間的差異進行比較,當兩個引用指向同一個對象(不考慮對象的實際內容)時,該值僅計算爲false。如上所述,yield-method可能會在每次迭代中創建新對象,因此!=將始終爲真。

有幾種可能的解決方案:

  • 使用.Skip(1)
  • 名單上使用.ToArray(),所以該列表將只創建一次。
  • 使用正確實施.Equals()方法

每個解決方案都有其權衡。

+0

「yield」的對象不會被重新創建......注意yield會返回引用。 –

+0

是的,並且通常人們會編寫像'yield return new Thingy(){...}'這樣的代碼。這意味着每次迭代你都會得到新的/不同的對象。 – Simon

+0

是真的,但我相當確信'.Where'和'.Skip'不會創建新對象... –