这是一个noob问题 - 我仍然是C#和泛型的新手,对谓词,委托和lambda表达式来说是全新的......
我有一个“查询”课程,其中包含另一个名为“车辆”的课程的通用列表。我正在构建代码以从父查询添加/编辑/删除车辆。目前,我特别关注删除。
从我到目前为止所读到的内容看来,我可以使用Vehicles.RemoveAll()删除具有特定VehicleID的项目或具有特定EnquiryID的所有项目。我的问题是理解如何提供.Remove所有正确的谓词 - 我看到的例子过于简单化(或者由于我对谓词,委托和lambda表达式缺乏了解,我可能过于简单化了。)
因此,如果我有一个List<Of Vehicle> Vehicles
,其中每辆车都有EnquiryID
,我如何使用Vehicles.RemoveAll()
删除给定EnquiryID的所有车辆?
我知道有几种方法,所以我很想听到方法之间的差异 - 尽管我需要一些工作,这也是一个学习练习。
作为补充问题,通用列表是这些对象的最佳存储库吗?我的第一个倾向是收藏品,但看起来我已经过时了。当然,仿制药似乎更受欢迎,但我对其他替代品感到好奇。
答案 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的车辆的数量。