JD2022-TU1/main/tools/framework/JD.Collections/OrderedDictionary.cs

274 lines
7.3 KiB
C#

using System.Collections.Generic;
using JD.Collections.ObjectModel;
using JD.Kernel.StaticHelpers;
namespace JD.Collections
{
/// <summary>
/// Ordered dictionary.
/// </summary>
/// <remarks>The dictionary keep the elements in the order they are added.</remarks>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TValue"></typeparam>
public class OrderedDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
#region Inner type
private class OrderedValueCollection : ReadOnlyCollectionBase<TValue>
{
private readonly OrderedDictionary<TKey, TValue> m_owner;
public OrderedValueCollection(OrderedDictionary<TKey, TValue> owner)
{
System.Diagnostics.Debug.Assert(owner != null);
m_owner = owner;
}
public override int Count
{
get { return m_owner.Count; }
}
private IEnumerable<TValue> FakeEnumerator()
{
foreach(TKey key in m_owner.Keys)
{
yield return m_owner[key];
}
}
public override IEnumerator<TValue> GetEnumerator()
{
return FakeEnumerator().GetEnumerator();
}
}
#endregion
#region Variables
private readonly List<TKey> m_keysOrder;
private readonly Dictionary<TKey, TValue> m_innerDictionary;
private readonly OrderedValueCollection m_valuesCollection;
#endregion
#region Conctructors
/// <summary>
/// Constructor.
/// </summary>
public OrderedDictionary()
{
m_innerDictionary = new Dictionary<TKey, TValue>();
m_keysOrder = new List<TKey>();
m_valuesCollection = new OrderedValueCollection(this);
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="dictionary"></param>
public OrderedDictionary(OrderedDictionary<TKey, TValue> dictionary)
: this()
{
Throw.IfNull(dictionary, "dictionary");
foreach(KeyValuePair<TKey, TValue> pair in dictionary)
{
Add(pair.Key, pair.Value);
}
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="capacity"></param>
public OrderedDictionary(int capacity)
{
m_innerDictionary = new Dictionary<TKey, TValue>(capacity);
m_keysOrder = new List<TKey>(capacity);
m_valuesCollection = new OrderedValueCollection(this);
}
#endregion
#region IDictionary<TKey,TValue> Members
/// <summary>
/// Add.
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void Add(TKey key, TValue value)
{
m_innerDictionary.Add(key, value);
m_keysOrder.Add(key);
}
/// <summary>
/// Constains key.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool ContainsKey(TKey key)
{
return m_innerDictionary.ContainsKey(key);
}
/// <summary>
/// Ordered keys.
/// </summary>
public ICollection<TKey> Keys
{
get
{
return m_keysOrder.AsReadOnly();
}
}
/// <summary>
/// Remove.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool Remove(TKey key)
{
if (m_innerDictionary.Remove(key))
{
Throw.InvalidProgramIf(!m_keysOrder.Remove(key), "The key was in the dictionary but not in the list.");
return true;
}
return false;
}
/// <summary>
/// Try get value.
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool TryGetValue(TKey key, out TValue value)
{
return m_innerDictionary.TryGetValue(key, out value);
}
/// <summary>
/// Ordered value.
/// </summary>
public ICollection<TValue> Values
{
get
{
return m_valuesCollection;
}
}
/// <summary>
/// Indexed accessor.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public TValue this[TKey key]
{
get
{
return m_innerDictionary[key];
}
set
{
m_innerDictionary[key] = value;
}
}
#endregion
#region ICollection<KeyValuePair<TKey,TValue>> Members
void ICollection<KeyValuePair<TKey,TValue>>.Add(KeyValuePair<TKey, TValue> item)
{
m_innerDictionary.Add(item.Key, item.Value);
m_keysOrder.Add(item.Key);
}
/// <summary>
/// Clear.
/// </summary>
public void Clear()
{
m_innerDictionary.Clear();
m_keysOrder.Clear();
}
bool ICollection<KeyValuePair<TKey,TValue>>.Contains(KeyValuePair<TKey, TValue> item)
{
return ((ICollection<KeyValuePair<TKey, TValue>>)m_innerDictionary).Contains(item);
}
void ICollection<KeyValuePair<TKey,TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
((ICollection<KeyValuePair<TKey, TValue>>)m_innerDictionary).CopyTo(array, arrayIndex);
}
/// <summary>
/// Count.
/// </summary>
public int Count
{
get { return m_innerDictionary.Count; }
}
/// <summary>
/// Is read-only.
/// </summary>
public bool IsReadOnly
{
get { return ((ICollection<KeyValuePair<TKey, TValue>>)m_innerDictionary).IsReadOnly; }
}
bool ICollection<KeyValuePair<TKey,TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
if (((ICollection<KeyValuePair<TKey, TValue>>)m_innerDictionary).Remove(item))
{
Throw.InvalidProgramIf(!m_keysOrder.Remove(item.Key), "The key was in the dictionary but not in the list.");
return true;
}
return false;
}
#endregion
#region IEnumerable<KeyValuePair<TKey,TValue>> Members
private IEnumerable<KeyValuePair<TKey, TValue>> FakeEnumerator()
{
foreach (TKey key in m_keysOrder)
{
yield return new KeyValuePair<TKey, TValue>(key, m_innerDictionary[key]);
}
}
/// <summary>
/// Ordered KeyValuePair.
/// </summary>
/// <returns></returns>
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return FakeEnumerator().GetEnumerator();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
}