using System; using System.Collections; using System.Collections.Generic; using System.Linq; namespace OpenVIII { /// /// List of KeyValuePairs /// TKey cannot be int use a List /// /// /// public sealed class OrderedDictionary : IDictionary { #region Fields private List> _list; #endregion Fields #region Constructors public OrderedDictionary(int capacity = 0) => _list = new List>(capacity); public OrderedDictionary(IDictionary copy) : this(copy.Count) { foreach (var pair in copy) { Add(new KeyValuePair(pair.Key, pair.Value)); } } #endregion Constructors #region Properties public bool IsFixedSize => false; public bool IsReadOnly => false; public bool IsSynchronized => false; public IReadOnlyList Keys => _list.Select(kvp => kvp.Key).ToList(); public IReadOnlyList Values => _list.Select(kvp => kvp.Value).ToList(); public int Count => _list.Count; ICollection IDictionary.Keys => _list.Select(kvp => kvp.Key).ToArray(); ICollection IDictionary.Values => _list.Select(kvp => kvp.Value).ToArray(); #endregion Properties #region Indexers public KeyValuePair this[int index] { get { if (TryGetKVPByIndex(index, out var kvp)) return kvp; throw new KeyNotFoundException($"{this}::Index:{index} - Not Found!"); } } public TValue this[TKey key] { get { if (TryGetByKey(key, out var value)) return value; throw new KeyNotFoundException($"{this}::Key:{key} - Not Found!"); } set { var index = _list.FindIndex(kvp => kvp.Key.Equals(key)); if (index >= 0) _list[index] = new KeyValuePair(key, value); else throw new KeyNotFoundException($"{this}::Key:{key} - Not Found!"); } } TValue IDictionary.this[TKey key] { get => this[key]; set => this[key] = value; } #endregion Indexers #region Methods public void Add(TKey key, TValue value) { if (!TryAdd(key, value)) throw new ArgumentException($"{this}::Key:{key} - Already Exists!"); } public void Add(KeyValuePair item) => Add(item.Key, item.Value); public void Clear() => _list.Clear(); public bool Contains(KeyValuePair item) => _list.Contains(item); public bool ContainsIndex(int index) => index < _list.Count; public bool ContainsKey(TKey key) => _list.Any(kvp => kvp.Key.Equals(key)); public bool ContainsValue(TValue value) => _list.Any(kvp => kvp.Value.Equals(value)); public void CopyTo(KeyValuePair[] array, int arrayIndex) { if (Count <= array.Length + arrayIndex) { foreach (var i in _list) { array[arrayIndex++] = i; } return; } throw new OverflowException($"{this}::Count:{Count} > array.Length:{array.Length} + arrayIndex:{arrayIndex}"); } public IEnumerator GetEnumerator() => _list.GetEnumerator(); public bool Remove(TKey key) { var kvp = _list.First(_kvp => _kvp.Key.Equals(key)); return _list.Remove(kvp); } public bool Remove(KeyValuePair item) => _list.Remove(item); public bool TryAdd(TKey key, TValue value) { if (!ContainsKey(key)) { _list.Add(new KeyValuePair(key, value)); return true; } return false; } public bool TryGetByIndex(int index, out TValue value) { if (ContainsIndex(index)) { value = _list[index].Value; return true; } value = default; return false; } public bool TryGetByKey(TKey key, out TValue value) { if (ContainsKey(key)) { value = _list.First(kvp => kvp.Key.Equals(key)).Value; return true; } value = default; return false; } public bool TryGetIndexByKey(TKey key, out int value) { if (ContainsKey(key)) { value = _list.FindIndex(kvp => kvp.Key.Equals(key)); return true; } value = -1; return false; } public bool TryGetKeyByIndex(int index, out TKey value) { if (ContainsIndex(index)) { value = _list[index].Key; return true; } value = default; return false; } public bool TryGetKVPByIndex(int index, out KeyValuePair value) { if (ContainsIndex(index)) { value = _list[index]; return true; } value = default; return false; } public bool TryGetValue(TKey key, out TValue value) => TryGetByKey(key, out value); public OrderedDictionary Clone() => new OrderedDictionary(this); IEnumerator> IEnumerable>.GetEnumerator() => _list.GetEnumerator(); #endregion Methods } }