如何创建一个扩展方法来处理带有谓词输入的bindinglist.removeall

时间:2011-07-06 15:18:32

标签: c# generics lambda extension-methods predicate

myGenericList.RemoveAll(x => (x.StudentName == "bad student"));

效果很好,但绑定列表没有此方法。我如何为绑定列表创建一个扩展方法,该方法将谓词作为输入,并像列表

的固定removeall一样发挥作用

三江源

2 个答案:

答案 0 :(得分:5)

就像我在评论中所说的那样,扩展方法没有神奇之处,只需像编写正常代码一样编写代码,只需将其放在静态类中的静态方法中并使用{{1}即可。 } keyword:

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()是惰性的,只在需要时枚举该集合,您无法枚举更改集合。

虽然这个解决方案很慢(O(N 2 )),因为每个Where()都必须查看集合才能找到要删除的正确项目。我们可以做得更好:

Remove()

这使用了我们可以在恒定时间内到达第i个项目的事实,因此整个方法是O(N)。迭代更容易向后写,因此我们尚未考虑的项目索引不会改变。

编辑:实际上第二个解决方案仍然是O(N 2 ),因为每个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); } 必须移动所有项目后移除的项目

答案 1 :(得分: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()? < / p>