2011-07-06 46 views
2
myGenericList.RemoveAll(x => (x.StudentName == "bad student")); 

工程很好,但綁定列表沒有此方法。如何創建爲需要輸入一個謂語,確實神奇像列表中的罐裝removeall過的的BindingList的擴展方法如何創建擴展方法來處理bindinglist.removeall與謂詞輸入

三江源

+0

擴展方法將執行與手動完成相同的操作。 – svick

+0

該死的。我希望有一些很酷的lambda技巧或什麼的。任何人 ? – Gullu

+0

本身並不是一個lambda技巧,lambdas只會幫助你處理謂詞。至於Linq,您可以使用Linq來幫助選擇,但Linq方法不會真正改變IEnumerable 序列。所以你需要一個選擇組合,然後刪除。感謝svick和詹姆斯,感謝 –

回答

5

就像我在評論中說,在擴展中沒有魔法ñ方法,只寫代碼的方式,如果你寫的一般,只是把它放在一個靜態方法在靜態類和使用this關鍵字:

public static void RemoveAll<T>(this BindingList<T> list, Func<T, bool> predicate) 
{ 
    foreach (var item in list.Where(predicate).ToArray()) 
     list.Remove(item); 
} 

你必須使用ToArray()(或ToList()) ,因爲Where()很懶,只在需要時枚舉集合,並且不能枚舉更改的集合。

儘管此解決方案相當慢(O(N )),因爲每個Remove()都必須查看集合才能找到要刪除的正確項目。我們可以做的更好:

public static void FastRemoveAll<T>(this BindingList<T> list, Func<T, bool> predicate) 
{ 
    for (int i = list.Count - 1; i >= 0; i--) 
     if (predicate(list[i])) 
      list.RemoveAt(i); 
} 

它使用的事實,我們可以得到第i個在固定時間內的項目,所以整個方法是O(N)。迭代更容易反寫,因此我們尚未考慮的項目索引不會改變。

編輯:實際上第二溶液仍然是O(N 2 ),因爲每RemoveAt()必須移動已刪除的一個之後的所有項目。

+0

真實的,無論他們以相同的數量級執行。我們兩個解決方案中的每一個的linq表達式對於不瞭解正在發生的新手開發人員來說可能更易於維護。 –

1

我會說:

public static class BindingListExtensions 
{ 
    public static void RemoveAll<T>(this BindingList<T> list, Func<T, bool> predicate) 
    { 
     // first check predicates -- uses System.Linq 
     // could collapse into the foreach, but still must use 
     // ToList() or ToArray() to avoid deferred execution      
     var toRemove = list.Where(predicate).ToList(); 

     // then loop and remove after 
     foreach (var item in toRemove) 
     { 
      list.Remove(item); 
     } 
    } 
} 

而對於那些感興趣的細節,似乎ToList()和ToArray()是如此接近相同的性能(實際上每個可以更快的基礎上的情況),以至於可以忽略不計:I need to iterate and count. What is fastest or preferred: ToArray() or ToList()?

+0

使用'ToArray()'可以輕鬆避免第一個'foreach'。 – svick

+0

的確如此,當我輸入並更新它時,我想到了這一點。儘管使用了ToList()。 –

+0

是的,但我認爲'ToArray()'在這裏稍微更清楚一點,因爲您不會改變結果,並且數組比列表更不易變。 – svick