Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

A KeyedList implementation

, 24 Dec 2003
A KeyedList implements an ordered key-value list.
keyedlist_src.zip
using System;
using System.Collections;

namespace System.Collections
{
	public interface IOrderedDictionary
	{
		void Insert(Int32 index, Object key, Object value);
		void RemoveAt(Int32 index);
	}

	[Serializable]
	public class KeyedList : ICollection, IDictionary, IEnumerable, IOrderedDictionary
	{
		private Hashtable objectTable = new Hashtable ();
		private ArrayList objectList = new ArrayList ();

		public void Add (object key, object value)
		{
			objectTable.Add (key, value);
			objectList.Add (new DictionaryEntry (key, value));
		}

		public void Clear ()
		{
			objectTable.Clear ();
			objectList.Clear ();
		}

		public bool Contains (object key)
		{
			return objectTable.Contains (key);
		}

		public void CopyTo (Array array, int idx)
		{
			objectTable.CopyTo (array, idx);
		}

		public void Insert (int idx, object key, object value)
		{
			if (idx > Count)
				throw new ArgumentOutOfRangeException ("index");

			objectTable.Add (key, value);
			objectList.Insert (idx, new DictionaryEntry (key, value));
		}

		public void Remove (object key)
		{
			objectTable.Remove (key);
			objectList.RemoveAt (IndexOf (key));
		}

		public void RemoveAt (int idx)
		{
			if (idx >= Count)
				throw new ArgumentOutOfRangeException ("index");

			objectTable.Remove ( ((DictionaryEntry)objectList[idx]).Key );
			objectList.RemoveAt (idx);
		}

		IDictionaryEnumerator IDictionary.GetEnumerator ()
		{
			return new KeyedListEnumerator (objectList);
		}

		IEnumerator IEnumerable.GetEnumerator ()
		{
			return new KeyedListEnumerator (objectList);
		}

		public int Count 
		{
			get { return objectList.Count; }
		}

		public bool IsFixedSize 
		{
			get { return false; }
		}

		public bool IsReadOnly 
		{
			get { return false; }
		}

		public bool IsSynchronized 
		{
			get { return false; }
		}

		public object this[int idx] 
		{
			get { return ((DictionaryEntry) objectList[idx]).Value; }
			set 
			{
				if (idx < 0 || idx >= Count)
					throw new ArgumentOutOfRangeException ("index");

				object key = ((DictionaryEntry) objectList[idx]).Key;
				objectList[idx] = new DictionaryEntry (key, value);
				objectTable[key] = value;
			}
		}

		public object this[object key] 
		{
			get { return objectTable[key]; }
			set 
			{
				if (objectTable.Contains (key))
				{
					objectTable[key] = value;
					objectTable[IndexOf (key)] = new DictionaryEntry (key, value);
					return;
				}
				Add (key, value);
			}
		}

		public ICollection Keys 
		{
			get 
			{ 
				ArrayList retList = new ArrayList ();
				for (int i = 0; i < objectList.Count; i++)
				{
					retList.Add ( ((DictionaryEntry)objectList[i]).Key );
				}
				return retList;
			}
		}

		public ICollection Values 
		{
			get 
			{
				ArrayList retList = new ArrayList ();
				for (int i = 0; i < objectList.Count; i++)
				{
					retList.Add ( ((DictionaryEntry)objectList[i]).Value );
				}
				return retList;
			}
		}
	
		public object SyncRoot 
		{
			get { return this; }
		}	

		private int IndexOf (object key)
		{
			for (int i = 0; i < objectList.Count; i++)
			{
				if (((DictionaryEntry) objectList[i]).Key.Equals (key))
				{
					return i;
				}
			}
			return -1;
		}
	}

	public class KeyedListEnumerator : IDictionaryEnumerator
	{
		private int index = -1;
		private ArrayList objs;

		internal KeyedListEnumerator (ArrayList list)
		{
			objs = list;
		}

		public bool MoveNext ()
		{
			index++;
			if (index >= objs.Count)
				return false;

			return true;
		}

		public void Reset ()
		{
			index = -1;
		}

		public object Current 
		{
			get 
			{
				if (index < 0 || index >= objs.Count)
					throw new InvalidOperationException ();

				return objs[index];
			}
		}

		public DictionaryEntry Entry 
		{
			get 
			{
				return (DictionaryEntry) Current;
			}
		}

		public object Key 
		{
			get 
			{
				return Entry.Key;
			}
		}

		public object Value 
		{
			get 
			{
				return Entry.Value;
			}
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Marc Clifton

United States United States
Marc is the creator of two open source projets, MyXaml, a declarative (XML) instantiation engine and the Advanced Unit Testing framework, and Interacx, a commercial n-tier RAD application suite.  Visit his website, www.marcclifton.com, where you will find many of his articles and his blog.
 
Marc lives in Philmont, NY.

| Advertise | Privacy | Mobile
Web04 | 2.8.141022.2 | Last Updated 25 Dec 2003
Article Copyright 2003 by Marc Clifton
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid