开发者

How to create an extension method to handle bindinglist.removeall with predicate input

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()?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜