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

前端 未结 9 1271
刺人心
刺人心 2020-12-09 01:40

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

9条回答
  •  佛祖请我去吃肉
    2020-12-09 02:20

    Here is a wrapper for the non-generic Systems.Collections.Specialized.OrderedDictionary type.

    This type will return keys/value/pairs sequences in insertion order, much like Ruby 2.0 hashes.

    It does not require C#6 magic, conforms to IDictionary (which also means that accessing a non-assigned key throws an exception), and ought to be serializable.

    It is given the name 'IndexedDictionary' per note on Adrian's answer.

    YMMV.

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Linq;
    
    /// 
    /// A dictionary that maintains insertion ordering of keys.
    /// 
    /// This is useful for emitting JSON where it is preferable to keep the key ordering
    /// for various human-friendlier reasons.
    /// 
    /// There is no support to manually re-order keys or to access keys
    /// by index without using Keys/Values or the Enumerator (eg).
    /// 
    [Serializable]
    public sealed class IndexedDictionary : IDictionary
    {
        // Non-generic version only in .NET 4.5
        private readonly OrderedDictionary _backing = new OrderedDictionary();
    
        private IEnumerable> KeyValuePairs
        {
            get
            {
                return _backing.OfType()
                    .Select(e => new KeyValuePair((TKey)e.Key, (TValue)e.Value));
            }
        }
    
        public IEnumerator> GetEnumerator()
        {
            return KeyValuePairs.GetEnumerator();
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    
        public void Add(KeyValuePair item)
        {
            _backing[item.Key] = item.Value;
        }
    
        public void Clear()
        {
            _backing.Clear();
        }
    
        public bool Contains(KeyValuePair item)
        {
            return _backing.Contains(item.Key);
        }
    
        public void CopyTo(KeyValuePair[] array, int arrayIndex)
        {
            KeyValuePairs.ToList().CopyTo(array, arrayIndex);
        }
    
        public bool Remove(KeyValuePair item)
        {
            TValue value;
            if (TryGetValue(item.Key, out value)
                && Equals(value, item.Value))
            {
                Remove(item.Key);
                return true;
            }
            return false;
        }
    
        public int Count
        {
            get { return _backing.Count; }
        }
    
        public bool IsReadOnly
        {
            get { return _backing.IsReadOnly; }
        }
    
        public bool ContainsKey(TKey key)
        {
            return _backing.Contains(key);
        }
    
        public void Add(TKey key, TValue value)
        {
            _backing.Add(key, value);
        }
    
        public bool Remove(TKey key)
        {
            var result = _backing.Contains(key);
            if (result) {
                _backing.Remove(key);
            }
            return result;
        }
    
        public bool TryGetValue(TKey key, out TValue value)
        {
            object foundValue;
            if ((foundValue = _backing[key]) != null
                || _backing.Contains(key))
            {
                // Either found with a non-null value, or contained value is null.
                value = (TValue)foundValue;
                return true;
            }
            value = default(TValue);
            return false;
        }
    
        public TValue this[TKey key]
        {
            get
            {
                TValue value;
                if (TryGetValue(key, out value))
                    return value;
                throw new KeyNotFoundException();
            }
            set { _backing[key] = value; }
        }
    
        public ICollection Keys
        {
            get { return _backing.Keys.OfType().ToList(); }
        }
    
        public ICollection Values
        {
            get { return _backing.Values.OfType().ToList(); }
        }
    }
    

提交回复
热议问题