最佳实践 - 从C#中的泛型集合中删除项目

时间:2009-03-13 21:30:06

标签: c# generics .net-3.5

我在Visual Studio 2008中使用C#和.NET 3.5。

我有一个通用字典,它将事件类型映射到通用订阅者列表。订阅者可以订阅多个活动。

private static Dictionary<EventType, List<ISubscriber>> _subscriptions;

要从订阅列表中删除订阅者,我可以使用这两个选项中的任何一个。

选项1:

ISubscriber subscriber;  // defined elsewhere
foreach (EventType event in _subscriptions.Keys) {
    if (_subscriptions[event].Contains(subscriber)) {
        _subscriptions[event].Remove(subscriber);
    }
}

选项2:

ISubscriber subscriber;  // defined elsewhere
foreach (EventType event in _subscriptions.Keys) {
    _subscriptions[event].Remove(subscriber);
}

我有两个问题。

首先,注意选项1在删除项目之前检查是否存在,而选项2使用强力删除,因为Remove()不会抛出异常。在这两个中,这是首选的“最佳实践”方式吗?

第二,是否有另一种“更干净”,更优雅的方式来实现这一点,可能使用lambda表达式或使用LINQ扩展?我仍然适应这两个特征。

感谢。

修改

为了澄清,我意识到选项1和2之间的选择是速度(选项2)与可维护性(选项1)的选择。在这种特殊情况下,我不一定会尝试优化代码,尽管这肯定是值得考虑的。我想要了解的是,如果这样做有一个普遍成熟的做法。如果没有,您将在自己的代码中使用哪个选项?

5 个答案:

答案 0 :(得分:3)

选项1将比选项2慢.Lambda表达式和LINQ将更慢。我会使用HashSet<>代替List<>

如果您需要确认项目移除,则必须使用Contains

EDITED: 由于在lock语句中使用代码的概率很高,并且最佳做法是减少lock内的执行时间,因此应用选项2可能很有用。看起来没有最好的练习使用或不使用ContainsRemove

答案 1 :(得分:2)

Remove()方法'approches O(1)',当一个键不存在时就可以了。

但是否则:如果有疑问,请测量。获得一些时间并不困难......

答案 2 :(得分:1)

为什么在关注所有值时枚举键是什么?

foreach (List<ISubscriber> list in _subscriptions.Values)
{
    list.Remove(subscriber);
}

也就是说,Eric P建议的LINQ解决方案肯定更简洁。但是,性能可能是一个问题。

答案 3 :(得分:0)

我会选择第二种选择。 Contains()和Remove()都是O(n)方法,没有理由同时调用它们,因为Remove不会抛出。至少在方法2中,你只需要调用一个昂贵的操作,而不是两个。

我不知道有更快的方法来处理它。

答案 4 :(得分:0)

如果您想使用Linq来做这件事,我认为这样可行(未经测试):

_subscriptions.Values.All(x => x.Remove(subscriber));

虽然可能想检查一下这方面的表现。