274 lines
7.3 KiB
C#
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
|
|
}
|
|
}
|