2009-06-27 60 views
2

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是否已存在集合中的分配。如果不是,那麼新的分配將被添加到集合中,但是如果是這樣的話,則將現有的分配替換爲新的分配。

我目前正在使用Dictionary來維護集合,以Allocation.EventDate爲關鍵。它適用於域名,但我想知道密鑰是否已經是價值的一部分本身並不是一種'難聞的氣味'。

我也沒有理由堅持除字典值之外的任何東西。因爲我使用的是NHibernate,所以我可能需要編寫一些自定義類型,並且我想知道這是否也是我應該使用不同類型的集合的線索。 (這也是Allocation類中的虛擬屬性的原因)。

我正在考慮的主要選擇將是一個具有專用EqualityComparer的HashSet。

您認爲如何?

乾杯, Berryl

+0

我知道這是一個非常古老的問題。但我想知道爲什麼沒有人提出鏈接列表,畢竟這是字典內部用於衝突散列的內容。 `Dictionary `不能有重複鍵的唯一原因是當你看起來一個鍵時它不知道該返回什麼。 (順便說一下,使鏈接類型成爲一個結構體,在性能上節省了很多。) – Aidiakapi 2011-11-16 19:05:56

回答

3

如果您使用外部比較器來執行HashSet<Allocation>,則必須非常小心,不要更改日期而不重新鍵入字典中的值。無論哪種方式,你都會遇到這個問題,但它會因可變性而加劇(至少Dictionary<,>它仍然能夠跟蹤它自己的鍵和值)。有一個可變的值作爲密鑰的一部分,你將永遠不會再看到這個值...

當我在過去的日程安排系統上工作時,我實際上已經使用了SortedList<,> - 類似,但如果你一般如果數據是相當一致的,則需要按順序訪問數據,並允許二進制搜索。

+0

感謝您對SortedList的建議。 Cheers – Berryl 2009-06-28 16:36:03

3

我不認爲這樣的事實,關鍵是部分的價值必然是一個問題。根據我的經驗,字典常常是這種情況。使用適當的相等比較器的HashSet肯定會起作用,只要您不需要使用特定的EventDate即可獲取當前對象。這似乎是一個有用的事情,能夠做到,潛在的...

你目前只是在一個模糊的方式擔心,或者你有一個具體的懷疑,這可能會咬你嗎?

+0

我真的想驗證對於作爲價值一部分的關鍵的某種模糊的關注。真相被告知字典很棒,易於使用。 我剛剛完成了本書的第一部分,順便說一句......你是一位出色的作家! – Berryl 2009-06-28 16:35:05

2

使用標準庫,沒有更好的解決方案,我知道。但是,我也覺得這種代碼是一種「難聞的氣味」,但這是因爲BCL中的集合類,而不是你的代碼。

我不知道MS爲什麼不創建泛型集<TKey, TData> where TData: IKeyed<TKey>而不是字典,因爲這可以實現這樣的數據結構,其中密鑰是數據的一部分。 KeyValuePair<TKey, TValue>: IKeyed<TKey>只是一個實現此接口的幫助器結構,因此可以創建與現在相同的字典功能。我想知道他們爲什麼不添加聲明式不可變類型的概念,並將其作爲一個可能的泛型類型約束,因爲這樣可以確保在過程中密鑰不會更改其哈希碼運行時(如果在某個可變對象上實現了GetHashCode()Equals(),則當前可能發生)。

+0

使用可變類型的對象作爲字典鍵沒有任何問題,前提是沒有以該方式使用的對象*實例將被暴露給可能在存儲在字典中時對其進行變異的代碼。框架/編譯器幫助維護不可變類型的不可變實例會很有幫助,但是它需要對類型系統進行一些重大更改。 – supercat 2014-03-04 02:15:02