myGenericList.RemoveAll(x => (x.StudentName == "bad student"));
开发者_运维知识库Works great, but a bindinglist does not have this method. How can I create an extension method for the bindinglist that takes as input a predicate and does the magic like the canned removeall for List
thankyou
Like I said in a comment, there is no magic in extension methods, just write the code the same way as if you wrote it normally, just put it in a static method in a static class and use the this
keyword:
public static void RemoveAll<T>(this BindingList<T> list, Func<T, bool> predicate)
{
foreach (var item in list.Where(predicate).ToArray())
list.Remove(item);
}
You have to use ToArray()
(or ToList()
), because Where()
is lazy and only enumerates the collection when needed and you can't enumerate changing collection.
Although this solution is quite slow (O(N2)), because every Remove()
has to look through the collection to find the correct item to remove. We can do better:
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);
}
This uses the fact that we can get to i-th item in constant time, so the whole method is O(N). The iteration is easier to write backwards, so that indexes of items we have yet to consider aren't changing.
EDIT: Actually the second solution is still O(N2), because every RemoveAt()
has to move all the items after the one that was removed.
I'd say:
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);
}
}
}
And for those interested in the minutia, seems ToList() and ToArray() are so close to the same performance (and in fact each can be faster based on the circumstance) as to be negligible: I need to iterate and count. What is fastest or preferred: ToArray() or ToList()?
精彩评论