我想使用一种集合类,它可以使用值的属性作为键,而不是使用 Dictionary<TKey,TValue>
,是否有这样的类?
我想使用一种集合类,它可以使用值的属性作为键,而不是使用 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);
}
}
正如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.