【发布时间】:2010-12-18 22:32:33
【问题描述】:
我想要某种类型的集合类,而不是使用Dictionary<TKey,TValue>,它可以使用值的属性作为键,有这样的东西吗?
【问题讨论】:
标签: .net collections dictionary
我想要某种类型的集合类,而不是使用Dictionary<TKey,TValue>,它可以使用值的属性作为键,有这样的东西吗?
【问题讨论】:
标签: .net collections dictionary
是的,有 - 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 是显而易见的候选者。
关于这个类的一些随机评论:
您当然希望用作键的属性是只读的。
它的方法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);
}
}
序列化可能效率低下,因为它会同时序列化其内部列表和内部字典。如果需要,您可以通过实现自定义序列化来解决这个问题。
【讨论】:
TryGetItem 并将 GetKeys 设为类似于 Keys 的属性。
使用普通的,设置键值对的时候,指定你感兴趣的值的属性。
这太简单了,我一定是误解了你的要求。
也许您想稍后而不是在输入时使用任意属性。在这种情况下,我认为您将不得不使用多个字典对象(可能在一个辅助类中捆绑在一起)。
【讨论】: