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

本文关键字:处理 谓词 输入 bindinglist removeall 扩展 创建 何创建 一个 方法 | 更新日期: 2023-09-27 18:01:15

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

效果很好,但是绑定列表没有这个方法。我如何为bindinglist创建一个扩展方法,该方法将谓词作为输入,并像List的罐装removeall一样神奇

感谢

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

正如我在评论中所说,扩展方法没有魔力,只需像正常编写一样编写代码,只需将其放入静态类中的静态方法中,并使用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(N2((,因为每个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(N2(,因为每个RemoveAt()都必须移动被删除的项目之后的所有项目。

我想说:

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((的性能似乎非常接近(事实上,根据具体情况,两者都可以更快(,以至于可以忽略不计:我需要迭代和计数。什么是最快的或首选的:ToArray((或ToList((?