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

时间:2009-11-20 23:57:31

标签: .net collections dictionary

不是使用Dictionary<TKey,TValue>我想要某种类型的集合类可以使用值的属性作为键,是否有这样的东西?

3 个答案:

答案 0 :(得分:9)

是的,有 - 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 :(得分:4)

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

关于这个课程的一些随机评论:

  • 您当然希望您用作密钥的财产是只读的。

  • 它的方法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);
        }
    }
    
  • 序列化可能效率低下,因为它会序列化其内部列表和内部字典。如果需要,可以通过实现自定义序列化来解决这个问题。

答案 2 :(得分:2)

使用普通值,并在设置键值对时,指定您感兴趣的值的属性。

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

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