2010-09-16 41 views
4

似乎我忘記了一個typename ...我腦海中的某些東西一直告訴我,我偶然發現了一個基本上使用用戶定義的Comparer進行查找的Dictionary。但我無法再在.Net的深處找到那個類。「字典」與鍵作爲存儲元素的一部分?

由於我沒有真正的想法如何描述我所尋找的而沒有描述可能的實現,我還將舉例說明我不想做什麼。

我basicly尋找一種方式來實現以下(僞):

class CustomId 
{ 
    // [...] 
} 
class Element 
{ 
    CustomId id; 
} 
Container<CustomId, Element> myContainer = new Container(myCustomComparer) 
myContainer.Add(new Element()) // No key specified 
myElement = myContainer[new CustomId(...)]; // Retrieval with custom id 

也許這在技術上是不太字典,但我希望這個想法是清楚的。基本上關鍵是存儲的元素的一部分。

+0

你可以使用Reflection創建它,但不確定這是你正在尋找的。 – Aliostad 2010-09-16 16:09:25

+1

我相信這個概念的通用名稱是一個索引。這就像在對象的「id」屬性中的RDBMS中添加索引一樣。 – rmeador 2010-09-16 16:20:59

回答

12

我認爲您在尋找KeyedCollection<TKey, TItem>。創建一個繼承此類的類並覆蓋GetKeyForItem()方法。

+0

哇,太快了,StackOverflow甚至不允許將它標記爲現在的答案。 – 2010-09-16 16:12:53

2

其實很簡單。你只需要從KeyedCollection<TKey, TItem>繼承:

public class ElementCollection : KeyedCollection<CustomId, Element> 
{ 
    public override CustomId GetKeyForItem(Element element) 
    { 
     return element.id; 
    } 
} 
+0

Doh!看起來我打字速度太慢。在這裏留下示例代碼... – 2010-09-16 16:11:44

+0

看來最終的結果是,您將'Element'作爲密鑰傳遞給容器,然後從返回的集合中獲取該Element。如果你已經有了'Element',那有什麼意義呢? – JohnB 2010-09-16 16:17:40

+1

因爲你還沒有元素。你只有CustomId。 GetKeyForItem方法在內部被調用來檢查你提供的CustomId對象集合中的元素......而不是相反。 – 2010-09-16 16:55:13

0

你可以做兩件事情:

使用一個簡單的列表,並使用Linq通過的自訂檢索對象:

var elements = myContainer.Where(e=>e.CustomID == new CustomID(...)).ToList(); 

或者,延長泛型Dictionary類提供知道如何從給定值投影密鑰的Add超載:

public class AutoDictionary<K,V> : Dictionary<K,V> 
{ 
    public Func<V,K> KeyGenerator { get; set; } 
    public void Add(V value) 
    { 
     Add(KeyGenerator(V),V); 
    } 
} 

... 

var myContainer = new AutoDictionary<CustomId, Element>(); 
myContainer.KeyGenerator = e=> e.id; 
myContainer.Add(myElement); 
var elementFromDictionary = myContainer[myElement.id]; //will be the same instance as myElement