Generic Key/Value pair collection in that preserves insertion order?

Fly*_*wat 30 .net c# data-structures

I'm looking for something like a Dictionary<K,V> however with a guarantee that it preserves insertion order. Since Dictionary is a hashtable, I do not think it does.

Is there a generic collection for this, or do I need to use one of the old .NET 1.1 collections?

McA*_*den 24

There is not. However, System.Collections.Specialized.OrderedDictionary should solve most need for it.

EDIT: Another option is to turn this into a Generic. I haven't tested it but it compiles (C# 6) and should work. However, it will still have the same limitations that Ondrej Petrzilka mentions in comments below.

    public class OrderdDictionary<T, K>
    {
        public OrderedDictionary UnderlyingCollection { get; } = new OrderedDictionary();

        public K this[T key]
        {
            get
            {
                return (K)UnderlyingCollection[key];
            }
            set
            {
                UnderlyingCollection[key] = value;
            }
        }

        public K this[int index]
        {
            get
            {
                return (K)UnderlyingCollection[index];
            }
            set
            {
                UnderlyingCollection[index] = value;
            }
        }
        public ICollection<T> Keys => UnderlyingCollection.Keys.OfType<T>().ToList();
        public ICollection<K> Values => UnderlyingCollection.Values.OfType<K>().ToList();
        public bool IsReadOnly => UnderlyingCollection.IsReadOnly;
        public int Count => UnderlyingCollection.Count;
        public IDictionaryEnumerator GetEnumerator() => UnderlyingCollection.GetEnumerator();
        public void Insert(int index, T key, K value) => UnderlyingCollection.Insert(index, key, value);
        public void RemoveAt(int index) => UnderlyingCollection.RemoveAt(index);
        public bool Contains(T key) => UnderlyingCollection.Contains(key);
        public void Add(T key, K value) => UnderlyingCollection.Add(key, value);
        public void Clear() => UnderlyingCollection.Clear();
        public void Remove(T key) => UnderlyingCollection.Remove(key);
        public void CopyTo(Array array, int index) => UnderlyingCollection.CopyTo(array, index);
    }
Run Code Online (Sandbox Code Playgroud)

  • 不通用,但看起来足够接近.谢谢. (3认同)

Eug*_*sky 14

实际上有一个是通用的,从.net 2.0开始就存在.它被称为KeyedCollection<TKey, TItem>.但是,它带有限制,它从值构造键,因此它不是通用的键/值对集合.(虽然你当然可以像KeyedCollection<TKey, Tuple<TKey, TItem>>解决方法一样使用它).

如果您需要它IDictionary<TKey, TItem>,它有一个.Dictionary属性.

我遇到的一个小问题是它是一个抽象类,你必须将它子类化并实现:

protected abstract TKey GetKeyForItem(TItem item)
Run Code Online (Sandbox Code Playgroud)

为了这个目的,我宁愿只将lambda传递给构造函数,但是再说一遍,我猜一个虚方法比lambda稍微快一点(对此有任何评论).

编辑正如评论中提出的问题:KeyedCollection保留顺序,因为它继承自Collection<T>,它来自哪个IList<T>.它来自.另请参阅Add方法的文档:将对象添加到Collection的末尾.).

  • 它保留了顺序,因为它继承自[Collection <T>](http://msdn.microsoft.com/en-us/library/ms132397).另请参阅"Add"方法的文档:*将对象添加到Collection <T>的末尾.(继承自Collection <T>.)*. (2认同)

adr*_*nks 8

有一个OrderedDictionary类,它是一本字典,但可以在插入顺序进行索引,但它不是泛型.目前在.Net框架中没有一个普遍的.

我已经从.Net团队中的某个人那里读过一条评论,说他们可能会在将来实施一个通用的版本,但如果是这样的话,很可能会被调用IndexableDictionary而不是OrderedDictionary让它的行为更加明显.

编辑:找到了报价.它位于MSDN页面上OrderedDictionary,归功于微软的David M. Kean:

这种类型实际上是错误的; 它不是一个"有序"字典,而是一个"索引"字典.虽然,今天没有这种类型的等效通用版本,如果我们将来添加一个,我们可能会命名为'IndexedDictionary'类型.


Tho*_*que 5

Well, you could use a List<KeyValuePair<K,V>>, which would preserve the order... however you would lose the lookup functionality of the dictionary. Why do you need the order to be preserved ?

  • 为什么人们总是要问"为什么"而不是坚持"如何"?可能是他需要这样...... (33认同)
  • @ md1337,我不同意.知道为什么经常允许提供更适当的解决方案 (19认同)
  • @ md1337问为什么没问题,但是应该在评论中做一遍,以便在回答之前澄清问题,而不是在答案中. (17认同)