3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 /*============================================================
10 ** Purpose: A generic sorted list.
12 ** Date: January 28, 2003
14 ===========================================================*/
15 namespace System.Collections.Generic {
17 using System.Security.Permissions;
18 using System.Diagnostics;
20 // The SortedDictionary class implements a generic sorted list of keys
21 // and values. Entries in a sorted list are sorted by their keys and
22 // are accessible both by key and by index. The keys of a sorted dictionary
23 // can be ordered either according to a specific IComparer
24 // implementation given when the sorted dictionary is instantiated, or
25 // according to the IComparable implementation provided by the keys
26 // themselves. In either case, a sorted dictionary does not allow entries
27 // with duplicate or null keys.
29 // A sorted list internally maintains two arrays that store the keys and
30 // values of the entries. The capacity of a sorted list is the allocated
31 // length of these internal arrays. As elements are added to a sorted list, the
32 // capacity of the sorted list is automatically increased as required by
33 // reallocating the internal arrays. The capacity is never automatically
34 // decreased, but users can call either TrimExcess or
35 // Capacity explicitly.
37 // The GetKeyList and GetValueList methods of a sorted list
38 // provides access to the keys and values of the sorted list in the form of
39 // List implementations. The List objects returned by these
40 // methods are aliases for the underlying sorted list, so modifications
41 // made to those lists are directly reflected in the sorted list, and vice
44 // The SortedList class provides a convenient way to create a sorted
45 // copy of another dictionary, such as a Hashtable. For example:
47 // Hashtable h = new Hashtable();
51 // SortedList s = new SortedList(h);
53 // The last line above creates a sorted list that contains a copy of the keys
54 // and values stored in the hashtable. In this particular example, the keys
55 // will be ordered according to the IComparable interface, which they
56 // all must implement. To impose a different ordering, SortedList also
57 // has a constructor that allows a specific IComparer implementation to
60 [DebuggerTypeProxy(typeof(System_DictionaryDebugView<,>))]
61 [DebuggerDisplay("Count = {Count}")]
63 [System.Runtime.InteropServices.ComVisible(false)]
64 public class SortedList<TKey, TValue> :
65 IDictionary<TKey, TValue>, System.Collections.IDictionary
68 private TValue[] values;
71 private IComparer<TKey> comparer;
72 private KeyList keyList;
73 private ValueList valueList;
75 private Object _syncRoot;
77 static TKey[] emptyKeys = new TKey[0];
78 static TValue[] emptyValues = new TValue[0];
80 private const int _defaultCapacity = 4;
82 // Constructs a new sorted list. The sorted list is initially empty and has
83 // a capacity of zero. Upon adding the first element to the sorted list the
84 // capacity is increased to _defaultCapacity, and then increased in multiples of two as
85 // required. The elements of the sorted list are ordered according to the
86 // IComparable interface, which must be implemented by the keys of
87 // all entries added to the sorted list.
92 comparer = Comparer<TKey>.Default;
95 // Constructs a new sorted list. The sorted list is initially empty and has
96 // a capacity of zero. Upon adding the first element to the sorted list the
97 // capacity is increased to 16, and then increased in multiples of two as
98 // required. The elements of the sorted list are ordered according to the
99 // IComparable interface, which must be implemented by the keys of
100 // all entries added to the sorted list.
102 public SortedList(int capacity) {
104 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity, ExceptionResource.ArgumentOutOfRange_NeedNonNegNumRequired);
105 keys = new TKey[capacity];
106 values = new TValue[capacity];
107 comparer = Comparer<TKey>.Default;
110 // Constructs a new sorted list with a given IComparer
111 // implementation. The sorted list is initially empty and has a capacity of
112 // zero. Upon adding the first element to the sorted list the capacity is
113 // increased to 16, and then increased in multiples of two as required. The
114 // elements of the sorted list are ordered according to the given
115 // IComparer implementation. If comparer is null, the
116 // elements are compared to each other using the IComparable
117 // interface, which in that case must be implemented by the keys of all
118 // entries added to the sorted list.
120 public SortedList(IComparer<TKey> comparer)
122 if (comparer != null) {
123 this.comparer = comparer;
127 // Constructs a new sorted dictionary with a given IComparer
128 // implementation and a given initial capacity. The sorted list is
129 // initially empty, but will have room for the given number of elements
130 // before any reallocations are required. The elements of the sorted list
131 // are ordered according to the given IComparer implementation. If
132 // comparer is null, the elements are compared to each other using
133 // the IComparable interface, which in that case must be implemented
134 // by the keys of all entries added to the sorted list.
136 public SortedList(int capacity, IComparer<TKey> comparer)
141 // Constructs a new sorted list containing a copy of the entries in the
142 // given dictionary. The elements of the sorted list are ordered according
143 // to the IComparable interface, which must be implemented by the
144 // keys of all entries in the the given dictionary as well as keys
145 // subsequently added to the sorted list.
147 public SortedList(IDictionary<TKey, TValue> dictionary)
148 : this(dictionary, null) {
151 // Constructs a new sorted list containing a copy of the entries in the
152 // given dictionary. The elements of the sorted list are ordered according
153 // to the given IComparer implementation. If comparer is
154 // null, the elements are compared to each other using the
155 // IComparable interface, which in that case must be implemented
156 // by the keys of all entries in the the given dictionary as well as keys
157 // subsequently added to the sorted list.
159 public SortedList(IDictionary<TKey, TValue> dictionary, IComparer<TKey> comparer)
160 : this((dictionary != null ? dictionary.Count : 0), comparer) {
161 if (dictionary==null)
162 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
164 dictionary.Keys.CopyTo(keys, 0);
165 dictionary.Values.CopyTo(values, 0);
166 Array.Sort<TKey, TValue>(keys, values, comparer);
167 _size = dictionary.Count;
170 // Adds an entry with the given key and value to this sorted list. An
171 // ArgumentException is thrown if the key is already present in the sorted list.
173 public void Add(TKey key, TValue value) {
174 if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
175 int i = Array.BinarySearch<TKey>(keys, 0, _size, key, comparer);
177 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
178 Insert(~i, key, value);
181 void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> keyValuePair) {
182 Add(keyValuePair.Key, keyValuePair.Value);
185 bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> keyValuePair) {
186 int index = IndexOfKey(keyValuePair.Key);
187 if( index >= 0 && EqualityComparer<TValue>.Default.Equals(values[index], keyValuePair.Value)) {
193 bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> keyValuePair) {
194 int index = IndexOfKey(keyValuePair.Key);
195 if( index >= 0 && EqualityComparer<TValue>.Default.Equals(values[index], keyValuePair.Value)) {
202 // Returns the capacity of this sorted list. The capacity of a sorted list
203 // represents the allocated length of the internal arrays used to store the
204 // keys and values of the list, and thus also indicates the maximum number
205 // of entries the list can contain before a reallocation of the internal
206 // arrays is required.
208 public int Capacity {
213 if (value != keys.Length) {
215 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity);
219 TKey[] newKeys = new TKey[value];
220 TValue[] newValues = new TValue[value];
222 Array.Copy(keys, 0, newKeys, 0, _size);
223 Array.Copy(values, 0, newValues, 0, _size);
230 values = emptyValues;
236 public IComparer<TKey> Comparer {
242 void System.Collections.IDictionary.Add(Object key, Object value) {
245 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
248 ThrowHelper.IfNullAndNullsAreIllegalThenThrow<TValue>(value, ExceptionArgument.value);
251 TKey tempKey = (TKey)key;
254 Add(tempKey, (TValue)value);
256 catch (InvalidCastException) {
257 ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(TValue));
260 catch (InvalidCastException) {
261 ThrowHelper.ThrowWrongKeyTypeArgumentException(key, typeof(TKey));
265 // Returns the number of entries in this sorted list.
273 // Returns a collection representing the keys of this sorted list. This
274 // method returns the same object as GetKeyList, but typed as an
275 // ICollection instead of an IList.
277 public IList<TKey> Keys {
279 return GetKeyListHelper();
283 ICollection<TKey> IDictionary<TKey,TValue>.Keys {
285 return GetKeyListHelper();
289 System.Collections.ICollection System.Collections.IDictionary.Keys {
291 return GetKeyListHelper();
295 // Returns a collection representing the values of this sorted list. This
296 // method returns the same object as GetValueList, but typed as an
297 // ICollection instead of an IList.
299 public IList<TValue> Values {
301 return GetValueListHelper();
305 ICollection<TValue> IDictionary<TKey,TValue>.Values {
307 return GetValueListHelper();
311 System.Collections.ICollection System.Collections.IDictionary.Values {
313 return GetValueListHelper();
317 private KeyList GetKeyListHelper() {
319 keyList = new KeyList(this);
323 private ValueList GetValueListHelper() {
324 if (valueList == null)
325 valueList = new ValueList(this);
329 bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly {
330 get { return false; }
333 bool System.Collections.IDictionary.IsReadOnly {
334 get { return false; }
337 bool System.Collections.IDictionary.IsFixedSize {
338 get { return false; }
341 bool System.Collections.ICollection.IsSynchronized {
342 get { return false; }
345 // Synchronization root for this object.
346 Object System.Collections.ICollection.SyncRoot {
348 if( _syncRoot == null) {
349 System.Threading.Interlocked.CompareExchange(ref _syncRoot, new Object(), null);
355 // Removes all entries from this sorted list.
356 public void Clear() {
357 // clear does not change the capacity
359 // Don't need to doc this but we clear the elements so that the gc can reclaim the references.
360 Array.Clear(keys, 0, _size);
361 Array.Clear(values, 0, _size);
366 bool System.Collections.IDictionary.Contains(Object key) {
367 if( IsCompatibleKey(key)) {
368 return ContainsKey((TKey) key);
373 // Checks if this sorted list contains an entry with the given key.
375 public bool ContainsKey(TKey key) {
376 return IndexOfKey(key) >= 0;
379 // Checks if this sorted list contains an entry with the given value. The
380 // values of the entries of the sorted list are compared to the given value
381 // using the Object.Equals method. This method performs a linear
382 // search and is substantially slower than the Contains
385 public bool ContainsValue(TValue value) {
386 return IndexOfValue(value) >= 0;
389 // Copies the values in this SortedList to an array.
390 void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) {
392 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
395 if (arrayIndex < 0 || arrayIndex > array.Length) {
396 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.arrayIndex, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
399 if (array.Length - arrayIndex < Count) {
400 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
403 for (int i = 0; i < Count; i++) {
404 KeyValuePair<TKey, TValue> entry = new KeyValuePair<TKey, TValue>(keys[i],values[i]);
405 array[arrayIndex + i] = entry;
409 void System.Collections.ICollection.CopyTo(Array array, int arrayIndex) {
411 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
414 if (array.Rank != 1) {
415 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
418 if( array.GetLowerBound(0) != 0 ) {
419 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
422 if (arrayIndex < 0 || arrayIndex > array.Length) {
423 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.arrayIndex, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
426 if (array.Length - arrayIndex < Count) {
427 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
430 KeyValuePair<TKey, TValue>[] keyValuePairArray = array as KeyValuePair<TKey, TValue>[];
431 if (keyValuePairArray != null) {
432 for (int i = 0; i < Count; i++) {
433 keyValuePairArray[i + arrayIndex] = new KeyValuePair<TKey, TValue>(keys[i],values[i]);
437 object[] objects = array as object[];
438 if( objects == null) {
439 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
443 for (int i = 0; i < Count; i++) {
444 objects[i + arrayIndex] = new KeyValuePair<TKey, TValue>(keys[i],values[i]);
447 catch(ArrayTypeMismatchException) {
448 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
454 private const int MaxArrayLength = 0X7FEFFFFF;
456 // Ensures that the capacity of this sorted list is at least the given
457 // minimum value. If the currect capacity of the list is less than
458 // min, the capacity is increased to twice the current capacity or
459 // to min, whichever is larger.
460 private void EnsureCapacity(int min) {
461 int newCapacity = keys.Length == 0? _defaultCapacity: keys.Length * 2;
462 // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.
463 // Note that this check works even when _items.Length overflowed thanks to the (uint) cast
464 if ((uint)newCapacity > MaxArrayLength) newCapacity = MaxArrayLength;
465 if (newCapacity < min) newCapacity = min;
466 Capacity = newCapacity;
469 // Returns the value of the entry at the given index.
471 private TValue GetByIndex(int index) {
472 if (index < 0 || index >= _size)
473 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
474 return values[index];
478 public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() {
479 return new Enumerator(this, Enumerator.KeyValuePair);
482 IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
484 return new Enumerator(this, Enumerator.KeyValuePair);
487 System.Collections.IDictionaryEnumerator System.Collections.IDictionary.GetEnumerator() {
488 return new Enumerator(this, Enumerator.DictEntry);
491 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
492 return new Enumerator(this, Enumerator.KeyValuePair);
496 // Returns the key of the entry at the given index.
498 private TKey GetKey(int index) {
499 if (index < 0 || index >= _size) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
504 // Returns the value associated with the given key. If an entry with the
505 // given key is not found, the returned value is null.
507 public TValue this[TKey key] {
509 int i = IndexOfKey(key);
513 ThrowHelper.ThrowKeyNotFoundException();
514 return default(TValue);
517 if (((Object) key) == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
518 int i = Array.BinarySearch<TKey>(keys, 0, _size, key, comparer);
524 Insert(~i, key, value);
528 Object System.Collections.IDictionary.this[Object key] {
530 if( IsCompatibleKey(key)) {
531 int i = IndexOfKey((TKey)key);
540 if(!IsCompatibleKey(key)) {
541 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
544 ThrowHelper.IfNullAndNullsAreIllegalThenThrow<TValue>(value, ExceptionArgument.value);
547 TKey tempKey = (TKey)key;
549 this[tempKey] = (TValue)value;
551 catch (InvalidCastException) {
552 ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(TValue));
555 catch (InvalidCastException) {
556 ThrowHelper.ThrowWrongKeyTypeArgumentException(key, typeof(TKey));
561 // Returns the index of the entry with a given key in this sorted list. The
562 // key is located through a binary search, and thus the average execution
563 // time of this method is proportional to Log2(size), where
564 // size is the size of this sorted list. The returned value is -1 if
565 // the given key does not occur in this sorted list. Null is an invalid
568 public int IndexOfKey(TKey key) {
570 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
571 int ret = Array.BinarySearch<TKey>(keys, 0, _size, key, comparer);
572 return ret >=0 ? ret : -1;
575 // Returns the index of the first occurrence of an entry with a given value
576 // in this sorted list. The entry is located through a linear search, and
577 // thus the average execution time of this method is proportional to the
578 // size of this sorted list. The elements of the list are compared to the
579 // given value using the Object.Equals method.
581 public int IndexOfValue(TValue value) {
582 return Array.IndexOf(values, value, 0, _size);
585 // Inserts an entry with a given key and value at a given index.
586 private void Insert(int index, TKey key, TValue value) {
587 if (_size == keys.Length) EnsureCapacity(_size + 1);
589 Array.Copy(keys, index, keys, index + 1, _size - index);
590 Array.Copy(values, index, values, index + 1, _size - index);
593 values[index] = value;
598 public bool TryGetValue(TKey key, out TValue value) {
599 int i = IndexOfKey(key);
605 value = default(TValue);
609 // Removes the entry at the given index. The size of the sorted list is
612 public void RemoveAt(int index) {
613 if (index < 0 || index >= _size) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
616 Array.Copy(keys, index + 1, keys, index, _size - index);
617 Array.Copy(values, index + 1, values, index, _size - index);
619 keys[_size] = default(TKey);
620 values[_size] = default(TValue);
624 // Removes an entry from this sorted list. If an entry with the specified
625 // key exists in the sorted list, it is removed. An ArgumentException is
626 // thrown if the key is null.
628 public bool Remove(TKey key) {
629 int i = IndexOfKey(key);
635 void System.Collections.IDictionary.Remove(Object key) {
636 if( IsCompatibleKey(key)) {
641 // Sets the capacity of this sorted list to the size of the sorted list.
642 // This method can be used to minimize a sorted list's memory overhead once
643 // it is known that no new elements will be added to the sorted list. To
644 // completely clear a sorted list and release all memory referenced by the
645 // sorted list, execute the following statements:
647 // SortedList.Clear();
648 // SortedList.TrimExcess();
650 public void TrimExcess() {
651 int threshold = (int)(((double)keys.Length) * 0.9);
652 if( _size < threshold ) {
657 private static bool IsCompatibleKey(object key) {
659 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
662 return (key is TKey);
666 /// <include file='doc\SortedList.uex' path='docs/doc[@for="SortedListEnumerator"]/*' />
668 private struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>, System.Collections.IDictionaryEnumerator
670 private SortedList<TKey, TValue> _sortedList;
672 private TValue value;
675 private int getEnumeratorRetType; // What should Enumerator.Current return?
677 internal const int KeyValuePair = 1;
678 internal const int DictEntry = 2;
680 internal Enumerator(SortedList<TKey, TValue> sortedList, int getEnumeratorRetType) {
681 this._sortedList = sortedList;
683 version = _sortedList.version;
684 this.getEnumeratorRetType = getEnumeratorRetType;
686 value = default(TValue);
689 public void Dispose()
693 value = default(TValue);
697 Object System.Collections.IDictionaryEnumerator.Key {
699 if( index == 0 || (index == _sortedList.Count + 1) ) {
700 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
707 public bool MoveNext() {
708 if (version != _sortedList.version) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
710 if ( (uint)index < (uint)_sortedList.Count ) {
711 key = _sortedList.keys[index];
712 value = _sortedList.values[index];
717 index = _sortedList.Count + 1;
719 value = default(TValue);
723 DictionaryEntry System.Collections.IDictionaryEnumerator.Entry {
725 if( index == 0 || (index == _sortedList.Count + 1) ) {
726 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
729 return new DictionaryEntry(key, value);
733 public KeyValuePair<TKey, TValue> Current {
735 return new KeyValuePair<TKey, TValue>(key, value);
739 Object System.Collections.IEnumerator.Current {
741 if( index == 0 || (index == _sortedList.Count + 1) ) {
742 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
745 if (getEnumeratorRetType == DictEntry) {
746 return new System.Collections.DictionaryEntry(key, value);
748 return new KeyValuePair<TKey, TValue>(key, value);
753 Object System.Collections.IDictionaryEnumerator.Value {
755 if( index == 0 || (index == _sortedList.Count + 1) ) {
756 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
763 void System.Collections.IEnumerator.Reset() {
764 if (version != _sortedList.version) {
765 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
770 value = default(TValue);
776 private sealed class SortedListKeyEnumerator : IEnumerator<TKey>, System.Collections.IEnumerator
778 private SortedList<TKey, TValue> _sortedList;
781 private TKey currentKey;
783 internal SortedListKeyEnumerator(SortedList<TKey, TValue> sortedList) {
784 _sortedList = sortedList;
785 version = sortedList.version;
788 public void Dispose() {
790 currentKey = default(TKey);
793 public bool MoveNext() {
794 if (version != _sortedList.version) {
795 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
798 if ( (uint)index < (uint)_sortedList.Count) {
799 currentKey = _sortedList.keys[index];
804 index = _sortedList.Count + 1;
805 currentKey = default(TKey);
809 public TKey Current {
815 Object System.Collections.IEnumerator.Current {
817 if( index == 0 || (index == _sortedList.Count + 1) ) {
818 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
825 void System.Collections.IEnumerator.Reset() {
826 if (version != _sortedList.version) {
827 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
830 currentKey = default(TKey);
836 private sealed class SortedListValueEnumerator : IEnumerator<TValue>, System.Collections.IEnumerator
838 private SortedList<TKey, TValue> _sortedList;
841 private TValue currentValue;
843 internal SortedListValueEnumerator(SortedList<TKey, TValue> sortedList) {
844 _sortedList = sortedList;
845 version = sortedList.version;
848 public void Dispose() {
850 currentValue = default(TValue);
853 public bool MoveNext() {
854 if (version != _sortedList.version) {
855 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
858 if ( (uint)index < (uint)_sortedList.Count) {
859 currentValue = _sortedList.values[index];
864 index = _sortedList.Count + 1;
865 currentValue = default(TValue);
869 public TValue Current {
875 Object System.Collections.IEnumerator.Current {
877 if( index == 0 || (index == _sortedList.Count + 1) ) {
878 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
885 void System.Collections.IEnumerator.Reset() {
886 if (version != _sortedList.version) {
887 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
890 currentValue = default(TValue);
895 [DebuggerTypeProxy(typeof(System_DictionaryKeyCollectionDebugView<,>))]
896 [DebuggerDisplay("Count = {Count}")]
898 private sealed class KeyList : IList<TKey>, System.Collections.ICollection
900 private SortedList<TKey, TValue> _dict;
902 internal KeyList(SortedList<TKey, TValue> dictionary) {
903 this._dict = dictionary;
907 get { return _dict._size; }
910 public bool IsReadOnly {
914 bool System.Collections.ICollection.IsSynchronized {
915 get { return false; }
918 Object System.Collections.ICollection.SyncRoot {
919 get { return ((ICollection)_dict).SyncRoot; }
922 public void Add(TKey key) {
923 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_SortedListNestedWrite);
926 public void Clear() {
927 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_SortedListNestedWrite);
930 public bool Contains(TKey key) {
931 return _dict.ContainsKey(key);
934 public void CopyTo(TKey[] array, int arrayIndex) {
935 // defer error checking to Array.Copy
936 Array.Copy(_dict.keys, 0, array, arrayIndex, _dict.Count);
939 void System.Collections.ICollection.CopyTo(Array array, int arrayIndex) {
940 if (array != null && array.Rank != 1)
941 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
944 // defer error checking to Array.Copy
945 Array.Copy(_dict.keys, 0, array, arrayIndex, _dict.Count);
947 catch(ArrayTypeMismatchException){
948 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
952 public void Insert(int index, TKey value) {
953 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_SortedListNestedWrite);
956 public TKey this[int index] {
958 return _dict.GetKey(index);
961 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet);
965 public IEnumerator<TKey> GetEnumerator() {
966 return new SortedListKeyEnumerator(_dict);
969 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
970 return new SortedListKeyEnumerator(_dict);
973 public int IndexOf(TKey key) {
974 if (((Object) key) == null)
975 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
977 int i = Array.BinarySearch<TKey>(_dict.keys, 0,
978 _dict.Count, key, _dict.comparer);
979 if (i >= 0) return i;
983 public bool Remove(TKey key) {
984 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_SortedListNestedWrite);
988 public void RemoveAt(int index) {
989 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_SortedListNestedWrite);
993 [DebuggerTypeProxy(typeof(System_DictionaryValueCollectionDebugView<,>))]
994 [DebuggerDisplay("Count = {Count}")]
996 private sealed class ValueList : IList<TValue>, System.Collections.ICollection
998 private SortedList<TKey, TValue> _dict;
1000 internal ValueList(SortedList<TKey, TValue> dictionary) {
1001 this._dict = dictionary;
1005 get { return _dict._size; }
1008 public bool IsReadOnly {
1009 get { return true; }
1012 bool System.Collections.ICollection.IsSynchronized {
1013 get { return false; }
1016 Object System.Collections.ICollection.SyncRoot {
1017 get { return ((ICollection)_dict).SyncRoot; }
1020 public void Add(TValue key) {
1021 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_SortedListNestedWrite);
1024 public void Clear() {
1025 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_SortedListNestedWrite);
1028 public bool Contains(TValue value) {
1029 return _dict.ContainsValue(value);
1032 public void CopyTo(TValue[] array, int arrayIndex) {
1033 // defer error checking to Array.Copy
1034 Array.Copy(_dict.values, 0, array, arrayIndex, _dict.Count);
1037 void System.Collections.ICollection.CopyTo(Array array, int arrayIndex) {
1038 if (array != null && array.Rank != 1)
1039 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
1042 // defer error checking to Array.Copy
1043 Array.Copy(_dict.values, 0, array, arrayIndex, _dict.Count);
1045 catch(ArrayTypeMismatchException){
1046 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
1050 public void Insert(int index, TValue value) {
1051 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_SortedListNestedWrite);
1054 public TValue this[int index] {
1056 return _dict.GetByIndex(index);
1059 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_SortedListNestedWrite);
1063 public IEnumerator<TValue> GetEnumerator() {
1064 return new SortedListValueEnumerator(_dict);
1067 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
1068 return new SortedListValueEnumerator(_dict);
1071 public int IndexOf(TValue value) {
1072 return Array.IndexOf(_dict.values, value, 0, _dict.Count);
1075 public bool Remove(TValue value) {
1076 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_SortedListNestedWrite);
1080 public void RemoveAt(int index) {
1081 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_SortedListNestedWrite);