2010-09-16 38 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