diff options
Diffstat (limited to 'src/mscorlib/src/System/Collections/Generic/List.cs')
-rw-r--r-- | src/mscorlib/src/System/Collections/Generic/List.cs | 116 |
1 files changed, 60 insertions, 56 deletions
diff --git a/src/mscorlib/src/System/Collections/Generic/List.cs b/src/mscorlib/src/System/Collections/Generic/List.cs index ae3356d372..3e2947f5f9 100644 --- a/src/mscorlib/src/System/Collections/Generic/List.cs +++ b/src/mscorlib/src/System/Collections/Generic/List.cs @@ -91,14 +91,7 @@ namespace System.Collections.Generic { else { _size = 0; _items = _emptyArray; - // This enumerable could be empty. Let Add allocate a new array, if needed. - // Note it will also go to _defaultCapacity first, not 1, then 2, etc. - - using(IEnumerator<T> en = collection.GetEnumerator()) { - while(en.MoveNext()) { - Add(en.Current); - } - } + AddEnumerable(collection); } } @@ -274,7 +267,7 @@ namespace System.Collections.Generic { // public int BinarySearch(int index, int count, T item, IComparer<T> comparer) { if (index < 0) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); if (count < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); if (_size - index < count) @@ -369,7 +362,7 @@ namespace System.Collections.Generic { Array.Copy(_items, 0, array, arrayIndex, _size); } catch(ArrayTypeMismatchException){ - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } } @@ -393,7 +386,7 @@ namespace System.Collections.Generic { } // Ensures that the capacity of this list is at least the given minimum - // value. If the currect capacity of the list is less than min, the + // value. If the current 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) { @@ -454,11 +447,11 @@ namespace System.Collections.Generic { public int FindIndex(int startIndex, int count, Predicate<T> match) { if( (uint)startIndex > (uint)_size ) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); } if (count < 0 || startIndex > _size - count) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count); + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); } if( match == null) { @@ -512,19 +505,19 @@ namespace System.Collections.Generic { if(_size == 0) { // Special case for 0 length List if( startIndex != -1) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); } } else { // Make sure we're not out of range if ( (uint)startIndex >= (uint)_size) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index(); } } // 2nd have of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0. if (count < 0 || startIndex - count + 1 < 0) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count); + ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); } int endIndex = startIndex - count; @@ -545,14 +538,14 @@ namespace System.Collections.Generic { int version = _version; for(int i = 0 ; i < _size; i++) { - if (version != _version && BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) { + if (version != _version) { break; } action(_items[i]); } - if (version != _version && BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); + if (version != _version) + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } // Returns an enumerator for this list with the given @@ -575,7 +568,7 @@ namespace System.Collections.Generic { public List<T> GetRange(int index, int count) { if (index < 0) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (count < 0) { @@ -628,7 +621,7 @@ namespace System.Collections.Generic { // public int IndexOf(T item, int index) { if (index > _size) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowArgumentOutOfRange_IndexException(); Contract.Ensures(Contract.Result<int>() >= -1); Contract.Ensures(Contract.Result<int>() < Count); Contract.EndContractBlock(); @@ -646,9 +639,9 @@ namespace System.Collections.Generic { // public int IndexOf(T item, int index, int count) { if (index > _size) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowArgumentOutOfRange_IndexException(); - if (count <0 || index > _size - count) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count); + if (count <0 || index > _size - count) ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); Contract.Ensures(Contract.Result<int>() >= -1); Contract.Ensures(Contract.Result<int>() < Count); Contract.EndContractBlock(); @@ -698,7 +691,7 @@ namespace System.Collections.Generic { } if ((uint)index > (uint)_size) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowArgumentOutOfRange_IndexException(); } Contract.EndContractBlock(); @@ -719,20 +712,24 @@ namespace System.Collections.Generic { Array.Copy(_items, index+count, _items, index*2, _size-index); } else { - T[] itemsToInsert = new T[count]; - c.CopyTo(itemsToInsert, 0); - itemsToInsert.CopyTo(_items, index); + c.CopyTo(_items, index); } _size += count; } } - else { + else if (index < _size) { + // We're inserting a lazy enumerable. Call Insert on each of the constituent items. using(IEnumerator<T> en = collection.GetEnumerator()) { while(en.MoveNext()) { Insert(index++, en.Current); } } } + else + { + // We're adding a lazy enumerable because the index is at the end of this list. + AddEnumerable(collection); + } _version++; } @@ -768,7 +765,7 @@ namespace System.Collections.Generic { public int LastIndexOf(T item, int index) { if (index >= _size) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index); + ThrowHelper.ThrowArgumentOutOfRange_IndexException(); Contract.Ensures(Contract.Result<int>() >= -1); Contract.Ensures(((Count == 0) && (Contract.Result<int>() == -1)) || ((Count > 0) && (Contract.Result<int>() <= index))); Contract.EndContractBlock(); @@ -786,7 +783,7 @@ namespace System.Collections.Generic { // public int LastIndexOf(T item, int index, int count) { if ((Count != 0) && (index < 0)) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if ((Count !=0) && (count < 0)) { @@ -885,7 +882,7 @@ namespace System.Collections.Generic { // public void RemoveRange(int index, int count) { if (index < 0) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (count < 0) { @@ -919,7 +916,7 @@ namespace System.Collections.Generic { // public void Reverse(int index, int count) { if (index < 0) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (count < 0) { @@ -930,22 +927,7 @@ namespace System.Collections.Generic { ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); Contract.EndContractBlock(); - // The non-generic Array.Reverse is not used because it does not perform - // well for non-primitive value types. - // If/when a generic Array.Reverse<T> becomes available, the below code - // can be deleted and replaced with a call to Array.Reverse<T>. - int i = index; - int j = index + count - 1; - T[] array = _items; - while (i < j) - { - T temp = array[i]; - array[i] = array[j]; - array[j] = temp; - i++; - j--; - } - + Array.Reverse(_items, index, count); _version++; } @@ -973,7 +955,7 @@ namespace System.Collections.Generic { // public void Sort(int index, int count, IComparer<T> comparer) { if (index < 0) { - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } if (count < 0) { @@ -995,8 +977,7 @@ namespace System.Collections.Generic { Contract.EndContractBlock(); if( _size > 0) { - IComparer<T> comparer = Comparer<T>.Create(comparison); - Array.Sort(_items, 0, _size, comparer); + ArraySortHelper<T>.Sort(_items, 0, _size, comparison); } } @@ -1006,12 +987,10 @@ namespace System.Collections.Generic { Contract.Ensures(Contract.Result<T[]>() != null); Contract.Ensures(Contract.Result<T[]>().Length == Count); -#if FEATURE_CORECLR if (_size == 0) { return _emptyArray; } -#endif T[] array = new T[_size]; Array.Copy(_items, 0, array, 0, _size); @@ -1048,6 +1027,31 @@ namespace System.Collections.Generic { return true; } + private void AddEnumerable(IEnumerable<T> enumerable) + { + Debug.Assert(enumerable != null); + Debug.Assert(!(enumerable is ICollection<T>), "We should have optimized for this beforehand."); + + using (IEnumerator<T> en = enumerable.GetEnumerator()) + { + _version++; // Even if the enumerable has no items, we can update _version. + + while (en.MoveNext()) + { + // Capture Current before doing anything else. If this throws + // an exception, we want to make a clean break. + T current = en.Current; + + if (_size == _items.Length) + { + EnsureCapacity(_size + 1); + } + + _items[_size++] = current; + } + } + } + [Serializable] public struct Enumerator : IEnumerator<T>, System.Collections.IEnumerator { @@ -1082,7 +1086,7 @@ namespace System.Collections.Generic { private bool MoveNextRare() { if (version != list._version) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } index = list._size + 1; @@ -1099,7 +1103,7 @@ namespace System.Collections.Generic { Object System.Collections.IEnumerator.Current { get { if( index == 0 || index == list._size + 1) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } return Current; } @@ -1107,7 +1111,7 @@ namespace System.Collections.Generic { void System.Collections.IEnumerator.Reset() { if (version != list._version) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } index = 0; |