集合查找;字典的替代品

时间:2009-06-27 21:50:45

标签: c# collections dictionary nhibernate-mapping hashset

TimeSheetActivity类有一组Allocations。分配是一个值对象,也由域中的其他对象使用,如下所示:

public class Allocation : ValueObject
{
    public virtual StaffMember StaffMember { get; private set; }
    public virtual TimeSheetActivity Activity { get; private set; }
    public virtual DateTime EventDate { get ... }
    public virtual TimeQuantity TimeSpent { get ... }
}

不允许对同一个Allocation.EventDate进行重复分配。因此,当客户端尝试对活动进行分配时,会进行检查以查看集合中是否已存在同一Allocation.EventDate的Allocation。如果没有,则新的Allocation将添加到集合中,但如果是,则现有的Allocation将替换为新的。

我目前正在使用Dictionary来维护集合,并将Allocation.EventDate作为键。它适用于域名,但我想知道密钥是否已经是价值的一部分,这本身并不是一种“难闻的气味”。

除了词典值,我也没有理由坚持任何东西。因为我正在使用NHibernate,所以我可能需要编写一些自定义类型,并且我想知道这是否也是我应该使用不同类型的集合的线索。 (这也是Allocation类中虚拟属性的原因。)

我想到的主要替代方案是具有专用EqualityComparer的HashSet。

您怎么看?

干杯, Berryl

3 个答案:

答案 0 :(得分:3)

我不认为密钥是值的一部分这一事实必然是一个问题。根据我的经验,词典经常出现这种情况。具有适当的相等比较器的HashSet肯定会起作用,只要你永远不需要使用特定的EventDate来获取当前对象。这似乎是一件有用的事情,可能......

您目前是否只是在某种模糊的方式担心,或者您对这可能会如何咬你有具体的怀疑?

答案 1 :(得分:3)

如果使用外部比较器来执行HashSet<Allocation>,则必须非常小心,不要在不重新键入字典中的值的情况下更改日期。你有这个问题,但是由于可变性而加剧(至少Dictionary<,>它仍然可以跟踪它自己的密钥和值)。如果将一个可变值作为键的一部分,那么您再也不会看到该值......

当我过去使用计划系统时,我实际上已经使用了SortedList<,> - 相似但是如果您通常希望数据按顺序有用,并且如果数据相当均匀则允许二进制搜索

答案 2 :(得分:2)

使用标准库,我知道没有更好的解决方案。但是,我也觉得这种代码是“难闻的气味”,但这是因为BCL中的集合类而不是你的代码。

我不知道为什么MS没有创建泛型集<TKey, TData> where TData: IKeyed<TKey>左右而不是字典,因为这将允许实现密钥是数据一部分的数据结构。 KeyValuePair<TKey, TValue>: IKeyed<TKey>只是一个实现此接口的辅助结构,因此允许创建与我们现在相同的字典功能。

另外(继续小咆哮)我想知道他们为什么不添加声明性不可变类型的概念并使其成为可能的泛型类型约束,因为这将允许确保键在运行时不会更改其哈希码(如果在某个可变对象上实现GetHashCode()Equals(),则当前可能会发生这种情况。)