如果值是对象并且这些对象的属性是键,那么是否有比Dictionary更好的数据结构?

我有一个Dictionary ,其中intobj一个属性。 是否有更好的数据结构? 我觉得使用属性是关键是多余的。

Dictionary是容器类中的一个字段,允许根据int id号随机索引到obj值。 容器类中的简化(无exception处理)索引器如下所示:

 obj this[int id] { get{ return this.myDictionary[id];} } 

其中myDictionary是前面提到的Dictionary持有对象。

这可能是快速随机访问的典型方式,但我想获得第二意见。

框架中没有具体的类来执行此操作。 有一个抽象的,KeyedCollection。 您必须从该类派生自己的类并实现GetKeyForItem()方法。 这很简单,只需返回要索引的属性的值即可。

这就是你需要做的,但要注意ChangeItemKey()。 当您用作键的属性更改值时,您必须执行一些有意义的操作。 如果你确保属性是不可变的(只有一个getter),那就足够了。 但是当你不这样做时很尴尬,对象本身现在需要知道它存储在你的集合中。 如果你没有做任何事情(调用ChangeItemKey),对象会在集合中丢失,你找不到它。 非常接近泄漏。

注意Dictionary <>如何通过分别指定键值和对象来解决此问题。 您可能仍然无法找到该对象,但至少它不会因设计而丢失。

有一个KeyedCollection类。

编辑:KeyedCollection可以在内部使用字典,但它比原始字典更清晰的接口,因为您可以直接按值查找。 不可否认,我发现它一般都没有用。

如果出厂设置附带的额外开销不值得,您可以轻松实现自己的KeyedCollectionSystem.Collections.ObjectModel的原始KeyedCollection在内部是DictionaryList ,这意味着您可以在IList<>IDictionary<>上定义操作。 例如,您可以插入,按索引访问,以插入的顺序遍历集合( IList<>促进所有这些),同时您可以基于键快速查找(借助字典)。 这意味着当您添加或删除项目时,它们必须在两个基础集合上执行,除了用于保存额外List<>的小内存开销(但对象不会像这样重复)。 虽然添加速度不会受到太大影响( List<>添加为O(1)),但移除速度会受到一点影响。

如果您不关心插入顺序和索引访问:

 public class KeyedCollection : ICollection { MemberInfo _keyInfo; Func _keySelector; Dictionary _dict; public TItem this[TKey key] { get { return _dict[key]; } } public int Count { get { return _dict.Count; } } public bool IsReadOnly { get { return false; } } public ICollection Keys { get { return _dict.Keys; } } private ICollection Items { get { return _dict.Values; } } public KeyedCollection(Expression> keySelector, IEqualityComparer comparer = null) { var keyExpression = keySelector.Body as MemberExpression; if (keyExpression != null) _keyInfo = keyExpression.Member; _keySelector = keySelector.Compile(); _dict = new Dictionary(comparer); } private TKey GetKeyForItem(TItem item) { return _keySelector(item); } public bool ContainsKey(TKey key) { return _dict.ContainsKey(key); } public bool Contains(TItem item) { return ContainsKey(GetKeyForItem(item)); } public bool TryGetItem(TKey key, out TItem item) { return _dict.TryGetValue(key, out item); } public void Add(TItem item) { _dict.Add(GetKeyForItem(item), item); } public void AddOrUpdate(TItem item) { _dict[GetKeyForItem(item)] = item; } public bool UpdateKey(TKey oldKey, TKey newKey) { TItem oldItem; if (_keyInfo == null || !TryGetItem(oldKey, out oldItem) || !SetItem(oldItem, newKey)) // important return false; RemoveKey(oldKey); Add(oldItem); return true; } private bool SetItem(TItem item, TKey key) { var propertyInfo = _keyInfo as PropertyInfo; if (propertyInfo != null) { if (!propertyInfo.CanWrite) return false; propertyInfo.SetValue(item, key, null); return true; } var fieldInfo = _keyInfo as FieldInfo; if (fieldInfo != null) { if (fieldInfo.IsInitOnly) return false; fieldInfo.SetValue(item, key); return true; } return false; } public bool RemoveKey(TKey key) { return _dict.Remove(key); } public bool Remove(TItem item) { return RemoveKey(GetKeyForItem(item)); } public void Clear() { _dict.Clear(); } public void CopyTo(TItem[] array, int arrayIndex) { Items.CopyTo(array, arrayIndex); } public IEnumerator GetEnumerator() { return Items.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } 

我已经实现了ICollection以使其更符合标准 – 并且您还获得了很好的集合初始化器语法! 🙂

样本用法:

 var p1 = new Person { Name = "a" }; var p2 = new Person { Name = "b" }; var people = new KeyedCollection(p => p.Name) { p1, p2 }; // p1 == people["a"]; // p2 == people["b"]; 

C#动态属性post似乎表明使用词典是一种流行的选择。 其他post建议使用HashTable

字典vs Hashtable