List <object> .RemoveAll - 如何创建适当的Predicate </object>

时间:2010-06-18 12:12:13

标签: c# generics delegates lambda predicate

这是一个noob问题 - 我仍然是C#和泛型的新手,对谓词,委托和lambda表达式来说是全新的......

我有一个“查询”课程,其中包含另一个名为“车辆”的课程的通用列表。我正在构建代码以从父查询添加/编辑/删除车辆。目前,我特别关注删除。

从我到目前为止所读到的内容看来,我可以使用Vehicles.RemoveAll()删除具有特定VehicleID的项目或具有特定EnquiryID的所有项目。我的问题是理解如何提供.Remove所有正确的谓词 - 我看到的例子过于简单化(或者由于我对谓词,委托和lambda表达式缺乏了解,我可能过于简单化了。)

因此,如果我有一个List<Of Vehicle> Vehicles,其中每辆车都有EnquiryID,我如何使用Vehicles.RemoveAll()删除给定EnquiryID的所有车辆?

我知道有几种方法,所以我很想听到方法之间的差异 - 尽管我需要一些工作,这也是一个学习练习。

作为补充问题,通用列表是这些对象的最佳存储库吗?我的第一个倾向是收藏品,但看起来我已经过时了。当然,仿制药似乎更受欢迎,但我对其他替代品感到好奇。

4 个答案:

答案 0 :(得分:84)

RemoveAll()方法接受Predicate<T>委托(直到此处没有新内容)。谓词指向一个简单返回true或false的方法。当然,RemoveAll将从集合中删除所有T个实例,这些实例在应用了谓词的情况下返回True。

C#3.0允许开发人员使用多种方法将谓词传递给RemoveAll方法(而不仅仅是这个...)。您可以使用:

Lambda表达式

vehicles.RemoveAll(vehicle => vehicle.EnquiryID == 123);

匿名方法

vehicles.RemoveAll(delegate(Vehicle v) {
  return v.EnquiryID == 1;
});

正常方法

vehicles.RemoveAll(VehicleCustomPredicate);
private static bool
VehicleCustomPredicate (Vehicle v) {
    return v.EnquiryID == 1; 
}

答案 1 :(得分:15)

T中的谓词是一个代理,它接受一个T并返回一个bool。 List&lt; T&gt; .RemoveAll将删除列表中调用谓词的所有元素返回true。提供简单谓词的最简单方法通常是lambda expression,但您也可以使用anonymous methods或实际方法。

{
    List<Vehicle> vehicles;
    // Using a lambda
    vehicles.RemoveAll(vehicle => vehicle.EnquiryID == 123);
    // Using an equivalent anonymous method
    vehicles.RemoveAll(delegate(Vehicle vehicle)
    {
        return vehicle.EnquiryID == 123;
    });
    // Using an equivalent actual method
    vehicles.RemoveAll(VehiclePredicate);
}

private static bool VehiclePredicate(Vehicle vehicle)
{
    return vehicle.EnquiryID == 123;
}

答案 2 :(得分:6)

这应该有用(enquiryId是您需要匹配的ID):

vehicles.RemoveAll(vehicle => vehicle.EnquiryID == enquiryId);

这样做是将列表中的每个车辆传递给lambda谓词,评估谓词。如果谓词返回true(即vehicle.EnquiryID == enquiryId),则当前车辆将从列表中删除。

如果您知道集合中对象的类型,那么使用泛型集合是一种更好的方法。它避免了从集合中检索对象时的转换,但如果集合中的项是值类型(这可能会导致性能问题),也可以避免装箱。

答案 3 :(得分:1)

我想解决迄今为止没有答案的事情:

  

从我到目前为止所读到的内容看来,我可以使用   Vehicles.RemoveAll()删除具有特定VehicleID的项目。   作为一个[原文如此]的补充问题,Generic列表是这些对象的最佳存储库吗?

假设VehicleID是唯一的顾名思义,当你获得大量车辆时,列表是一种非常低效的存储方式,因为删除(以及其他方法,如Find)仍然是O (N)。看看HashSet<Vehicle>,它使用O(1)删除(以及其他方法):

int GetHashCode(Vehicle vehicle){return vehicle.VehicleID;}
int Equals(Vehicle v1, Vehicle v2){return v1.VehicleID == v2.VehicleID;}

删除具有特定EnquiryID的所有车辆仍然需要以这种方式迭代所有元素,因此您可以考虑返回GetHashCode的{​​{1}},具体取决于您经常执行的操作。如果很多车辆共享相同的EnquiryID,那么这会产生许多碰撞的缺点。

在这种情况下,一个更好的选择是制作一个{EnverIDs映射到车辆的EnquiryID,并在添加/移除车辆时保持最新状态。然后从HashSet中移除这些车辆是O(m)操作,其中m是具有特定EnquiryID的车辆的数量。