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

7

我想使用一种集合类,它可以使用值的属性作为键,而不是使用 Dictionary<TKey,TValue>,是否有这样的类?

3个回答

10

是的,有 - 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);
    }
}

4

正如Jon Skeet所说,KeyedCollection是显而易见的选择。

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

  • You will of course want the property that you use as the key to be readonly.

  • Its method Contains(TItem item) is inherited from Collection<T>, and is implemented by iterating through the collection. This can therefore be much slower than Contains(TKey key). It's too easy for developers to make the mistake of using the wrong overload, so it may be worth considering implementing your own Contains(TItem item) method:

    public new bool Contains(TItem item)
    {
        if (item == null) throw new ArgumentNullException("item");
        return this.Contains(GetKeyForItem(item));
    }
    
  • Unlike an IDictionary, it doesn't have a method TryGetValue. This can be useful and it might be worth implementing your own:

    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;
    }
    
  • It doesn't support enumeration of the keys, which can be useful:

    public IEnumerable<TKey> GetKeys()
    {
        foreach (TItem item in this)
        {
            yield return GetKeyForItem(item);
        }
    }
    
  • Serialization can be inefficient, as it will serialize both its internal list and its internal dictionary. You can get round this if you need to by implementing custom serialization.


+1,这就是键控集合应该实现的方式。我有两个建议,我会将其称为“TryGetItem”,并使“GetKeys”成为像“Keys”一样的属性。 - nawfal

2
使用普通方法,当你设置键值对时,请指定你感兴趣的值的属性。
这太简单了,我一定误解了你的要求。
也许你希望稍后使用任意属性而不是在输入时使用。在这种情况下,我认为你需要使用多个字典对象(可能在一个辅助类中绑定在一起)。

1
如果您在添加对象后设置其属性,则该属性将与集合中的键不同步。 - Jeremy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接