是否有像集合这样的字典可以使用它的值的属性作为关键?

问题描述:

而不是使用Dictionary<TKey,TValue>我想要一些类型的集合类,可以使用值的属性作为关键,是否有这样的事情?是否有像集合这样的字典可以使用它的值的属性作为关键?

是的,有 - System.Collections.ObjectModel.KeyedCollection<TKey, TValue>

这是抽象的,并且在我看到的框架中没有具体的派生类,但是我所看到的所有需要​​实现的都是GetKeyForItem。例如,你可以这样做与代表:

public class DelegatingKeyedCollection<TKey, TItem> : System.Collections.ObjectModel.KeyedCollection<TKey, TItem> 
{ 
    private readonly Func<TItem, TKey> keySelector; 

    public DelegatingKeyedCollection(Func<TItem, TKey> keySelector) 
    { 
     this.keySelector = keySelector; 
    } 

    protected override TKey GetKeyForItem(TItem item) 
    { 
     return keySelector(item); 
    } 
} 

使用正常的,当你设置的键值对,指定您感兴趣的价值的财产。

那是太容易了,我一定是误解你的要求。

也许你想使用任意属性,而不是在输入时。在这种情况下,我认为你将不得不使用多个字典对象(可能绑定在一个助手类中)。

+1

如果在添加对象后设置对象的属性,则该对象的属性将与集合中的键不同步。 – Jeremy 2009-11-21 00:37:38

KeyedCollection作为Jon Skeet说是明显的候选人。

一些关于这个类随机备注:

  • 你当然会希望您使用的关键是只读属性。

  • 其方法Contains(TItem item)Collection<T>继承,并通过迭代通过集合实现。因此这可能比Contains(TKey key)慢得多。这太容易为开发者采用了错误的过载的错误,因此它可能是值得考虑实现自己的Contains(TItem item)方法:

    public new bool Contains(TItem item) 
    { 
        if (item == null) throw new ArgumentNullException("item"); 
        return this.Contains(GetKeyForItem(item)); 
    } 
    
  • 不像一个IDictionary,它没有一种方法TryGetValue。这可能是有用的,它可能是值得实现自己:

    public bool TryGetValue(TKey key, out TItem item) 
    { 
        // If the dictionary exists, use it 
        if (Dictionary != null) return Dictionary.TryGetValue(key, out item); 
        // Else do it the hard way 
        if (!this.Contains(key)) 
        { 
         item = default(TItem); 
         return false; 
        } 
        item = this[key]; 
        return true; 
    } 
    
  • 它不支持键枚举,这可能是有用的:

    public IEnumerable<TKey> GetKeys() 
    { 
        foreach (TItem item in this) 
        { 
         yield return GetKeyForItem(item); 
        } 
    } 
    
  • 序列化可能是低效的,因为它会序列化它的内部列表和它的内部字典。如果需要通过实现自定义序列化,您可以了解这一点。

+0

+1,这就是键控收集应该如何实施。两个建议,我会称之为'TryGetItem'并使'GetKeys'成为'Keys'的属性。 – nawfal 2013-11-01 02:32:38