context: /**
   * @author electricessence / https://github.com/electricessence/
   * Liscensing: GNU.v3 https://github.com/electricessence/ObjectX/blob/master/LICENSE
   */
  
  using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Collections.Specialized;
  using System.Threading;
  using System.Diagnostics.Contracts;
  using ObjectX.Core;
  
  namespace ObjectX.Collections
  {
  	/// <summary>
  	/// Represents a generic items of key/source pairs that are ordered independently of the key and source.
  	/// </summary>
  	/// <typeparam name="TKey">The type of the keys in the dictionary</typeparam>
  	/// <typeparam name="TValue">The type of the values in the dictionary</typeparam>
  	public interface IOrderedDictionary<TKey, TValue> : IOrderedDictionary, IDictionary<TKey, TValue>
  	{
  		/// <summary>
  		/// Adds an entry with the specified key and source into the <see cref="IOrderedDictionary{TKey,TValue}">IOrderedDictionary&lt;TKey,TValue&gt;</see> items with the lowest available index.
  		/// </summary>
  		/// <param name="key">The key of the entry to add.</param>
  		/// <param name="source">The source of the entry to add.</param>
  		/// <returns>The index of the newly added entry</returns>
  		/// <remarks>
  		/// <para>You can also use the <see cref="P:System.Collections.Generic.IDictionary{TKey,TValue}.Item(TKey)"/> property to add new elements by setting the source of a key that does not exist in the <see cref="IOrderedDictionary{TKey,TValue}">IOrderedDictionary&lt;TKey,TValue&gt;</see> items; however, if the specified key already exists in the <see cref="IOrderedDictionary{TKey,TValue}">IOrderedDictionary&lt;TKey,TValue&gt;</see>, setting the <see cref="P:Item(TKey)"/> property overwrites the old source. In contrast, the <see cref="M:AddSynchronized"/> method does not modify existing elements.</para></remarks>
  		/// <exception cref="ArgumentException">An element with the same key already exists in the <see cref="IOrderedDictionary{TKey,TValue}">IOrderedDictionary&lt;TKey,TValue&gt;</see></exception>
  		/// <exception cref="NotSupportedException">The <see cref="IOrderedDictionary{TKey,TValue}">IOrderedDictionary&lt;TKey,TValue&gt;</see> is read-only.<br/>
  		/// -or-<br/>
  		/// The <see cref="IOrderedDictionary{TKey,TValue}">IOrderedDictionary&lt;TKey,TValue&gt;</see> has a fized size.</exception>
  		new int Add(TKey key, TValue value);
  
  		/// <summary>
  		/// Inserts a new entry into the <see cref="IOrderedDictionary{TKey,TValue}">IOrderedDictionary&lt;TKey,TValue&gt;</see> items with the specified key and source at the specified index.
  		/// </summary>
  		/// <param name="index">The zero-based index at which the element should be inserted.</param>
  		/// <param name="key">The key of the entry to add.</param>
  		/// <param name="source">The source of the entry to add. The source can be <null/> if the type of the values in the dictionary is a reference type.</param>
  		/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than 0.<br/>
  		/// -or-<br/>
  		/// <paramref name="index"/> is greater than <see cref="System.Collections.ICollection.Count"/>.</exception>
  		/// <exception cref="ArgumentException">An element with the same key already exists in the <see cref="IOrderedDictionary{TKey,TValue}">IOrderedDictionary&lt;TKey,TValue&gt;</see>.</exception>
  		/// <exception cref="NotSupportedException">The <see cref="IOrderedDictionary{TKey,TValue}">IOrderedDictionary&lt;TKey,TValue&gt;</see> is read-only.<br/>
  		/// -or-<br/>
  		/// The <see cref="IOrderedDictionary{TKey,TValue}">IOrderedDictionary&lt;TKey,TValue&gt;</see> has a fized size.</exception>
  		void Insert(int index, TKey key, TValue value);
  
  		/// <summary>
  		/// Gets or sets the source at the specified index.
  		/// </summary>
  		/// <param name="index">The zero-based index of the source to get or set.</param>
  		/// <source>The source of the item at the specified index.</source>
  		/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than 0.<br/>
  		/// -or-<br/>
  		/// <paramref name="index"/> is equal to or greater than <see cref="System.Collections.ICollection.Count"/>.</exception>
  		new TValue this[int index]
  		{
  			get;
  			set;
  		}
  	}
  
  
  	/// <summary>
  	/// Represents a generic items of key/source pairs that are ordered independently of the key and source.
  	/// </summary>
  	/// <typeparam name="TKey">The type of the keys in the dictionary</typeparam>
  	/// <typeparam name="TValue">The type of the values in the dictionary</typeparam>
  	public class OrderedDictionary<TKey, TValue> : DisposableBase, IOrderedDictionary<TKey, TValue>
  	{
  		public enum Change
  		{
  			None,
  			Added,
  			Removed,
  			Inserted,
  			Modified
  		}
  
  		public class ItemChangedEventArgs<TIKey,TIValue> : EventArgs {
  			public readonly Change Change;
  			public readonly int Index;
  			public readonly TIKey Key;
  			public readonly TIValue Value;
  
  			public ItemChangedEventArgs(Change action, int index, TIKey key, TIValue value)
  			{
  				Change = action;
  				Index = index;
  				Key = key;
  				Value = value;
  			}
  		}
  
  		public delegate void ItemChangedEventHandler<TIKey,TIValue>(Object source, ItemChangedEventArgs<TIKey,TIValue> e);
  
  		public event ItemChangedEventHandler<TKey, TValue> ItemChanged;
  
  		protected void OnItemChanged(Change action, int index, TKey key, TValue value)
  		{
  			OnItemChanged(new ItemChangedEventArgs<TKey, TValue>(action, index, key, value));
  		}
  
  		protected virtual void OnItemChanged(ItemChangedEventArgs<TKey,TValue> e)
  		{
  			var handler = ItemChanged;
  			if (handler != null)
  				handler(this, e);
  		}
  
  		private const int DefaultInitialCapacity = 0;
  
  		private static readonly string _keyTypeName = typeof(TKey).FullName;
  		private static readonly string _valueTypeName = typeof(TValue).FullName;
  		private static readonly bool _valueTypeIsReferenceType = !typeof(ValueType).IsAssignableFrom(typeof(TValue));
  
  		private Dictionary<TKey, TValue> _dictionary;
  		private List<TKey> _list;
  		private IEqualityComparer<TKey> _comparer;
  		private object _syncRoot;
  		private int _initialCapacity;
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> class.
  		/// </summary>
  		public OrderedDictionary()
  			: this(DefaultInitialCapacity, null)
  		{
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> class using the specified initial capacity.
  		/// </summary>
  		/// <param name="capacity">The initial number of elements that the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> can contain.</param>
  		/// <exception cref="ArgumentOutOfRangeException"><paramref name="capacity"/> is less than 0</exception>
  		public OrderedDictionary(int capacity)
  			: this(capacity, null)
  		{
  			Contract.Requires(capacity >= 0, "'capacity' must be non-negative"); // Preferred Exception: <ArgumentOutOfRangeException>
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> class using the specified comparer.
  		/// </summary>
  		/// <param name="comparer">The <see cref="IEqualityComparer{TKey}">IEqualityComparer&lt;TKey&gt;</see> to use when comparing keys, or <null/> to use the default <see cref="EqualityComparer{TKey}">EqualityComparer&lt;TKey&gt;</see> for the type of the key.</param>
  		public OrderedDictionary(IEqualityComparer<TKey> comparer)
  			: this(DefaultInitialCapacity, comparer)
  		{
  		}
  
  		/// <summary>
  		/// Initializes a new instance of the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> class using the specified initial capacity and comparer.
  		/// </summary>
  		/// <param name="capacity">The initial number of elements that the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> items can contain.</param>
  		/// <param name="comparer">The <see cref="IEqualityComparer{TKey}">IEqualityComparer&lt;TKey&gt;</see> to use when comparing keys, or <null/> to use the default <see cref="EqualityComparer{TKey}">EqualityComparer&lt;TKey&gt;</see> for the type of the key.</param>
  		/// <exception cref="ArgumentOutOfRangeException"><paramref name="capacity"/> is less than 0</exception>
  		public OrderedDictionary(int capacity, IEqualityComparer<TKey> comparer)
  		{
  			Contract.Requires(capacity >= 0, "'capacity' must be non-negative"); // Preferred Exception: <ArgumentOutOfRangeException>
  
  			_initialCapacity = capacity;
  			_comparer = comparer;
  		}
  
  		public OrderedDictionary(TKey[] keys, TValue[] values = null)
  		{
  			if (values.Length > keys.Length)
  				throw new Exception("Invalid initialization values.  Value array is longer than key array.");
  
  			for(var i=0;i<keys.Length;i++)
  				AddInternal(keys[i], i < values.Length ? values[i] : default(TValue));
  
  		}
  
  		/// <summary>
  		/// Converts the object passed as a key to the key type of the dictionary
  		/// </summary>
  		/// <param name="keyObject">The key object to check</param>
  		/// <returns>The key object, cast as the key type of the dictionary</returns>
  		/// <exception cref="ArgumentNullException"><paramref name="keyObject"/> is <null/>.</exception>
  		/// <exception cref="ArgumentException">The key type of the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> is not in the inheritance hierarchy of <paramref name="keyObject"/>.</exception>
  		private static TKey ConvertToKeyType(object keyObject)
  		{
  			Contract.Assume(keyObject != null);
  			Contract.Assume(keyObject is TKey || _valueTypeIsReferenceType);
  
  			return (TKey)keyObject;
  		}
  
  		/// <summary>
  		/// Converts the object passed as a source to the source type of the dictionary
  		/// </summary>
  		/// <param name="source">The object to convert to the source type of the dictionary</param>
  		/// <returns>The source object, converted to the source type of the dictionary</returns>
  		/// <exception cref="ArgumentNullException"><paramref name="valueObject"/> is <null/>, and the source type of the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> is a source type.</exception>
  		/// <exception cref="ArgumentException">The source type of the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> is not in the inheritance hierarchy of <paramref name="valueObject"/>.</exception>
  		private static TValue ConvertToValueType(object value)
  		{
  			Contract.Assume(value is TValue || _valueTypeIsReferenceType);
  
  			if (null == value && _valueTypeIsReferenceType)
  					return default(TValue);
  
  			return (TValue)value;
  		}
  
  		/// <summary>
  		/// Gets the dictionary object that stores the keys and values
  		/// </summary>
  		/// <source>The dictionary object that stores the keys and values for the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see></source>
  		/// <remarks>Accessing this property will create the dictionary object if necessary</remarks>
  		private Dictionary<TKey, TValue> Dictionary
  		{
  			get
  			{
  				Contract.Ensures(Contract.Result<Dictionary<TKey, TValue>>() != null);
  
  				return LazyInitializer.EnsureInitialized(ref _dictionary, () => new Dictionary<TKey, TValue>(_initialCapacity, _comparer))
  					?? new Dictionary<TKey, TValue>(_initialCapacity, _comparer); // Satisifes code contracts...
  			}
  		}
  
  		/// <summary>
  		/// Gets the list object that stores the key/source pairs.
  		/// </summary>
  		/// <source>The list object that stores the key/source pairs for the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see></source>
  		/// <remarks>Accessing this property will create the list object if necessary.</remarks>
  		private List<TKey> List
  		{
  			get
  			{
  				Contract.Ensures(Contract.Result<List<TKey>>() != null);
  
  				return LazyInitializer.EnsureInitialized(ref _list, () => new List<TKey>(_initialCapacity))
  					?? new List<TKey>(_initialCapacity); // Satisifes code contracts...
  			}
  		}
  
  		private IEnumerable<KeyValuePair<TKey, TValue>> AsEnumerable()
  		{
  			foreach (var key in List)
  				yield return new KeyValuePair<TKey, TValue>(key, Dictionary[key]);
  		}
  
  		IDictionaryEnumerator IOrderedDictionary.GetEnumerator()
  		{
  			return Dictionary.GetEnumerator();
  		}
  
  		IDictionaryEnumerator IDictionary.GetEnumerator()
  		{
  			return Dictionary.GetEnumerator();
  		}
  
  		IEnumerator IEnumerable.GetEnumerator()
  		{
  			return AsEnumerable().GetEnumerator();
  		}
  
  		IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey,TValue>>.GetEnumerator()
  		{
  			return AsEnumerable().GetEnumerator();
  		}
  
  		/// <summary>
  		/// Inserts a new entry into the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> items with the specified key and source at the specified index.
  		/// </summary>
  		/// <param name="index">The zero-based index at which the element should be inserted.</param>
  		/// <param name="key">The key of the entry to add.</param>
  		/// <param name="source">The source of the entry to add. The source can be <null/> if the type of the values in the dictionary is a reference type.</param>
  		/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than 0.<br/>
  		/// -or-<br/>
  		/// <paramref name="index"/> is greater than <see cref="Count"/>.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="key"/> is <null/>.</exception>
  		/// <exception cref="ArgumentException">An element with the same key already exists in the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see>.</exception>
  		public void Insert(int index, TKey key, TValue value)
  		{
  			Contract.Assume(index >= 0);
  
  			lock (SyncRoot)
  			{
  				Contract.Assume(index <= Count);
  
  				Dictionary.Add(key, value);
  				Contract.Assume(index <= List.Count);
  				List.Insert(index, key);
  			}
  			OnItemChanged(Change.Inserted, index, key, value);
  		}
  
  		/// <summary>
  		/// Inserts a new entry into the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> items with the specified key and source at the specified index.
  		/// </summary>
  		/// <param name="index">The zero-based index at which the element should be inserted.</param>
  		/// <param name="key">The key of the entry to add.</param>
  		/// <param name="source">The source of the entry to add. The source can be <null/> if the type of the values in the dictionary is a reference type.</param>
  		/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than 0.<br/>
  		/// -or-<br/>
  		/// <paramref name="index"/> is greater than <see cref="Count"/>.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="key"/> is <null/>.<br/>
  		/// -or-<br/>
  		/// <paramref name="source"/> is <null/>, and the source type of the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> is a source type.</exception>
  		/// <exception cref="ArgumentException">The key type of the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> is not in the inheritance hierarchy of <paramref name="key"/>.<br/>
  		/// -or-<br/>
  		/// The source type of the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> is not in the inheritance hierarchy of <paramref name="source"/>.<br/>
  		/// -or-<br/>
  		/// An element with the same key already exists in the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see>.</exception>
  		void IOrderedDictionary.Insert(int index, object key, object value)
  		{
  			Contract.Assume(key != null);
  
  			Insert(index, ConvertToKeyType(key), ConvertToValueType(value));
  		}
  
  		/// <summary>
  		/// Removes the entry at the specified index from the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> items.
  		/// </summary>
  		/// <param name="index">The zero-based index of the entry to remove.</param>
  		/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than 0.<br/>
  		/// -or-<br/>
  		/// index is equal to or greater than <see cref="Count"/>.</exception>
  		public void RemoveAt(int index)
  		{
  			Contract.Assume(index >= 0);
  			TKey key;
  			TValue value;
  
  			lock (SyncRoot)
  			{
  				Contract.Assume(index < List.Count);
  
  				key = List[index];
  				value = Dictionary[key];
  
  				List.RemoveAt(index);
  				Dictionary.Remove(key);
  			}
  			OnItemChanged(Change.Removed, index, key, value);
  		}
  
  
  		/// <summary>
  		/// Gets or sets the source at the specified index.
  		/// </summary>
  		/// <param name="index">The zero-based index of the source to get or set.</param>
  		/// <source>The source of the item at the specified index.</source>
  		/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than 0.<br/>
  		/// -or-<br/>
  		/// index is equal to or greater than <see cref="Count"/>.</exception>
  		[ContractVerification(false)] // *** Avoid requiring a lock to verify count...
  		public TValue this[int index]
  		{
  			get
  			{
  				Contract.Assume(index >= 0);
  				//Contract.Assume(index < Count); // ***
  
  				return Dictionary[List[index]];
  			}
  
  			set
  			{
  				Contract.Assume(index >= 0);
  				TKey key;
  				bool changed = false;
  
  				lock (SyncRoot)
  				{
  					Contract.Assume(index < Count);
  
  					key = List[index];
  
  					changed = !Dictionary.ContainsKey(key) || !Dictionary[key].Equals(value);
  					if (changed)
  						Dictionary[key] = value;
  				}
  				if (changed)
  					OnItemChanged(Change.Modified, index, key, value);
  			}
  		}
  
  
  		/// <summary>
  		/// Gets or sets the source at the specified index.
  		/// </summary>
  		/// <param name="index">The zero-based index of the source to get or set.</param>
  		/// <source>The source of the item at the specified index.</source>
  		/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than 0.<br/>
  		/// -or-<br/>
  		/// index is equal to or greater than <see cref="Count"/>.</exception>
  		/// <exception cref="ArgumentNullException"><paramref name="valueObject"/> is a null reference, and the source type of the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> is a source type.</exception>
  		/// <exception cref="ArgumentException">The source type of the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> is not in the inheritance hierarchy of <paramref name="valueObject"/>.</exception>
  		object IOrderedDictionary.this[int index]
  		{
  			get
  			{
  				Contract.Assume(index >= 0);
  
  				return this[index];
  			}
  
  			set
  			{
  				Contract.Assume(index >= 0);
  
  				this[index] = ConvertToValueType(value);
  			}
  		}
  
  		/// <summary>
  		/// Adds an entry with the specified key and source into the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> items with the lowest available index.
  		/// </summary>
  		/// <param name="key">The key of the entry to add.</param>
  		/// <param name="source">The source of the entry to add. This source can be <null/>.</param>
  		/// <remarks>A key cannot be <null/>, but a source can be.
  		/// <para>You can also use the <see cref="P:OrderedDictionary{TKey,TValue}.Item(TKey)"/> property to add new elements by setting the source of a key that does not exist in the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> items; however, if the specified key already exists in the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see>, setting the <see cref="P:OrderedDictionary{TKey,TValue}.Item(TKey)"/> property overwrites the old source. In contrast, the <see cref="M:AddSynchronized"/> method does not modify existing elements.</para></remarks>
  		/// <exception cref="ArgumentNullException"><paramref name="key"/> is <null/></exception>
  		/// <exception cref="ArgumentException">An element with the same key already exists in the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see></exception>
  		void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
  		{
  			Add(key, value);
  		}
  
  		/// <summary>
  		/// Adds an entry with the specified key and source into the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> items with the lowest available index.
  		/// </summary>
  		/// <param name="key">The key of the entry to add.</param>
  		/// <param name="source">The source of the entry to add. This source can be <null/>.</param>
  		/// <returns>The index of the newly added entry</returns>
  		/// <remarks>A key cannot be <null/>, but a source can be.
  		/// <para>You can also use the <see cref="P:OrderedDictionary{TKey,TValue}.Item(TKey)"/> property to add new elements by setting the source of a key that does not exist in the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> items; however, if the specified key already exists in the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see>, setting the <see cref="P:OrderedDictionary{TKey,TValue}.Item(TKey)"/> property overwrites the old source. In contrast, the <see cref="M:AddSynchronized"/> method does not modify existing elements.</para></remarks>
  		/// <exception cref="ArgumentNullException"><paramref name="key"/> is <null/></exception>
  		/// <exception cref="ArgumentException">An element with the same key already exists in the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see></exception>
  		public int Add(TKey key, TValue value)
  		{
  			int count;
  			lock (SyncRoot)
  				count = AddInternal(key,value);
  			return count;
  		}
  
  		private int AddInternal(TKey key, TValue value)
  		{
  			Dictionary.Add(key, value);
  			List.Add(key);
  			return Count;
  		}
  
  		/// <summary>
  		/// Adds an entry with the specified key and source into the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> items with the lowest available index.
  		/// </summary>
  		/// <param name="key">The key of the entry to add.</param>
  		/// <param name="source">The source of the entry to add. This source can be <null/>.</param>
  		/// <exception cref="ArgumentNullException"><paramref name="key"/> is <null/>.<br/>
  		/// -or-<br/>
  		/// <paramref name="source"/> is <null/>, and the source type of the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> is a source type.</exception>
  		/// <exception cref="ArgumentException">The key type of the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> is not in the inheritance hierarchy of <paramref name="key"/>.<br/>
  		/// -or-<br/>
  		/// The source type of the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> is not in the inheritance hierarchy of <paramref name="source"/>.</exception>
  		void IDictionary.Add(object key, object value)
  		{
  			Contract.Assert(key != null);
  
  			Add(ConvertToKeyType(key), ConvertToValueType(value));
  		}
  
  		/// <summary>
  		/// Removes all elements from the <see cref="OrderedDictionary{TKey,TValue}">OrderedDictionary&lt;TKey,TValue&gt;</see> items.
  		/// </summary>
  		/// <remarks>The capacity is not changed as a response of calling this method.</remarks>
  		public void Clear()
  		{
  			lock (SyncRoot)
  			{
  				OnBeforeCleared(EventArgs.Empty);
  				Dictionary.Clear();
  				List.Clear();
  				Contract.Assume(Count == 0);
  				OnAfterCleared(EventArgs.Empty);
  			}
  			
  		}
  
  		public event EventHandler BeforeCleared;
  		protected virtual void OnBeforeCleared(EventArgs e)
  		{
  			var handler = BeforeCleared;
  			if (handler != null)
  				handler(this,e);
  		}
  
  		public event EventHandler AfterCleared;
  		protected virtual void OnAfterCleared(EventArgs e)
  		{
  			var handler = AfterCleared;
  
gt: 			if (handler != null)