summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Collections/SortedList.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/Collections/SortedList.cs')
-rw-r--r--src/mscorlib/src/System/Collections/SortedList.cs1010
1 files changed, 1010 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Collections/SortedList.cs b/src/mscorlib/src/System/Collections/SortedList.cs
new file mode 100644
index 0000000000..c6d6e8d391
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/SortedList.cs
@@ -0,0 +1,1010 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/*============================================================
+**
+**
+**
+**
+** Purpose: A sorted dictionary.
+**
+**
+===========================================================*/
+namespace System.Collections {
+ using System;
+ using System.Security.Permissions;
+ using System.Diagnostics;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+
+ // The SortedList class implements a sorted list of keys and values. Entries in
+ // a sorted list are sorted by their keys and are accessible both by key and by
+ // index. The keys of a sorted list can be ordered either according to a
+ // specific IComparer implementation given when the sorted list is
+ // instantiated, or according to the IComparable implementation provided
+ // by the keys themselves. In either case, a sorted list does not allow entries
+ // with duplicate keys.
+ //
+ // A sorted list internally maintains two arrays that store the keys and
+ // values of the entries. The capacity of a sorted list is the allocated
+ // length of these internal arrays. As elements are added to a sorted list, the
+ // capacity of the sorted list is automatically increased as required by
+ // reallocating the internal arrays. The capacity is never automatically
+ // decreased, but users can call either TrimToSize or
+ // Capacity explicitly.
+ //
+ // The GetKeyList and GetValueList methods of a sorted list
+ // provides access to the keys and values of the sorted list in the form of
+ // List implementations. The List objects returned by these
+ // methods are aliases for the underlying sorted list, so modifications
+ // made to those lists are directly reflected in the sorted list, and vice
+ // versa.
+ //
+ // The SortedList class provides a convenient way to create a sorted
+ // copy of another dictionary, such as a Hashtable. For example:
+ //
+ // Hashtable h = new Hashtable();
+ // h.Add(...);
+ // h.Add(...);
+ // ...
+ // SortedList s = new SortedList(h);
+ //
+ // The last line above creates a sorted list that contains a copy of the keys
+ // and values stored in the hashtable. In this particular example, the keys
+ // will be ordered according to the IComparable interface, which they
+ // all must implement. To impose a different ordering, SortedList also
+ // has a constructor that allows a specific IComparer implementation to
+ // be specified.
+ //
+ [DebuggerTypeProxy(typeof(System.Collections.SortedList.SortedListDebugView))]
+ [DebuggerDisplay("Count = {Count}")]
+[System.Runtime.InteropServices.ComVisible(true)]
+#if FEATURE_CORECLR
+ [Obsolete("Non-generic collections have been deprecated. Please use collections in System.Collections.Generic.")]
+#endif
+ [Serializable]
+ public class SortedList : IDictionary, ICloneable
+ {
+ private Object[] keys;
+ private Object[] values;
+ private int _size;
+ private int version;
+ private IComparer comparer;
+ private KeyList keyList;
+ private ValueList valueList;
+ [NonSerialized]
+ private Object _syncRoot;
+
+ private const int _defaultCapacity = 16;
+
+ private static Object[] emptyArray = EmptyArray<Object>.Value;
+
+ // Constructs a new sorted list. The sorted list is initially empty and has
+ // a capacity of zero. Upon adding the first element to the sorted list the
+ // capacity is increased to 16, and then increased in multiples of two as
+ // required. The elements of the sorted list are ordered according to the
+ // IComparable interface, which must be implemented by the keys of
+ // all entries added to the sorted list.
+ public SortedList() {
+ Init();
+ }
+ private void Init()
+ {
+ keys = emptyArray;
+ values = emptyArray;
+ _size = 0;
+ comparer = new Comparer(CultureInfo.CurrentCulture);
+ }
+
+ // Constructs a new sorted list. The sorted list is initially empty and has
+ // a capacity of zero. Upon adding the first element to the sorted list the
+ // capacity is increased to 16, and then increased in multiples of two as
+ // required. The elements of the sorted list are ordered according to the
+ // IComparable interface, which must be implemented by the keys of
+ // all entries added to the sorted list.
+ //
+ public SortedList(int initialCapacity) {
+ if (initialCapacity < 0)
+ throw new ArgumentOutOfRangeException("initialCapacity", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+ keys = new Object[initialCapacity];
+ values = new Object[initialCapacity];
+ comparer = new Comparer(CultureInfo.CurrentCulture);
+ }
+
+ // Constructs a new sorted list with a given IComparer
+ // implementation. The sorted list is initially empty and has a capacity of
+ // zero. Upon adding the first element to the sorted list the capacity is
+ // increased to 16, and then increased in multiples of two as required. The
+ // elements of the sorted list are ordered according to the given
+ // IComparer implementation. If comparer is null, the
+ // elements are compared to each other using the IComparable
+ // interface, which in that case must be implemented by the keys of all
+ // entries added to the sorted list.
+ //
+ public SortedList(IComparer comparer)
+ : this() {
+ if (comparer != null) this.comparer = comparer;
+ }
+
+ // Constructs a new sorted list with a given IComparer
+ // implementation and a given initial capacity. The sorted list is
+ // initially empty, but will have room for the given number of elements
+ // before any reallocations are required. The elements of the sorted list
+ // are ordered according to the given IComparer implementation. If
+ // comparer is null, the elements are compared to each other using
+ // the IComparable interface, which in that case must be implemented
+ // by the keys of all entries added to the sorted list.
+ //
+ public SortedList(IComparer comparer, int capacity)
+ : this(comparer) {
+ Capacity = capacity;
+ }
+
+ // Constructs a new sorted list containing a copy of the entries in the
+ // given dictionary. The elements of the sorted list are ordered according
+ // to the IComparable interface, which must be implemented by the
+ // keys of all entries in the the given dictionary as well as keys
+ // subsequently added to the sorted list.
+ //
+ public SortedList(IDictionary d)
+ : this(d, null) {
+ }
+
+ // Constructs a new sorted list containing a copy of the entries in the
+ // given dictionary. The elements of the sorted list are ordered according
+ // to the given IComparer implementation. If comparer is
+ // null, the elements are compared to each other using the
+ // IComparable interface, which in that case must be implemented
+ // by the keys of all entries in the the given dictionary as well as keys
+ // subsequently added to the sorted list.
+ //
+ public SortedList(IDictionary d, IComparer comparer)
+ : this(comparer, (d != null ? d.Count : 0)) {
+ if (d==null)
+ throw new ArgumentNullException("d", Environment.GetResourceString("ArgumentNull_Dictionary"));
+ Contract.EndContractBlock();
+ d.Keys.CopyTo(keys, 0);
+ d.Values.CopyTo(values, 0);
+ Array.Sort(keys, values, comparer);
+ _size = d.Count;
+ }
+
+ // Adds an entry with the given key and value to this sorted list. An
+ // ArgumentException is thrown if the key is already present in the sorted list.
+ //
+ public virtual void Add(Object key, Object value) {
+ if (key == null) throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ Contract.EndContractBlock();
+ int i = Array.BinarySearch(keys, 0, _size, key, comparer);
+ if (i >= 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_AddingDuplicate__", GetKey(i), key));
+ Insert(~i, key, value);
+ }
+
+ // Returns the capacity of this sorted list. The capacity of a sorted list
+ // represents the allocated length of the internal arrays used to store the
+ // keys and values of the list, and thus also indicates the maximum number
+ // of entries the list can contain before a reallocation of the internal
+ // arrays is required.
+ //
+ public virtual int Capacity {
+ get {
+ return keys.Length;
+ }
+ set {
+ if (value < Count) {
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity"));
+ }
+ Contract.EndContractBlock();
+
+ if (value != keys.Length) {
+ if (value > 0) {
+ Object[] newKeys = new Object[value];
+ Object[] newValues = new Object[value];
+ if (_size > 0) {
+ Array.Copy(keys, 0, newKeys, 0, _size);
+ Array.Copy(values, 0, newValues, 0, _size);
+ }
+ keys = newKeys;
+ values = newValues;
+ }
+ else {
+ // size can only be zero here.
+ Contract.Assert( _size == 0, "Size is not zero");
+ keys = emptyArray;
+ values = emptyArray;
+ }
+ }
+ }
+ }
+
+ // Returns the number of entries in this sorted list.
+ //
+ public virtual int Count {
+ get {
+ return _size;
+ }
+ }
+
+ // Returns a collection representing the keys of this sorted list. This
+ // method returns the same object as GetKeyList, but typed as an
+ // ICollection instead of an IList.
+ //
+ public virtual ICollection Keys {
+ get {
+ return GetKeyList();
+ }
+ }
+
+ // Returns a collection representing the values of this sorted list. This
+ // method returns the same object as GetValueList, but typed as an
+ // ICollection instead of an IList.
+ //
+ public virtual ICollection Values {
+ get {
+ return GetValueList();
+ }
+ }
+
+ // Is this SortedList read-only?
+ public virtual bool IsReadOnly {
+ get { return false; }
+ }
+
+ public virtual bool IsFixedSize {
+ get { return false; }
+ }
+
+ // Is this SortedList synchronized (thread-safe)?
+ public virtual bool IsSynchronized {
+ get { return false; }
+ }
+
+ // Synchronization root for this object.
+ public virtual Object SyncRoot {
+ get {
+ if( _syncRoot == null) {
+ System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ }
+ return _syncRoot;
+ }
+ }
+
+ // Removes all entries from this sorted list.
+ public virtual void Clear() {
+ // clear does not change the capacity
+ version++;
+ Array.Clear(keys, 0, _size); // Don't need to doc this but we clear the elements so that the gc can reclaim the references.
+ Array.Clear(values, 0, _size); // Don't need to doc this but we clear the elements so that the gc can reclaim the references.
+ _size = 0;
+
+ }
+
+ // Makes a virtually identical copy of this SortedList. This is a shallow
+ // copy. IE, the Objects in the SortedList are not cloned - we copy the
+ // references to those objects.
+ public virtual Object Clone()
+ {
+ SortedList sl = new SortedList(_size);
+ Array.Copy(keys, 0, sl.keys, 0, _size);
+ Array.Copy(values, 0, sl.values, 0, _size);
+ sl._size = _size;
+ sl.version = version;
+ sl.comparer = comparer;
+ // Don't copy keyList nor valueList.
+ return sl;
+ }
+
+
+ // Checks if this sorted list contains an entry with the given key.
+ //
+ public virtual bool Contains(Object key) {
+ return IndexOfKey(key) >= 0;
+ }
+
+ // Checks if this sorted list contains an entry with the given key.
+ //
+ public virtual bool ContainsKey(Object key) {
+ // Yes, this is a SPEC'ed duplicate of Contains().
+ return IndexOfKey(key) >= 0;
+ }
+
+ // Checks if this sorted list contains an entry with the given value. The
+ // values of the entries of the sorted list are compared to the given value
+ // using the Object.Equals method. This method performs a linear
+ // search and is substantially slower than the Contains
+ // method.
+ //
+ public virtual bool ContainsValue(Object value) {
+ return IndexOfValue(value) >= 0;
+ }
+
+ // Copies the values in this SortedList to an array.
+ public virtual void CopyTo(Array array, int arrayIndex) {
+ if (array == null)
+ throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Array"));
+ if (array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException("arrayIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (array.Length - arrayIndex < Count)
+ throw new ArgumentException(Environment.GetResourceString("Arg_ArrayPlusOffTooSmall"));
+ Contract.EndContractBlock();
+ for (int i = 0; i<Count; i++) {
+ DictionaryEntry entry = new DictionaryEntry(keys[i],values[i]);
+ array.SetValue(entry, i + arrayIndex);
+ }
+ }
+
+ // Copies the values in this SortedList to an KeyValuePairs array.
+ // KeyValuePairs is different from Dictionary Entry in that it has special
+ // debugger attributes on its fields.
+
+ internal virtual KeyValuePairs[] ToKeyValuePairsArray() {
+ KeyValuePairs[] array = new KeyValuePairs[Count];
+ for (int i = 0; i < Count; i++) {
+ array[i] = new KeyValuePairs(keys[i],values[i]);
+ }
+ return array;
+ }
+
+ // Ensures that the capacity of this sorted list is at least the given
+ // minimum value. If the currect capacity of the list is less than
+ // min, the capacity is increased to twice the current capacity or
+ // to min, whichever is larger.
+ private void EnsureCapacity(int min) {
+ int newCapacity = keys.Length == 0? 16: keys.Length * 2;
+ // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.
+ // Note that this check works even when _items.Length overflowed thanks to the (uint) cast
+ if ((uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength;
+ if (newCapacity < min) newCapacity = min;
+ Capacity = newCapacity;
+ }
+
+ // Returns the value of the entry at the given index.
+ //
+ public virtual Object GetByIndex(int index) {
+ if (index < 0 || index >= Count)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+ return values[index];
+ }
+
+ // Returns an IEnumerator for this sorted list. If modifications
+ // made to the sorted list while an enumeration is in progress,
+ // the MoveNext and Remove methods
+ // of the enumerator will throw an exception.
+ //
+ IEnumerator IEnumerable.GetEnumerator() {
+ return new SortedListEnumerator(this, 0, _size, SortedListEnumerator.DictEntry);
+ }
+
+ // Returns an IDictionaryEnumerator for this sorted list. If modifications
+ // made to the sorted list while an enumeration is in progress,
+ // the MoveNext and Remove methods
+ // of the enumerator will throw an exception.
+ //
+ public virtual IDictionaryEnumerator GetEnumerator() {
+ return new SortedListEnumerator(this, 0, _size, SortedListEnumerator.DictEntry);
+ }
+
+ // Returns the key of the entry at the given index.
+ //
+ public virtual Object GetKey(int index) {
+ if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+ return keys[index];
+ }
+
+ // Returns an IList representing the keys of this sorted list. The
+ // returned list is an alias for the keys of this sorted list, so
+ // modifications made to the returned list are directly reflected in the
+ // underlying sorted list, and vice versa. The elements of the returned
+ // list are ordered in the same way as the elements of the sorted list. The
+ // returned list does not support adding, inserting, or modifying elements
+ // (the Add, AddRange, Insert, InsertRange,
+ // Reverse, Set, SetRange, and Sort methods
+ // throw exceptions), but it does allow removal of elements (through the
+ // Remove and RemoveRange methods or through an enumerator).
+ // Null is an invalid key value.
+ //
+ public virtual IList GetKeyList() {
+ if (keyList == null) keyList = new KeyList(this);
+ return keyList;
+ }
+
+ // Returns an IList representing the values of this sorted list. The
+ // returned list is an alias for the values of this sorted list, so
+ // modifications made to the returned list are directly reflected in the
+ // underlying sorted list, and vice versa. The elements of the returned
+ // list are ordered in the same way as the elements of the sorted list. The
+ // returned list does not support adding or inserting elements (the
+ // Add, AddRange, Insert and InsertRange
+ // methods throw exceptions), but it does allow modification and removal of
+ // elements (through the Remove, RemoveRange, Set and
+ // SetRange methods or through an enumerator).
+ //
+ public virtual IList GetValueList() {
+ if (valueList == null) valueList = new ValueList(this);
+ return valueList;
+ }
+
+ // Returns the value associated with the given key. If an entry with the
+ // given key is not found, the returned value is null.
+ //
+ public virtual Object this[Object key] {
+ get {
+ int i = IndexOfKey(key);
+ if (i >= 0) return values[i];
+ return null;
+ }
+ set {
+ if (key == null) throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ Contract.EndContractBlock();
+ int i = Array.BinarySearch(keys, 0, _size, key, comparer);
+ if (i >= 0) {
+ values[i] = value;
+ version++;
+ return;
+ }
+ Insert(~i, key, value);
+ }
+ }
+
+ // Returns the index of the entry with a given key in this sorted list. The
+ // key is located through a binary search, and thus the average execution
+ // time of this method is proportional to Log2(size), where
+ // size is the size of this sorted list. The returned value is -1 if
+ // the given key does not occur in this sorted list. Null is an invalid
+ // key value.
+ //
+ public virtual int IndexOfKey(Object key) {
+ if (key == null)
+ throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ Contract.EndContractBlock();
+ int ret = Array.BinarySearch(keys, 0, _size, key, comparer);
+ return ret >=0 ? ret : -1;
+ }
+
+ // Returns the index of the first occurrence of an entry with a given value
+ // in this sorted list. The entry is located through a linear search, and
+ // thus the average execution time of this method is proportional to the
+ // size of this sorted list. The elements of the list are compared to the
+ // given value using the Object.Equals method.
+ //
+ public virtual int IndexOfValue(Object value) {
+ return Array.IndexOf(values, value, 0, _size);
+ }
+
+ // Inserts an entry with a given key and value at a given index.
+ private void Insert(int index, Object key, Object value) {
+ if (_size == keys.Length) EnsureCapacity(_size + 1);
+ if (index < _size) {
+ Array.Copy(keys, index, keys, index + 1, _size - index);
+ Array.Copy(values, index, values, index + 1, _size - index);
+ }
+ keys[index] = key;
+ values[index] = value;
+ _size++;
+ version++;
+ }
+
+ // Removes the entry at the given index. The size of the sorted list is
+ // decreased by one.
+ //
+ public virtual void RemoveAt(int index) {
+ if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+ _size--;
+ if (index < _size) {
+ Array.Copy(keys, index + 1, keys, index, _size - index);
+ Array.Copy(values, index + 1, values, index, _size - index);
+ }
+ keys[_size] = null;
+ values[_size] = null;
+ version++;
+ }
+
+ // Removes an entry from this sorted list. If an entry with the specified
+ // key exists in the sorted list, it is removed. An ArgumentException is
+ // thrown if the key is null.
+ //
+ public virtual void Remove(Object key) {
+ int i = IndexOfKey(key);
+ if (i >= 0)
+ RemoveAt(i);
+ }
+
+ // Sets the value at an index to a given value. The previous value of
+ // the given entry is overwritten.
+ //
+ public virtual void SetByIndex(int index, Object value) {
+ if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+ values[index] = value;
+ version++;
+ }
+
+ // Returns a thread-safe SortedList.
+ //
+ [HostProtection(Synchronization=true)]
+ public static SortedList Synchronized(SortedList list) {
+ if (list==null)
+ throw new ArgumentNullException("list");
+ Contract.EndContractBlock();
+ return new SyncSortedList(list);
+ }
+
+ // Sets the capacity of this sorted list to the size of the sorted list.
+ // This method can be used to minimize a sorted list's memory overhead once
+ // it is known that no new elements will be added to the sorted list. To
+ // completely clear a sorted list and release all memory referenced by the
+ // sorted list, execute the following statements:
+ //
+ // sortedList.Clear();
+ // sortedList.TrimToSize();
+ //
+ public virtual void TrimToSize() {
+ Capacity = _size;
+ }
+
+ [Serializable]
+ private class SyncSortedList : SortedList
+ {
+ private SortedList _list;
+ private Object _root;
+
+
+ internal SyncSortedList(SortedList list) {
+ _list = list;
+ _root = list.SyncRoot;
+ }
+
+ public override int Count {
+ get { lock(_root) { return _list.Count; } }
+ }
+
+ public override Object SyncRoot {
+ get { return _root; }
+ }
+
+ public override bool IsReadOnly {
+ get { return _list.IsReadOnly; }
+ }
+
+ public override bool IsFixedSize {
+ get { return _list.IsFixedSize; }
+ }
+
+
+ public override bool IsSynchronized {
+ get { return true; }
+ }
+
+ public override Object this[Object key] {
+ get {
+ lock(_root) {
+ return _list[key];
+ }
+ }
+ set {
+ lock(_root) {
+ _list[key] = value;
+ }
+ }
+ }
+
+ public override void Add(Object key, Object value) {
+ lock(_root) {
+ _list.Add(key, value);
+ }
+ }
+
+ public override int Capacity {
+ get{ lock(_root) { return _list.Capacity; } }
+ }
+
+ public override void Clear() {
+ lock(_root) {
+ _list.Clear();
+ }
+ }
+
+ public override Object Clone() {
+ lock(_root) {
+ return _list.Clone();
+ }
+ }
+
+ public override bool Contains(Object key) {
+ lock(_root) {
+ return _list.Contains(key);
+ }
+ }
+
+ public override bool ContainsKey(Object key) {
+ lock(_root) {
+ return _list.ContainsKey(key);
+ }
+ }
+
+ public override bool ContainsValue(Object key) {
+ lock(_root) {
+ return _list.ContainsValue(key);
+ }
+ }
+
+ public override void CopyTo(Array array, int index) {
+ lock(_root) {
+ _list.CopyTo(array, index);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override Object GetByIndex(int index) {
+ lock(_root) {
+ return _list.GetByIndex(index);
+ }
+ }
+
+ public override IDictionaryEnumerator GetEnumerator() {
+ lock(_root) {
+ return _list.GetEnumerator();
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override Object GetKey(int index) {
+ lock(_root) {
+ return _list.GetKey(index);
+ }
+ }
+
+ public override IList GetKeyList() {
+ lock(_root) {
+ return _list.GetKeyList();
+ }
+ }
+
+ public override IList GetValueList() {
+ lock(_root) {
+ return _list.GetValueList();
+ }
+ }
+
+ public override int IndexOfKey(Object key) {
+ if (key == null)
+ throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ Contract.EndContractBlock();
+
+ lock(_root) {
+ return _list.IndexOfKey(key);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int IndexOfValue(Object value) {
+ lock(_root) {
+ return _list.IndexOfValue(value);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void RemoveAt(int index) {
+ lock(_root) {
+ _list.RemoveAt(index);
+ }
+ }
+
+ public override void Remove(Object key) {
+ lock(_root) {
+ _list.Remove(key);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void SetByIndex(int index, Object value) {
+ lock(_root) {
+ _list.SetByIndex(index, value);
+ }
+ }
+
+ internal override KeyValuePairs[] ToKeyValuePairsArray() {
+ return _list.ToKeyValuePairsArray();
+ }
+
+ public override void TrimToSize() {
+ lock(_root) {
+ _list.TrimToSize();
+ }
+ }
+ }
+
+
+ [Serializable]
+ private class SortedListEnumerator : IDictionaryEnumerator, ICloneable
+ {
+ private SortedList sortedList;
+ private Object key;
+ private Object value;
+ private int index;
+ private int startIndex; // Store for Reset.
+ private int endIndex;
+ private int version;
+ private bool current; // Is the current element valid?
+ private int getObjectRetType; // What should GetObject return?
+
+ internal const int Keys = 1;
+ internal const int Values = 2;
+ internal const int DictEntry = 3;
+
+ internal SortedListEnumerator(SortedList sortedList, int index, int count,
+ int getObjRetType) {
+ this.sortedList = sortedList;
+ this.index = index;
+ startIndex = index;
+ endIndex = index + count;
+ version = sortedList.version;
+ getObjectRetType = getObjRetType;
+ current = false;
+ }
+
+ public Object Clone()
+ {
+ return MemberwiseClone();
+ }
+
+ public virtual Object Key {
+ get {
+ if (version != sortedList.version) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
+ if (current == false) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+ return key;
+ }
+ }
+
+ public virtual bool MoveNext() {
+ if (version != sortedList.version) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
+ if (index < endIndex) {
+ key = sortedList.keys[index];
+ value = sortedList.values[index];
+ index++;
+ current = true;
+ return true;
+ }
+ key = null;
+ value = null;
+ current = false;
+ return false;
+ }
+
+ public virtual DictionaryEntry Entry {
+ get {
+ if (version != sortedList.version) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
+ if (current == false) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+ return new DictionaryEntry(key, value);
+ }
+ }
+
+ public virtual Object Current {
+ get {
+ if (current == false) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+
+ if (getObjectRetType==Keys)
+ return key;
+ else if (getObjectRetType==Values)
+ return value;
+ else
+ return new DictionaryEntry(key, value);
+ }
+ }
+
+ public virtual Object Value {
+ get {
+ if (version != sortedList.version) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion));
+ if (current == false) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+ return value;
+ }
+ }
+
+ public virtual void Reset() {
+ if (version != sortedList.version) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion));
+ index = startIndex;
+ current = false;
+ key = null;
+ value = null;
+ }
+ }
+
+ [Serializable]
+ private class KeyList : IList
+ {
+ private SortedList sortedList;
+
+ internal KeyList(SortedList sortedList) {
+ this.sortedList = sortedList;
+ }
+
+ public virtual int Count {
+ get { return sortedList._size; }
+ }
+
+ public virtual bool IsReadOnly {
+ get { return true; }
+ }
+
+ public virtual bool IsFixedSize {
+ get { return true; }
+ }
+
+ public virtual bool IsSynchronized {
+ get { return sortedList.IsSynchronized; }
+ }
+
+ public virtual Object SyncRoot {
+ get { return sortedList.SyncRoot; }
+ }
+
+ public virtual int Add(Object key) {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ // return 0; // suppress compiler warning
+ }
+
+ public virtual void Clear() {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+
+ public virtual bool Contains(Object key) {
+ return sortedList.Contains(key);
+ }
+
+ public virtual void CopyTo(Array array, int arrayIndex) {
+ if (array != null && array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+ Contract.EndContractBlock();
+
+ // defer error checking to Array.Copy
+ Array.Copy(sortedList.keys, 0, array, arrayIndex, sortedList.Count);
+ }
+
+ public virtual void Insert(int index, Object value) {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+
+ public virtual Object this[int index] {
+ get {
+ return sortedList.GetKey(index);
+ }
+ set {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_KeyCollectionSet"));
+ }
+ }
+
+ public virtual IEnumerator GetEnumerator() {
+ return new SortedListEnumerator(sortedList, 0, sortedList.Count, SortedListEnumerator.Keys);
+ }
+
+ public virtual int IndexOf(Object key) {
+ if (key==null)
+ throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ Contract.EndContractBlock();
+
+ int i = Array.BinarySearch(sortedList.keys, 0,
+ sortedList.Count, key, sortedList.comparer);
+ if (i >= 0) return i;
+ return -1;
+ }
+
+ public virtual void Remove(Object key) {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+
+ public virtual void RemoveAt(int index) {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+ }
+
+ [Serializable]
+ private class ValueList : IList
+ {
+ private SortedList sortedList;
+
+ internal ValueList(SortedList sortedList) {
+ this.sortedList = sortedList;
+ }
+
+ public virtual int Count {
+ get { return sortedList._size; }
+ }
+
+ public virtual bool IsReadOnly {
+ get { return true; }
+ }
+
+ public virtual bool IsFixedSize {
+ get { return true; }
+ }
+
+ public virtual bool IsSynchronized {
+ get { return sortedList.IsSynchronized; }
+ }
+
+ public virtual Object SyncRoot {
+ get { return sortedList.SyncRoot; }
+ }
+
+ public virtual int Add(Object key) {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+
+ public virtual void Clear() {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+
+ public virtual bool Contains(Object value) {
+ return sortedList.ContainsValue(value);
+ }
+
+ public virtual void CopyTo(Array array, int arrayIndex) {
+ if (array != null && array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+ Contract.EndContractBlock();
+
+ // defer error checking to Array.Copy
+ Array.Copy(sortedList.values, 0, array, arrayIndex, sortedList.Count);
+ }
+
+ public virtual void Insert(int index, Object value) {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+
+ public virtual Object this[int index] {
+ get {
+ return sortedList.GetByIndex(index);
+ }
+ set {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+ }
+
+ public virtual IEnumerator GetEnumerator() {
+ return new SortedListEnumerator(sortedList, 0, sortedList.Count, SortedListEnumerator.Values);
+ }
+
+ public virtual int IndexOf(Object value) {
+ return Array.IndexOf(sortedList.values, value, 0, sortedList.Count);
+ }
+
+ public virtual void Remove(Object value) {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+
+ public virtual void RemoveAt(int index) {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+
+ }
+
+ // internal debug view class for sorted list
+ internal class SortedListDebugView {
+ private SortedList sortedList;
+
+ public SortedListDebugView( SortedList sortedList) {
+ if( sortedList == null) {
+ throw new ArgumentNullException("sortedList");
+ }
+ Contract.EndContractBlock();
+
+ this.sortedList = sortedList;
+ }
+
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public KeyValuePairs[] Items {
+ get {
+ return sortedList.ToKeyValuePairsArray();
+ }
+ }
+ }
+ }
+}