Click here to Skip to main content
15,868,141 members
Articles / Web Development / ASP.NET
Article

A Dictionary Collection Sorting By Value

Rate me:
Please Sign up or sign in to vote.
4.25/5 (10 votes)
6 May 20042 min read 144.8K   228   40   14
An article on creating a custom collection like the SortedList that sort entries by value instead of by key.

Introduction

The classes provided in this article illustrate how to create a custom collection similar to the System.Collections.SortedList collection, but the collection created here will sort items by value instead of by key like the SortedList.

Background

In one of my major projects, I created a custom field control capable of rendering actual ASP.NET controls based on its fieldtype property. One of the field-types is dropdown which renders a combo box that is bound to a SortedList for its values.

This implementation worked fairly well but it soon became obvious that using a SortedList was not the best choice since elements displayed in the combo box are sorted by key instead of by value.

To solve this problem, I searched through MSDN for a solution and did some Googling. I found out that I was not the only person with this problem!

Nowhere did I find a good solution to my problem, but found a good article written by Marc Clifton which I used as a roadmap for developing the collection shown in this article.

Using the code

The LookupCollection is used exactly like the SortedList provided by Microsoft but, as mentioned in the introduction, it will sort items by value instead of by key. The main purpose I use this collection for is to serve as a data source for a DropDownList on an ASP.NET page, as shown in the code snippet below:

C#
LookupCollection collection = new LookupCollection();

collection.Clear();
collection.Add("002", "Hertzogville");
collection.Add("005", "Bloemfontein");
collection.Add("HER", "Herman");
collection.Add("001", "Kimberley");
collection.Add("012", "Bothaville");
collection.Add("HAN", "Hannes");

this.lstResults.DataSource     = collection;
this.lstResults.DataValueField = "key";
this.lstResults.DataTextField  = "value";
this.lstResults.DataBind();

Unit Test

Perhaps a more thorough illustration on how to use the code can be seen by examining the Unit Test class developed with NUnit.

C#
using System;
using System.Collections;
using NUnit.Framework;

namespace CustomCollection {
    [TestFixture]
    public class LookupCollectionTest {
        private LookupCollection collection;

        //---------------------------------------------------------------------
        // Init
        //---------------------------------------------------------------------
        [SetUp] 
        public void Init() {
            this.collection = new LookupCollection();

        }

        //---------------------------------------------------------------------
        // TestAdd
        //---------------------------------------------------------------------
        [Test]
        public void TestAdd() {
            this.collection.Clear();
            this.collection.Add("002", "Hertzogville");
            this.collection.Add("005", "Bloemfontein");
            this.collection.Add("001", "Kimberley");
            this.collection.Add("FRA", "Francisca");


            Assert.AreEqual(4, this.collection.Count);

            this.collection.Clear();
            Assert.AreEqual(0, this.collection.Count);
        }

        //---------------------------------------------------------------------
        // TestClear
        //---------------------------------------------------------------------
        [Test]
        public void TestClear() {
            this.collection.Add("T1",   "Test");
            this.collection.Add("TEST", "ATEST");
            this.collection.Add("1",    "1");

            this.collection.Clear();
            Assert.AreEqual(0, this.collection.Count);
        }

        //---------------------------------------------------------------------
        // TestContains
        //---------------------------------------------------------------------
        [Test]
        public void TestContains() {
            this.collection.Clear();
            this.collection.Add("HER", "Herman");
            this.collection.Add("HAN", "Hannes");
            this.collection.Add("ELA", "Elaine");
            this.collection.Add("FRA", "Francisca");
            this.collection.Add("002", "Hertzogville");
            this.collection.Add("005", "Bloemfontein");


            Assert.IsTrue(this.collection.Contains("FRA"));
            Assert.IsTrue(this.collection.Contains("HAN"));
            Assert.IsTrue(this.collection.Contains("002"));
            Assert.IsFalse(this.collection.Contains("NON"));
        }

        //---------------------------------------------------------------------
        // TestCopyTo
        //---------------------------------------------------------------------
        [Test]
        public void TestCopyTo() {
            this.collection.Clear();
            this.collection.Add("HER", "Herman");
            this.collection.Add("HAN", "Hannes");
            this.collection.Add("ELA", "Elaine");
            this.collection.Add("FRA", "Francisca");

            Lookup[] testArray = new Lookup[4];
            Assert.IsNull(testArray[0]);
            Assert.IsNull(testArray[3]);

            this.collection.CopyTo(testArray, 0);
            Assert.IsNotNull(testArray[0]);
            Assert.IsNotNull(testArray[3]);
        }

        //---------------------------------------------------------------------
        // TestGetEnumerator
        //---------------------------------------------------------------------
        [Test]
        public void TestGetEnumerator() {
            this.collection.Clear();
            this.collection.Add("002", "Hertzogville");
            this.collection.Add("005", "Bloemfontein");
            this.collection.Add("HER", "Herman");
            this.collection.Add("001", "Kimberley");
            this.collection.Add("012", "Bothaville");
            this.collection.Add("HAN", "Hannes");

            IDictionaryEnumerator enumurator = this.collection.GetEnumerator();

            enumurator.MoveNext(); Assert.AreEqual("Bloemfontein", 
                            ((Lookup)enumurator.Current).Value);
            enumurator.MoveNext(); Assert.AreEqual("Bothaville", 
                            ((Lookup)enumurator.Current).Value);
            enumurator.MoveNext(); Assert.AreEqual("Hannes",   
                            ((Lookup)enumurator.Current).Value);
            enumurator.MoveNext(); Assert.AreEqual("Herman", 
                            ((Lookup)enumurator.Current).Value);
            enumurator.MoveNext(); Assert.AreEqual("Hertzogville", 
                            ((Lookup)enumurator.Current).Value);
            enumurator.MoveNext(); Assert.AreEqual("Kimberley", 
                            ((Lookup)enumurator.Current).Value);
        }

        //---------------------------------------------------------------------
        // TestRemove
        //---------------------------------------------------------------------
        [Test]
        public void TestRemove() {
            this.collection.Clear();
            this.collection.Add("002", "Hertzogville");
            this.collection.Add("005", "Bloemfontein");
            this.collection.Add("001", "Kimberley");

            this.collection.Remove("005");
            Assert.AreEqual(2, this.collection.Count);

            this.collection.Remove("004");
            Assert.AreEqual(2, this.collection.Count);

            this.collection.Remove("002");
            Assert.AreEqual(1, this.collection.Count);
        }

        //=====================================================================
        // PROPERTIES
        //=====================================================================
        //---------------------------------------------------------------------
        // TestCount
        //---------------------------------------------------------------------
        [Test]
        public void TestCount() {
            this.collection.Clear();
            Assert.AreEqual(this.collection.Count, 0);

            for (int i = 0; i < 100; i++) {
                this.collection.Add(i.ToString(), i + " Item");
            }

            Assert.AreEqual(this.collection.Count, 100);
        }

        //---------------------------------------------------------------------
        // TestIndexer
        //---------------------------------------------------------------------
        [Test]
        public void TestIndexer() {
            this.collection.Clear();
            this.collection.Add("002", "Hertzogville");
            this.collection.Add("005", "Bloemfontein");
            this.collection.Add("001", "Kimberley");
            this.collection.Add("012", "Bothaville");

            Assert.IsTrue(this.collection.Contains("001"));
            Assert.AreEqual("Kimberley", this.collection["001"]);

            Assert.IsTrue(this.collection.Contains("002"));
            Assert.AreEqual("Hertzogville", this.collection["002"]);
        }

        //---------------------------------------------------------------------
        // TestKeys
        //---------------------------------------------------------------------
        [Test]
        public void TestKeys() {
            this.collection.Clear();
            this.collection.Add("002", "Hertzogville");
            this.collection.Add("005", "Bloemfontein");
            this.collection.Add("HER", "Herman");
            this.collection.Add("001", "Kimberley");
            this.collection.Add("012", "Bothaville");
            this.collection.Add("HAN", "Hannes");

            ArrayList keys = (ArrayList)this.collection.Keys;
            Assert.AreEqual("005", keys[0]);
            Assert.AreEqual("012", keys[1]);
            Assert.AreEqual("HAN", keys[2]);
            Assert.AreEqual("HER", keys[3]);
            Assert.AreEqual("002", keys[4]);
            Assert.AreEqual("001", keys[5]);

        }

        //---------------------------------------------------------------------
        // TestValues
        //---------------------------------------------------------------------
        [Test]
        public void TestValues() {
            this.collection.Clear();
            this.collection.Add("002", "Hertzogville");
            this.collection.Add("005", "Bloemfontein");
            this.collection.Add("HER", "Herman");
            this.collection.Add("001", "Kimberley");
            this.collection.Add("012", "Bothaville");
            this.collection.Add("HAN", "Hannes");

            ArrayList values = (ArrayList)this.collection.Values;
            Assert.AreEqual("Bloemfontein", values[0]);
            Assert.AreEqual("Bothaville",   values[1]);
            Assert.AreEqual("Hannes",       values[2]);
            Assert.AreEqual("Herman",       values[3]);
            Assert.AreEqual("Hertzogville", values[4]);
            Assert.AreEqual("Kimberley",    values[5]);
        }
    }
}

Lookup

The Lookup class illustrated below is used to store a key-value pair in the LookupCollection, I do however think (hope) that some smart programmer will have something to say about the implementation of ToDictionaryEntry and CompareTo, and can't wait for feedback!

C#
using System;
using System.Collections;

namespace CustomCollection {
    [Serializable]
    public class Lookup : IComparable {
        private object mKey;
        private object mValue;

        //---------------------------------------------------------------------
        // Default Constructor
        //---------------------------------------------------------------------
        public Lookup() : this(null, null) {
        }

        //---------------------------------------------------------------------
        // Overloaded Constructor
        //---------------------------------------------------------------------
        public Lookup(object key, object value) {
            this.Key   = key;
            this.Value = value;
        }

        //---------------------------------------------------------------------
        // CompareTo
        //---------------------------------------------------------------------
        public int CompareTo(object obj) {
            int result = 0;

            if (obj is Lookup) {
             result = 
              ((IComparable)this.Value).CompareTo((IComparable)
                                         (((Lookup)obj).Value));
            }

            return result;
        }

        //---------------------------------------------------------------------
        // ToDictionaryEntry
        //---------------------------------------------------------------------
        public DictionaryEntry ToDictionaryEntry() {
            return new DictionaryEntry(this.Key, this.Value);
        }

        //=====================================================================
        // PROPERTIES
        //=====================================================================
        public object Key {
            get {
                return this.mKey;
            }
            set {
                if (this.mKey != value) {
                    this.mKey = value;
                }
            }
        }

        public object Value {
            get {
                return this.mValue;
            }
            set {
                if (this.mValue != value) {
                    this.mValue = value;
                }
            }
        }
    }
}

Enumerator

The enumerator class is used by the LookupCollection class to create an enumerator that will allow programmers to use the foreach loop on this collection.

C#
using System;
using System.Collections;

namespace CustomCollection {
    public class LookupEnumerator : IDictionaryEnumerator {
        private int       index = -1;
        private ArrayList items;

        //---------------------------------------------------------------------
        // Constructor
        //---------------------------------------------------------------------
        public LookupEnumerator(ArrayList list) {
            this.items = list;
        }

        //---------------------------------------------------------------------
        // MoveNext
        //---------------------------------------------------------------------
        public bool MoveNext() {
            this.index++;
            if (index >= this.items.Count)
                return false;

            return true;
        }

        //=====================================================================
        // PROPERTIES
        //=====================================================================
        //---------------------------------------------------------------------
        // Reset
        //---------------------------------------------------------------------
        public void Reset() {
            this.index = -1;
        }

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

                return this.items[index];
            }
        }

        //---------------------------------------------------------------------
        // Entry
        //---------------------------------------------------------------------
        public DictionaryEntry Entry {
            get {
                return ((Lookup)this.Current).ToDictionaryEntry();
            }
        }

        //---------------------------------------------------------------------
        // Key
        //---------------------------------------------------------------------
        public object Key {
            get {
                return this.Entry.Key;
            }
        }

        //---------------------------------------------------------------------
        // Value
        //---------------------------------------------------------------------
        public object Value {
            get {
                return this.Entry.Value;
            }
        }
    }
}

LookupCollection

This is the actual class that implements the collection that this article is all about. As can be seen from the code, dictionary entries added to this collection are stored internally in an ArrayList of Lookup items.

C#
using System;
using System.Collections;

namespace CustomCollection {

    [Serializable]
    public class LookupCollection : ICollection, IDictionary, IEnumerable {
        private ArrayList mItems = new ArrayList();

        //---------------------------------------------------------------------
        // Constructor
        //---------------------------------------------------------------------
        public LookupCollection() {
        }

        //---------------------------------------------------------------------
        // Add
        //---------------------------------------------------------------------
        public void Add(object key, object value) {
            // do some validation
            if (key == null)
              throw new ArgumentNullException("key is a null reference");
            else if (this.Contains(key))
              throw new 
               ArgumentException("An element with the same key already exists");

            // add the new item
            Lookup newItem = new Lookup();
    
            newItem.Key   = key;
            newItem.Value = value;

            this.mItems.Add(newItem);
            this.mItems.Sort();
        }

        //---------------------------------------------------------------------
        // Clear
        //---------------------------------------------------------------------
        public void Clear() {
            this.mItems.Clear();
        }

        //---------------------------------------------------------------------
        // Contains
        //---------------------------------------------------------------------
        public bool Contains(object key) {
            return (this.GetByKey(key) != null);
        }

        //---------------------------------------------------------------------
        // CopyTo
        //---------------------------------------------------------------------
        public void CopyTo(Array array, int index) {
            this.mItems.CopyTo(array, index);
        }

        //---------------------------------------------------------------------
        // GetEnumerator (1)
        //---------------------------------------------------------------------
        public IDictionaryEnumerator GetEnumerator() {
            return new LookupEnumerator(this.mItems);
        }

        //---------------------------------------------------------------------
        // GetEnumerator (2)
        //---------------------------------------------------------------------
        IEnumerator IEnumerable.GetEnumerator() {
            return new LookupEnumerator(this.mItems);
        }

        //---------------------------------------------------------------------
        // Remove
        //---------------------------------------------------------------------
        public void Remove(object key) {
            if (key == null)
                throw new ArgumentNullException("key is a null reference");

            Lookup deleteItem = this.GetByKey(key);
            if (deleteItem != null) {
                this.mItems.Remove(deleteItem);
                this.mItems.Sort();
            }
        }

        //=====================================================================
        // PRIVATE
        //=====================================================================
        private Lookup GetByKey(object key) {
            Lookup    result   = null;
            int       keyIndex = -1;
            ArrayList keys     = (ArrayList)this.Keys;

            if (this.mItems.Count > 0) {
                keyIndex = keys.IndexOf(key);

                if (keyIndex >= 0) {
                    result = (Lookup)this.mItems[keyIndex];
                }
            }

            return result;
        }

        //=====================================================================
        // PROPERTIES
        //=====================================================================
        public int Count { 
            get {
                return this.mItems.Count;
            }
        }
        
        public bool IsSynchronized { 
            get {
                return false;
            }
        }

        public object SyncRoot { 
            get {
                return this;
            }
        }

        public bool IsFixedSize { 
            get {
                return false;
            } 
        }

        public bool IsReadOnly {
            get {
                return false;
            } 
        }

        public object this[object key] {
            get {

                if (key == null)
                    throw new ArgumentNullException("key is a null reference");

                object result = null;

                Lookup findItem = this.GetByKey(key);
                if (findItem != null) {
                    result = findItem.Value;
                }

                return result;
            }
            set {
            }
        }

        public ICollection Keys {
            get {
                ArrayList result = new ArrayList();

                this.mItems.Sort();

                foreach (Lookup curItem in this.mItems) {
                    result.Add(curItem.Key);
                }

                return result;
            }
        }

        public ICollection Values {
            get {
                ArrayList result = new ArrayList();

                foreach (Lookup curItem in this.mItems) {
                    result.Add(curItem.Value);
                }

                return result;
            }
        }
    }
}

Conclusion

Although I am quite sure that my implementation is not the best one, I hope that you find these classes at least somewhat useful, or that they will help to point you in the right direction.

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


Written By
Web Developer
South Africa South Africa

Comments and Discussions

 
GeneralMarc Clifton's Link is broke Pin
DaveAuld15-May-10 9:35
professionalDaveAuld15-May-10 9:35 
GeneralThe author forgot one important part Pin
irnbru10-Oct-07 23:32
irnbru10-Oct-07 23:32 
GeneralRe: The author forgot one important part Pin
VCSKicks24-Sep-08 12:25
VCSKicks24-Sep-08 12:25 
JokeBloemfontein Pin
ajheunis5-May-06 0:33
ajheunis5-May-06 0:33 
JokeRe: Bloemfontein Pin
Hannes Foulds24-Jun-07 22:13
Hannes Foulds24-Jun-07 22:13 
GeneralCopy the SortedList Pin
howcheng11-Jun-04 11:46
howcheng11-Jun-04 11:46 
GeneralRe: Copy the SortedList Pin
BradVincent27-Sep-04 3:46
BradVincent27-Sep-04 3:46 
howcheng wrote:
one could use Lutz Roeder's .NET Reflector[^] and view the decompiled code for SortedList and make a few changes to sort by value instead

I did this and here is the working code :
<br />
namespace Custom.Collections<br />
{<br />
	using System;<br />
	using System.Reflection;<br />
	using System.Collections;<br />
<br />
	[Serializable]<br />
	public class SortedListByValue : IDictionary, ICollection, IEnumerable, ICloneable<br />
	{<br />
		// Methods<br />
		public SortedListByValue()<br />
		{<br />
			this.keys = new object[0x10];<br />
			this.values = new object[0x10];<br />
			this.comparer = new SortedByListDefaultComparer();<br />
		}<br />
<br />
		public SortedListByValue(IComparer comparer) : this()<br />
		{<br />
			if (comparer != null)<br />
			{<br />
				this.comparer = comparer;<br />
			}<br />
		}<br />
<br />
		public SortedListByValue(IDictionary d) : this(d, (IComparer) null)<br />
		{<br />
		}<br />
<br />
		public SortedListByValue(int initialCapacity)<br />
		{<br />
			if (initialCapacity < 0)<br />
			{<br />
				throw new ArgumentOutOfRangeException("initialCapacity"); //, Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));<br />
			}<br />
			this.keys = new object[initialCapacity];<br />
			this.values = new object[initialCapacity];<br />
			this.comparer = new SortedByListDefaultComparer();<br />
		}<br />
<br />
		public SortedListByValue(IComparer comparer, int capacity) : this(comparer)<br />
		{<br />
			this.Capacity = capacity;<br />
		}<br />
<br />
		public SortedListByValue(IDictionary d, IComparer comparer) : this(comparer, (d != null) ? d.Count : 0)<br />
		{<br />
			if (d == null)<br />
			{<br />
				throw new ArgumentNullException("d"); //, Environment.GetResourceString("ArgumentNull_Dictionary"));<br />
			}<br />
			d.Keys.CopyTo(this.keys, 0);<br />
			d.Values.CopyTo(this.values, 0);<br />
			Array.Sort(this.keys, this.values, comparer);<br />
			this._size = d.Count;<br />
		}<br />
<br />
		public virtual void Add(object key, object value)<br />
		{<br />
			if (key == null)<br />
			{<br />
				throw new ArgumentNullException("key"); //, Environment.GetResourceString("ArgumentNull_Key"));<br />
			}<br />
			int num1 = Array.BinarySearch(this.values,  0, this._size, value, this.comparer);<br />
			if (num1 >= 0)<br />
			{<br />
				object[] objArray1 = new object[2] { this.GetKey(num1), key } ;<br />
				throw new ArgumentException("Cannot add duplicate key"); //(Environment.GetResourceString("Argument_AddingDuplicate__", objArray1));<br />
			}<br />
			this.Insert(~num1, key, value);<br />
		}<br />
<br />
		public virtual void Clear()<br />
		{<br />
			this.version++;<br />
			this._size = 0;<br />
			this.keys = new object[0x10];<br />
			this.values = new object[0x10];<br />
		}<br />
<br />
		public virtual object Clone()<br />
		{<br />
			SortedListByValue list1 = new SortedListByValue(this._size);<br />
			Array.Copy(this.keys, 0, list1.keys, 0, this._size);<br />
			Array.Copy(this.values, 0, list1.values, 0, this._size);<br />
			list1._size = this._size;<br />
			list1.version = this.version;<br />
			list1.comparer = this.comparer;<br />
			return list1;<br />
		}<br />
<br />
		public virtual bool Contains(object key)<br />
		{<br />
			return (this.IndexOfKey(key) >= 0);<br />
		}<br />
<br />
		public virtual bool ContainsKey(object key)<br />
		{<br />
			return (this.IndexOfKey(key) >= 0);<br />
		}<br />
<br />
		public virtual bool ContainsValue(object value)<br />
		{<br />
			return (this.IndexOfValue(value) >= 0);<br />
		}<br />
<br />
		public virtual void CopyTo(Array array, int arrayIndex)<br />
		{<br />
			if (array == null)<br />
			{<br />
				throw new ArgumentNullException("array"); //, Environment.GetResourceString("ArgumentNull_Array"));<br />
			}<br />
			if (array.Rank != 1)<br />
			{<br />
				throw new ArgumentException(); //Environment.GetResourceString("Arg_RankMultiDimNotSupported"));<br />
			}<br />
			if (arrayIndex < 0)<br />
			{<br />
				throw new ArgumentOutOfRangeException("arrayIndex"); //, Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));<br />
			}<br />
			if ((array.Length - arrayIndex) < this.Count)<br />
			{<br />
				throw new ArgumentException(); //Environment.GetResourceString("Arg_ArrayPlusOffTooSmall"));<br />
			}<br />
			for (int num1 = 0; num1 < this.Count; num1++)<br />
			{<br />
				DictionaryEntry entry1;<br />
				entry1 = new DictionaryEntry(this.keys[num1], this.values[num1]);<br />
				array.SetValue(entry1, (int) (num1 + arrayIndex));<br />
			}<br />
		}<br />
<br />
		private void EnsureCapacity(int min)<br />
		{<br />
			int num1 = (this.keys.Length == 0) ? 0x10 : (this.keys.Length * 2);<br />
			if (num1 < min)<br />
			{<br />
				num1 = min;<br />
			}<br />
			this.Capacity = num1;<br />
		}<br />
<br />
		public virtual object GetByIndex(int index)<br />
		{<br />
			if ((index < 0) || (index >= this._size))<br />
			{<br />
				throw new ArgumentOutOfRangeException("index"); //, Environment.GetResourceString("ArgumentOutOfRange_Index"));<br />
			}<br />
			return this.values[index];<br />
		}<br />
<br />
		public virtual IDictionaryEnumerator GetEnumerator()<br />
		{<br />
			return new SortedListByValue.SortedListEnumerator(this, 0, this._size, 3);<br />
		}<br />
<br />
		public virtual object GetKey(int index)<br />
		{<br />
			if ((index < 0) || (index >= this._size))<br />
			{<br />
				throw new ArgumentOutOfRangeException("index"); //, Environment.GetResourceString("ArgumentOutOfRange_Index"));<br />
			}<br />
			return this.keys[index];<br />
		}<br />
<br />
		public virtual IList GetKeyList()<br />
		{<br />
			if (this.keyList == null)<br />
			{<br />
				this.keyList = new KeyList(this);<br />
			}<br />
			return this.keyList;<br />
		}<br />
<br />
		public virtual IList GetValueList()<br />
		{<br />
			if (this.valueList == null)<br />
			{<br />
				this.valueList = new ValueList(this);<br />
			}<br />
			return this.valueList;<br />
		}<br />
<br />
		public virtual int IndexOfKey(object key)<br />
		{<br />
			if (key == null)<br />
			{<br />
				throw new ArgumentNullException("key"); //, Environment.GetResourceString("ArgumentNull_Key"));<br />
			}<br />
			int num1 = Array.BinarySearch(this.keys, 0, this._size, key, this.comparer);<br />
			if (num1 < 0)<br />
			{<br />
				return -1;<br />
			}<br />
			return num1;<br />
		}<br />
<br />
		public virtual int IndexOfValue(object value)<br />
		{<br />
			return Array.IndexOf(this.values, value, 0, this._size);<br />
		}<br />
<br />
		private void Insert(int index, object key, object value)<br />
		{<br />
			if (this._size == this.keys.Length)<br />
			{<br />
				this.EnsureCapacity(this._size + 1);<br />
			}<br />
			if (index < this._size)<br />
			{<br />
				Array.Copy(this.keys, index, this.keys, (int) (index + 1), (int) (this._size - index));<br />
				Array.Copy(this.values, index, this.values, (int) (index + 1), (int) (this._size - index));<br />
			}<br />
			this.keys[index] = key;<br />
			this.values[index] = value;<br />
			this._size++;<br />
			this.version++;<br />
		}<br />
<br />
		public virtual void Remove(object key)<br />
		{<br />
			int num1 = this.IndexOfKey(key);<br />
			if (num1 >= 0)<br />
			{<br />
				this.RemoveAt(num1);<br />
			}<br />
		}<br />
<br />
		public virtual void RemoveAt(int index)<br />
		{<br />
			if ((index < 0) || (index >= this._size))<br />
			{<br />
				throw new ArgumentOutOfRangeException("index"); //, Environment.GetResourceString("ArgumentOutOfRange_Index"));<br />
			}<br />
			this._size--;<br />
			if (index < this._size)<br />
			{<br />
				Array.Copy(this.keys, (int) (index + 1), this.keys, index, (int) (this._size - index));<br />
				Array.Copy(this.values, (int) (index + 1), this.values, index, (int) (this._size - index));<br />
			}<br />
			this.keys[this._size] = null;<br />
			this.values[this._size] = null;<br />
			this.version++;<br />
		}<br />
<br />
		public virtual void SetByIndex(int index, object value)<br />
		{<br />
			if ((index < 0) || (index >= this._size))<br />
			{<br />
				throw new ArgumentOutOfRangeException("index"); //, Environment.GetResourceString("ArgumentOutOfRange_Index"));<br />
			}<br />
			this.values[index] = value;<br />
			this.version++;<br />
		}<br />
<br />
		public static SortedListByValue Synchronized(SortedListByValue list)<br />
		{<br />
			if (list == null)<br />
			{<br />
				throw new ArgumentNullException("list");<br />
			}<br />
			return new SyncSortedList(list);<br />
		}<br />
<br />
		IEnumerator IEnumerable.GetEnumerator()<br />
		{<br />
			return new SortedListByValue.SortedListEnumerator(this, 0, this._size, 3);<br />
		}<br />
<br />
		public virtual void TrimToSize()<br />
		{<br />
			this.Capacity = this._size;<br />
		}<br />
<br />
<br />
		// Properties<br />
		public virtual int Capacity<br />
		{<br />
			get<br />
			{<br />
				return this.keys.Length;<br />
			}<br />
			set<br />
			{<br />
				if (value != this.keys.Length)<br />
				{<br />
					if (value < this._size)<br />
					{<br />
						throw new ArgumentOutOfRangeException("value"); //, Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity"));<br />
					}<br />
					if (value > 0)<br />
					{<br />
						object[] objArray1 = new object[value];<br />
						object[] objArray2 = new object[value];<br />
						if (this._size > 0)<br />
						{<br />
							Array.Copy(this.keys, 0, objArray1, 0, this._size);<br />
							Array.Copy(this.values, 0, objArray2, 0, this._size);<br />
						}<br />
						this.keys = objArray1;<br />
						this.values = objArray2;<br />
					}<br />
					else<br />
					{<br />
						this.keys = new object[0x10];<br />
						this.values = new object[0x10];<br />
					}<br />
				}<br />
			}<br />
		}<br />
<br />
		public virtual int Count<br />
		{<br />
			get<br />
			{<br />
				return this._size;<br />
			}<br />
		}<br />
<br />
		public virtual bool IsFixedSize<br />
		{<br />
			get<br />
			{<br />
				return false;<br />
			}<br />
		}<br />
<br />
		public virtual bool IsReadOnly<br />
		{<br />
			get<br />
			{<br />
				return false;<br />
			}<br />
		}<br />
<br />
		public virtual bool IsSynchronized<br />
		{<br />
			get<br />
			{<br />
				return false;<br />
			}<br />
		}<br />
<br />
		public virtual object this[object key]<br />
		{<br />
			get<br />
			{<br />
				int num1 = this.IndexOfKey(key);<br />
				if (num1 >= 0)<br />
				{<br />
					return this.values[num1];<br />
				}<br />
				return null;<br />
			}<br />
			set<br />
			{<br />
				if (key == null)<br />
				{<br />
					throw new ArgumentNullException("key"); //, Environment.GetResourceString("ArgumentNull_Key"));<br />
				}<br />
				int num1 = Array.BinarySearch(this.keys, 0, this._size, key, this.comparer);<br />
				if (num1 >= 0)<br />
				{<br />
					this.values[num1] = value;<br />
					this.version++;<br />
				}<br />
				else<br />
				{<br />
					this.Insert(~num1, key, value);<br />
				}<br />
			}<br />
		}<br />
<br />
		public virtual ICollection Keys<br />
		{<br />
			get<br />
			{<br />
				return this.GetKeyList();<br />
			}<br />
		}<br />
<br />
		public virtual object SyncRoot<br />
		{<br />
			get<br />
			{<br />
				return this;<br />
			}<br />
		}<br />
<br />
		public virtual ICollection Values<br />
		{<br />
			get<br />
			{<br />
				return this.GetValueList();<br />
			}<br />
		}<br />
<br />
<br />
		// Fields<br />
		private const int _defaultCapacity = 0x10;<br />
		private int _size;<br />
		private IComparer comparer;<br />
		private KeyList keyList;<br />
		private object[] keys;<br />
		private ValueList valueList;<br />
		private object[] values;<br />
		private int version;<br />
<br />
		// Nested Types<br />
		[Serializable]<br />
			private class KeyList : IList, ICollection, IEnumerable<br />
		{<br />
			// Methods<br />
			internal KeyList(SortedListByValue sortedList)<br />
			{<br />
				this.sortedList = sortedList;<br />
			}<br />
<br />
			public virtual int Add(object key)<br />
			{<br />
				throw new NotSupportedException(); //Environment.GetResourceString("NotSupported_SortedListNestedWrite"));<br />
			}<br />
<br />
			public virtual void Clear()<br />
			{<br />
				throw new NotSupportedException(); //Environment.GetResourceString("NotSupported_SortedListNestedWrite"));<br />
			}<br />
<br />
			public virtual bool Contains(object key)<br />
			{<br />
				return this.sortedList.Contains(key);<br />
			}<br />
<br />
			public virtual void CopyTo(Array array, int arrayIndex)<br />
			{<br />
				if ((array != null) && (array.Rank != 1))<br />
				{<br />
					throw new ArgumentException(); //Environment.GetResourceString("Arg_RankMultiDimNotSupported"));<br />
				}<br />
				Array.Copy(this.sortedList.keys, 0, array, arrayIndex, this.sortedList.Count);<br />
			}<br />
<br />
			public virtual IEnumerator GetEnumerator()<br />
			{<br />
				return new SortedListByValue.SortedListEnumerator(this.sortedList, 0, this.sortedList.Count, 1);<br />
			}<br />
<br />
			public virtual int IndexOf(object key)<br />
			{<br />
				if (key == null)<br />
				{<br />
					throw new ArgumentNullException("key"); //, Environment.GetResourceString("ArgumentNull_Key"));<br />
				}<br />
				int num1 = Array.BinarySearch(this.sortedList.keys, 0, this.sortedList.Count, key, this.sortedList.comparer);<br />
				if (num1 >= 0)<br />
				{<br />
					return num1;<br />
				}<br />
				return -1;<br />
			}<br />
<br />
			public virtual void Insert(int index, object value)<br />
			{<br />
				throw new NotSupportedException(); //Environment.GetResourceString("NotSupported_SortedListNestedWrite"));<br />
			}<br />
<br />
			public virtual void Remove(object key)<br />
			{<br />
				throw new NotSupportedException(); //Environment.GetResourceString("NotSupported_SortedListNestedWrite"));<br />
			}<br />
<br />
			public virtual void RemoveAt(int index)<br />
			{<br />
				throw new NotSupportedException(); //Environment.GetResourceString("NotSupported_SortedListNestedWrite"));<br />
			}<br />
<br />
<br />
			// Properties<br />
			public virtual int Count<br />
			{<br />
				get<br />
				{<br />
					return this.sortedList._size;<br />
				}<br />
			}<br />
<br />
			public virtual bool IsFixedSize<br />
			{<br />
				get<br />
				{<br />
					return true;<br />
				}<br />
			}<br />
<br />
			public virtual bool IsReadOnly<br />
			{<br />
				get<br />
				{<br />
					return true;<br />
				}<br />
			}<br />
<br />
			public virtual bool IsSynchronized<br />
			{<br />
				get<br />
				{<br />
					return this.sortedList.IsSynchronized;<br />
				}<br />
			}<br />
<br />
			public virtual object this[int index]<br />
			{<br />
				get<br />
				{<br />
					return this.sortedList.GetKey(index);<br />
				}<br />
				set<br />
				{<br />
					throw new NotSupportedException(); //("NotSupported_KeyCollectionSet"));<br />
				}<br />
			}<br />
<br />
			public virtual object SyncRoot<br />
			{<br />
				get<br />
				{<br />
					return this.sortedList.SyncRoot;<br />
				}<br />
			}<br />
<br />
<br />
			// Fields<br />
			private SortedListByValue sortedList;<br />
		}<br />
<br />
		[Serializable]<br />
			private class SortedListEnumerator : IDictionaryEnumerator, IEnumerator, ICloneable<br />
		{<br />
			// Methods<br />
			internal SortedListEnumerator(SortedListByValue sortedList, int index, int count, int getObjRetType)<br />
			{<br />
				this.sortedList = sortedList;<br />
				this.index = index;<br />
				this.startIndex = index;<br />
				this.endIndex = index + count;<br />
				this.version = sortedList.version;<br />
				this.getObjectRetType = getObjRetType;<br />
				this.current = false;<br />
			}<br />
<br />
			public object Clone()<br />
			{<br />
				return base.MemberwiseClone();<br />
			}<br />
<br />
			public virtual bool MoveNext()<br />
			{<br />
				if (this.version != this.sortedList.version)<br />
				{<br />
					throw new InvalidOperationException(); //Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));<br />
				}<br />
				if (this.index < this.endIndex)<br />
				{<br />
					this.key = this.sortedList.keys[this.index];<br />
					this.value = this.sortedList.values[this.index];<br />
					this.index++;<br />
					this.current = true;<br />
					return true;<br />
				}<br />
				this.key = null;<br />
				this.value = null;<br />
				this.current = false;<br />
				return false;<br />
			}<br />
<br />
			public virtual void Reset()<br />
			{<br />
				if (this.version != this.sortedList.version)<br />
				{<br />
					throw new InvalidOperationException(); //Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));<br />
				}<br />
				this.index = this.startIndex;<br />
				this.current = false;<br />
				this.key = null;<br />
				this.value = null;<br />
			}<br />
<br />
<br />
			// Properties<br />
			public virtual object Current<br />
			{<br />
				get<br />
				{<br />
					if (!this.current)<br />
					{<br />
						throw new InvalidOperationException(); //Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));<br />
					}<br />
					if (this.getObjectRetType == 1)<br />
					{<br />
						return this.key;<br />
					}<br />
					if (this.getObjectRetType == 2)<br />
					{<br />
						return this.value;<br />
					}<br />
					return new DictionaryEntry(this.key, this.value);<br />
				}<br />
			}<br />
<br />
			public virtual DictionaryEntry Entry<br />
			{<br />
				get<br />
				{<br />
					if (this.version != this.sortedList.version)<br />
					{<br />
						throw new InvalidOperationException(); //Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));<br />
					}<br />
					if (!this.current)<br />
					{<br />
						throw new InvalidOperationException(); //Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));<br />
					}<br />
					return new DictionaryEntry(this.key, this.value);<br />
				}<br />
			}<br />
<br />
			public virtual object Key<br />
			{<br />
				get<br />
				{<br />
					if (this.version != this.sortedList.version)<br />
					{<br />
						throw new InvalidOperationException(); //Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));<br />
					}<br />
					if (!this.current)<br />
					{<br />
						throw new InvalidOperationException(); //Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));<br />
					}<br />
					return this.key;<br />
				}<br />
			}<br />
<br />
			public virtual object Value<br />
			{<br />
				get<br />
				{<br />
					if (this.version != this.sortedList.version)<br />
					{<br />
						throw new InvalidOperationException(); //Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));<br />
					}<br />
					if (!this.current)<br />
					{<br />
						throw new InvalidOperationException(); //Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));<br />
					}<br />
					return this.value;<br />
				}<br />
			}<br />
<br />
<br />
			// Fields<br />
			private bool current;<br />
			internal const int DictEntry = 3;<br />
			private int endIndex;<br />
			private int getObjectRetType;<br />
			private int index;<br />
			private object key;<br />
			internal const int Keys = 1;<br />
			private SortedListByValue sortedList;<br />
			private int startIndex;<br />
			private object value;<br />
			internal const int Values = 2;<br />
			private int version;<br />
		}<br />
<br />
		[Serializable]<br />
			private class SyncSortedList : SortedListByValue<br />
		{<br />
			// Methods<br />
			internal SyncSortedList(SortedListByValue list)<br />
			{<br />
				this._list = list;<br />
				this._root = list.SyncRoot;<br />
			}<br />
<br />
			public override void Add(object key, object value)<br />
			{<br />
				lock (this._root)<br />
				{<br />
					this._list.Add(key, value);<br />
				}<br />
			}<br />
<br />
			public override void Clear()<br />
			{<br />
				lock (this._root)<br />
				{<br />
					this._list.Clear();<br />
				}<br />
			}<br />
<br />
			public override object Clone()<br />
			{<br />
				object obj1;<br />
				lock (this._root)<br />
				{<br />
					obj1 = this._list.Clone();<br />
				}<br />
				return obj1;<br />
			}<br />
<br />
			public override bool Contains(object key)<br />
			{<br />
				bool flag1;<br />
				lock (this._root)<br />
				{<br />
					flag1 = this._list.Contains(key);<br />
				}<br />
				return flag1;<br />
			}<br />
<br />
			public override bool ContainsKey(object key)<br />
			{<br />
				bool flag1;<br />
				lock (this._root)<br />
				{<br />
					flag1 = this._list.ContainsKey(key);<br />
				}<br />
				return flag1;<br />
			}<br />
<br />
			public override bool ContainsValue(object key)<br />
			{<br />
				bool flag1;<br />
				lock (this._root)<br />
				{<br />
					flag1 = this._list.ContainsValue(key);<br />
				}<br />
				return flag1;<br />
			}<br />
<br />
			public override void CopyTo(Array array, int index)<br />
			{<br />
				lock (this._root)<br />
				{<br />
					this._list.CopyTo(array, index);<br />
				}<br />
			}<br />
<br />
			public override object GetByIndex(int index)<br />
			{<br />
				object obj1;<br />
				lock (this._root)<br />
				{<br />
					obj1 = this._list.GetByIndex(index);<br />
				}<br />
				return obj1;<br />
			}<br />
<br />
			public override IDictionaryEnumerator GetEnumerator()<br />
			{<br />
				IDictionaryEnumerator enumerator1;<br />
				lock (this._root)<br />
				{<br />
					enumerator1 = this._list.GetEnumerator();<br />
				}<br />
				return enumerator1;<br />
			}<br />
<br />
			public override object GetKey(int index)<br />
			{<br />
				object obj1;<br />
				lock (this._root)<br />
				{<br />
					obj1 = this._list.GetKey(index);<br />
				}<br />
				return obj1;<br />
			}<br />
<br />
			public override IList GetKeyList()<br />
			{<br />
				IList list1;<br />
				lock (this._root)<br />
				{<br />
					list1 = this._list.GetKeyList();<br />
				}<br />
				return list1;<br />
			}<br />
<br />
			public override IList GetValueList()<br />
			{<br />
				IList list1;<br />
				lock (this._root)<br />
				{<br />
					list1 = this._list.GetValueList();<br />
				}<br />
				return list1;<br />
			}<br />
<br />
			public override int IndexOfKey(object key)<br />
			{<br />
				int num1;<br />
				lock (this._root)<br />
				{<br />
					num1 = this._list.IndexOfKey(key);<br />
				}<br />
				return num1;<br />
			}<br />
<br />
			public override int IndexOfValue(object value)<br />
			{<br />
				int num1;<br />
				lock (this._root)<br />
				{<br />
					num1 = this._list.IndexOfValue(value);<br />
				}<br />
				return num1;<br />
			}<br />
<br />
			public override void Remove(object key)<br />
			{<br />
				lock (this._root)<br />
				{<br />
					this._list.Remove(key);<br />
				}<br />
			}<br />
<br />
			public override void RemoveAt(int index)<br />
			{<br />
				lock (this._root)<br />
				{<br />
					this._list.RemoveAt(index);<br />
				}<br />
			}<br />
<br />
			public override void SetByIndex(int index, object value)<br />
			{<br />
				lock (this._root)<br />
				{<br />
					this._list.SetByIndex(index, value);<br />
				}<br />
			}<br />
<br />
			public override void TrimToSize()<br />
			{<br />
				lock (this._root)<br />
				{<br />
					this._list.TrimToSize();<br />
				}<br />
			}<br />
<br />
<br />
			// Properties<br />
			public override int Capacity<br />
			{<br />
				get<br />
				{<br />
					int num1;<br />
					lock (this._root)<br />
					{<br />
						num1 = this._list.Capacity;<br />
					}<br />
					return num1;<br />
				}<br />
			}<br />
<br />
			public override int Count<br />
			{<br />
				get<br />
				{<br />
					int num1;<br />
					lock (this._root)<br />
					{<br />
						num1 = this._list.Count;<br />
					}<br />
					return num1;<br />
				}<br />
			}<br />
<br />
			public override bool IsFixedSize<br />
			{<br />
				get<br />
				{<br />
					return this._list.IsFixedSize;<br />
				}<br />
			}<br />
<br />
			public override bool IsReadOnly<br />
			{<br />
				get<br />
				{<br />
					return this._list.IsReadOnly;<br />
				}<br />
			}<br />
<br />
			public override bool IsSynchronized<br />
			{<br />
				get<br />
				{<br />
					return true;<br />
				}<br />
			}<br />
<br />
			public override object this[object key]<br />
			{<br />
				get<br />
				{<br />
					object obj1;<br />
					lock (this._root)<br />
					{<br />
						obj1 = this._list[key];<br />
					}<br />
					return obj1;<br />
				}<br />
				set<br />
				{<br />
					lock (this._root)<br />
					{<br />
						this._list[key] = value;<br />
					}<br />
				}<br />
			}<br />
<br />
			public override object SyncRoot<br />
			{<br />
				get<br />
				{<br />
					return this._root;<br />
				}<br />
			}<br />
<br />
<br />
			// Fields<br />
			private SortedListByValue _list;<br />
			private object _root;<br />
		}<br />
<br />
		[Serializable]<br />
			private class ValueList : IList, ICollection, IEnumerable<br />
		{<br />
			// Methods<br />
			internal ValueList(SortedListByValue sortedList)<br />
			{<br />
				this.sortedList = sortedList;<br />
			}<br />
<br />
			public virtual int Add(object key)<br />
			{<br />
				throw new NotSupportedException(); //Environment.GetResourceString("NotSupported_SortedListNestedWrite"));<br />
			}<br />
<br />
			public virtual void Clear()<br />
			{<br />
				throw new NotSupportedException(); //Environment.GetResourceString("NotSupported_SortedListNestedWrite"));<br />
			}<br />
<br />
			public virtual bool Contains(object value)<br />
			{<br />
				return this.sortedList.ContainsValue(value);<br />
			}<br />
<br />
			public virtual void CopyTo(Array array, int arrayIndex)<br />
			{<br />
				if ((array != null) && (array.Rank != 1))<br />
				{<br />
					throw new ArgumentException(); //Environment.GetResourceString("Arg_RankMultiDimNotSupported"));<br />
				}<br />
				Array.Copy(this.sortedList.values, 0, array, arrayIndex, this.sortedList.Count);<br />
			}<br />
<br />
			public virtual IEnumerator GetEnumerator()<br />
			{<br />
				return new SortedListByValue.SortedListEnumerator(this.sortedList, 0, this.sortedList.Count, 2);<br />
			}<br />
<br />
			public virtual int IndexOf(object value)<br />
			{<br />
				return Array.IndexOf(this.sortedList.values, value, 0, this.sortedList.Count);<br />
			}<br />
<br />
			public virtual void Insert(int index, object value)<br />
			{<br />
				throw new NotSupportedException(); //Environment.GetResourceString("NotSupported_SortedListNestedWrite"));<br />
			}<br />
<br />
			public virtual void Remove(object value)<br />
			{<br />
				throw new NotSupportedException(); //Environment.GetResourceString("NotSupported_SortedListNestedWrite"));<br />
			}<br />
<br />
			public virtual void RemoveAt(int index)<br />
			{<br />
				throw new NotSupportedException(); //Environment.GetResourceString("NotSupported_SortedListNestedWrite"));<br />
			}<br />
<br />
<br />
			// Properties<br />
			public virtual int Count<br />
			{<br />
				get<br />
				{<br />
					return this.sortedList._size;<br />
				}<br />
			}<br />
<br />
			public virtual bool IsFixedSize<br />
			{<br />
				get<br />
				{<br />
					return true;<br />
				}<br />
			}<br />
<br />
			public virtual bool IsReadOnly<br />
			{<br />
				get<br />
				{<br />
					return true;<br />
				}<br />
			}<br />
<br />
			public virtual bool IsSynchronized<br />
			{<br />
				get<br />
				{<br />
					return this.sortedList.IsSynchronized;<br />
				}<br />
			}<br />
<br />
			public virtual object this[int index]<br />
			{<br />
				get<br />
				{<br />
					return this.sortedList.GetByIndex(index);<br />
				}<br />
				set<br />
				{<br />
					this.sortedList.SetByIndex(index, value);<br />
				}<br />
			}<br />
<br />
			public virtual object SyncRoot<br />
			{<br />
				get<br />
				{<br />
					return this.sortedList.SyncRoot;<br />
				}<br />
			}<br />
<br />
<br />
			// Fields<br />
			private SortedListByValue sortedList;<br />
		}<br />
	}<br />
	public class SortedByListDefaultComparer : IComparer<br />
	{<br />
		public int Compare(object x,object y)        <br />
		{<br />
			return 0;<br />
		}<br />
	}<br />
}

GeneralRe: Copy the SortedList Pin
Ben Morrison27-Jan-06 3:47
Ben Morrison27-Jan-06 3:47 
GeneralRe: Copy the SortedList Pin
tigerite3-Apr-06 23:43
tigerite3-Apr-06 23:43 
GeneralPerformance Issues Pin
jaredutley19-May-04 6:26
jaredutley19-May-04 6:26 
GeneralRe: Performance Issues Pin
Hannes Foulds20-May-04 0:19
Hannes Foulds20-May-04 0:19 
GeneralRe: Performance Issues Pin
jaredutley20-May-04 3:35
jaredutley20-May-04 3:35 
GeneralRe: Performance Issues Pin
Hannes Foulds20-May-04 4:11
Hannes Foulds20-May-04 4:11 
GeneralAbsolutely excellent idea Pin
amiscell11-May-04 11:17
amiscell11-May-04 11:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.