我在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)的选择。在这种特殊情况下,我不一定会尝试优化代码,尽管这肯定是值得考虑的。我想要了解的是,如果这样做有一个普遍成熟的做法。如果没有,您将在自己的代码中使用哪个选项?
答案 0 :(得分:3)
选项1将比选项2慢.Lambda表达式和LINQ将更慢。我会使用HashSet<>
代替List<>
。
如果您需要确认项目移除,则必须使用Contains
。
EDITED:
由于在lock
语句中使用代码的概率很高,并且最佳做法是减少lock
内的执行时间,因此应用选项2可能很有用。看起来没有最好的练习使用或不使用Contains
和Remove
。
答案 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));
虽然可能想检查一下这方面的表现。