diff --git a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs index 7b458a0ae13581..8facde37fce4fb 100644 --- a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs +++ b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs @@ -1650,7 +1650,7 @@ bool ICollection>.Remove(KeyValuePair k /// of the dictionary. The contents exposed through the enumerator may contain modifications /// made to the dictionary after was called. /// - IEnumerator IEnumerable.GetEnumerator() => ((ConcurrentDictionary)this).GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); #endregion @@ -2294,9 +2294,9 @@ internal Tables(VolatileNode[] buckets, object[] locks, int[] countPerLock, IEqu /// private sealed class DictionaryEnumerator : IDictionaryEnumerator { - private readonly IEnumerator> _enumerator; // Enumerator over the dictionary. + private readonly Enumerator _enumerator; // Enumerator over the dictionary. - internal DictionaryEnumerator(ConcurrentDictionary dictionary) => _enumerator = dictionary.GetEnumerator(); + internal DictionaryEnumerator(ConcurrentDictionary dictionary) => _enumerator = new Enumerator(dictionary); public DictionaryEntry Entry => new DictionaryEntry(_enumerator.Current.Key, _enumerator.Current.Value); diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/LinkedList.cs b/src/libraries/System.Collections/src/System/Collections/Generic/LinkedList.cs index 14dbc030d7a148..8ff8b6c2741e2b 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/LinkedList.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/LinkedList.cs @@ -505,8 +505,8 @@ public struct Enumerator : IEnumerator, IEnumerator, ISerializable, IDeserial private readonly LinkedList _list; private LinkedListNode? _node; private readonly int _version; + private bool _valid; private T? _current; - private int _index; internal Enumerator(LinkedList list) { @@ -514,7 +514,7 @@ internal Enumerator(LinkedList list) _version = list.version; _node = list.head; _current = default; - _index = 0; + _valid = false; } public T Current => _current!; @@ -523,7 +523,7 @@ internal Enumerator(LinkedList list) { get { - if (_index == 0 || (_index == _list.Count + 1)) + if (!_valid) { throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen); } @@ -541,11 +541,11 @@ public bool MoveNext() if (_node == null) { - _index = _list.Count + 1; + _valid = false; return false; } - ++_index; + _valid = true; _current = _node.item; _node = _node.next; if (_node == _list.head) @@ -564,7 +564,7 @@ void IEnumerator.Reset() _current = default; _node = _list.head; - _index = 0; + _valid = false; } public void Dispose() diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs b/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs index c5f7c7e7e0c28d..fd38e64e18f321 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs @@ -1034,7 +1034,6 @@ private bool MoveNextRare() throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion); } - _index = _queue._size + 1; _current = default; return false; } diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/SortedList.cs b/src/libraries/System.Collections/src/System/Collections/Generic/SortedList.cs index 9b010bbca060bd..a73a25d00d440d 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/SortedList.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/SortedList.cs @@ -780,7 +780,7 @@ object IDictionaryEnumerator.Key { get { - if (_index == 0 || (_index == _sortedList.Count + 1)) + if (_index <= 0) { throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen); } @@ -801,7 +801,7 @@ public bool MoveNext() return true; } - _index = _sortedList.Count + 1; + _index = -1; _key = default; _value = default; return false; @@ -811,7 +811,7 @@ DictionaryEntry IDictionaryEnumerator.Entry { get { - if (_index == 0 || (_index == _sortedList.Count + 1)) + if (_index <= 0) { throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen); } @@ -826,7 +826,7 @@ DictionaryEntry IDictionaryEnumerator.Entry { get { - if (_index == 0 || (_index == _sortedList.Count + 1)) + if (_index <= 0) { throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen); } @@ -846,7 +846,7 @@ DictionaryEntry IDictionaryEnumerator.Entry { get { - if (_index == 0 || (_index == _sortedList.Count + 1)) + if (_index <= 0) { throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen); } @@ -901,7 +901,7 @@ public bool MoveNext() return true; } - _index = _sortedList.Count + 1; + _index = -1; _currentKey = default; return false; } @@ -912,7 +912,7 @@ public bool MoveNext() { get { - if (_index == 0 || (_index == _sortedList.Count + 1)) + if (_index <= 0) { throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen); } @@ -965,7 +965,7 @@ public bool MoveNext() return true; } - _index = _sortedList.Count + 1; + _index = -1; _currentValue = default; return false; } @@ -976,7 +976,7 @@ public bool MoveNext() { get { - if (_index == 0 || (_index == _sortedList.Count + 1)) + if (_index <= 0) { throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen); } diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/SortedSet.cs b/src/libraries/System.Collections/src/System/Collections/Generic/SortedSet.cs index 4ab5df4f1274c1..d33359288676ab 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/SortedSet.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/SortedSet.cs @@ -1832,11 +1832,10 @@ private bool HasChildren(Node child1, Node child2) public struct Enumerator : IEnumerator, IEnumerator, ISerializable, IDeserializationCallback { private readonly SortedSet _tree; - private readonly int _version; - private readonly Stack _stack; private Node? _current; + private readonly int _version; private readonly bool _reverse; internal Enumerator(SortedSet set) diff --git a/src/libraries/System.Private.CoreLib/src/System/Array.Enumerators.cs b/src/libraries/System.Private.CoreLib/src/System/Array.Enumerators.cs index 0acdb27afa622b..ea12bb8235845e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Array.Enumerators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Array.Enumerators.cs @@ -28,10 +28,9 @@ public object Clone() public bool MoveNext() { nint index = _index + 1; - nuint length = _array.NativeLength; - if ((nuint)index >= length) + if ((nuint)index >= _array.NativeLength) { - _index = (nint)length; + _index = -2; return false; } _index = index; @@ -47,14 +46,7 @@ public object? Current if ((nuint)index >= array.NativeLength) { - if (index < 0) - { - ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumNotStarted(); - } - else - { - ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumEnded(); - } + ThrowHelper.ThrowInvalidOperationException_EnumCurrent((int)index); } return array.InternalGetValue(index); @@ -140,7 +132,7 @@ public object Current { get { - ThrowHelper.ThrowInvalidOperationException_EnumCurrent(-1); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumNotStarted(); return default; } } @@ -167,7 +159,7 @@ private GenericEmptyEnumerator() { } { get { - ThrowHelper.ThrowInvalidOperationException_EnumCurrent(-1); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumNotStarted(); return default; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs b/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs index e62a847e764eb6..052a3bd230ff69 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs @@ -300,11 +300,13 @@ internal Enumerator(ArraySegment arraySegment) public bool MoveNext() { - if (_current < _end) + int current = _current + 1; + if ((uint)current < (uint)_end) { - _current++; - return _current < _end; + _current = current; + return true; } + _current = -2; return false; } @@ -313,9 +315,7 @@ public T Current get { if (_current < _start) - ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumNotStarted(); - if (_current >= _end) - ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumEnded(); + ThrowHelper.ThrowInvalidOperationException_EnumCurrent(_current - _start); return _array![_current]; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/CharEnumerator.cs b/src/libraries/System.Private.CoreLib/src/System/CharEnumerator.cs index dbe151378d8f95..95443b83438f29 100644 --- a/src/libraries/System.Private.CoreLib/src/System/CharEnumerator.cs +++ b/src/libraries/System.Private.CoreLib/src/System/CharEnumerator.cs @@ -19,15 +19,13 @@ public sealed class CharEnumerator : IEnumerator, IEnumerator, IDisposable public bool MoveNext() { int index = _index + 1; - int length = _str.Length; - - if (index < length) + if ((uint)index < (uint)_str.Length) { _index = index; return true; } - _index = length; + _index = -2; return false; } @@ -43,7 +41,7 @@ public char Current string s = _str; if ((uint)index >= (uint)s.Length) { - ThrowHelper.ThrowInvalidOperationException_EnumCurrent(_index); + ThrowHelper.ThrowInvalidOperationException_EnumCurrent(index); } return s[index]; diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/ArrayList.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/ArrayList.cs index 7090ea8919a549..b81c63de8172be 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/ArrayList.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/ArrayList.cs @@ -2553,16 +2553,12 @@ private sealed class ArrayListEnumeratorSimple : IEnumerator, ICloneable private readonly int _version; private object? _currentElement; private readonly bool _isArrayList; - // this object is used to indicate enumeration has not started or has terminated - private static readonly object s_dummyObject = new object(); internal ArrayListEnumeratorSimple(ArrayList list) { _list = list; - _index = -1; _version = list._version; _isArrayList = (list.GetType() == typeof(ArrayList)); - _currentElement = s_dummyObject; } public object Clone() => MemberwiseClone(); @@ -2571,57 +2567,41 @@ public bool MoveNext() { if (_version != _list._version) { - throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } if (_isArrayList) { // avoid calling virtual methods if we are operating on ArrayList to improve performance - if (_index < _list._size - 1) + if ((uint)_index < (uint)_list._size) { - _currentElement = _list._items[++_index]; + _currentElement = _list._items[_index++]; return true; } - else - { - _currentElement = s_dummyObject; - _index = _list._size; - return false; - } } else { - if (_index < _list.Count - 1) + if ((uint)_index < (uint)_list.Count) { - _currentElement = _list[++_index]; + _currentElement = _list[_index++]; return true; } - else - { - _index = _list.Count; - _currentElement = s_dummyObject; - return false; - } } + + _index = -1; + _currentElement = null; + return false; } public object? Current { get { - object? temp = _currentElement; - if (s_dummyObject == temp) - { // check if enumeration has not started or has terminated - if (_index == -1) - { - throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted); - } - else - { - throw new InvalidOperationException(SR.InvalidOperation_EnumEnded); - } + if (_index <= 0) + { + ThrowHelper.ThrowInvalidOperationException_EnumCurrent(_index - 1); } - return temp; + return _currentElement; } } @@ -2629,11 +2609,11 @@ public void Reset() { if (_version != _list._version) { - throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } - _currentElement = s_dummyObject; - _index = -1; + _currentElement = null; + _index = 0; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/BitArray.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/BitArray.cs index 66fe6f6c37eff6..b3a0588e2c2f62 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/BitArray.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/BitArray.cs @@ -983,7 +983,7 @@ private sealed class BitArrayEnumeratorSimple : IEnumerator, ICloneable private readonly BitArray _bitArray; private readonly int _version; private int _index; - private object _currentElement = s_boxedFalse; + private bool _current; internal BitArrayEnumeratorSimple(BitArray bitArray) { @@ -998,17 +998,18 @@ public bool MoveNext() { if (_version != _bitArray._version) { - throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } - if (_index < (_bitArray._bitLength - 1)) + int index = _index + 1; + if ((uint)index < (uint)_bitArray._bitLength) { - _index++; - _currentElement = _bitArray.Get(_index) ? s_boxedTrue : s_boxedFalse; + _index = index; + _current = _bitArray.Get(index); return true; } - _index = _bitArray._bitLength; + _index = -2; return false; } @@ -1016,12 +1017,12 @@ public object Current { get { - if ((uint)_index >= (uint)_bitArray._bitLength) + if (_index < 0) { - throw GetInvalidOperationException(_index); + ThrowHelper.ThrowInvalidOperationException_EnumCurrent(_index); } - return _currentElement; + return _current ? s_boxedTrue : s_boxedFalse; } } @@ -1029,24 +1030,11 @@ public void Reset() { if (_version != _bitArray._version) { - throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion); + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } _index = -1; } - - private InvalidOperationException GetInvalidOperationException(int index) - { - if (index == -1) - { - return new InvalidOperationException(SR.InvalidOperation_EnumNotStarted); - } - else - { - Debug.Assert(index >= _bitArray._bitLength); - return new InvalidOperationException(SR.InvalidOperation_EnumEnded); - } - } } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs index c890bbed83c7ef..83863a2b7f8212 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs @@ -1771,7 +1771,7 @@ public struct Enumerator : IEnumerator>, IDictionaryE private readonly int _getEnumeratorRetType; // What should Enumerator.Current return? internal const int DictEntry = 1; - internal const int KeyValuePair = 2; + internal const int KeyValuePair = 0; internal Enumerator(Dictionary dictionary, int getEnumeratorRetType) { @@ -1789,8 +1789,6 @@ public bool MoveNext() ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } - // Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends. - // dictionary.count+1 could be negative if dictionary.count is int.MaxValue while ((uint)_index < (uint)_dictionary._count) { ref Entry entry = ref _dictionary._entries![_index++]; @@ -1802,7 +1800,7 @@ public bool MoveNext() } } - _index = _dictionary._count + 1; + _index = -1; _current = default; return false; } @@ -1815,7 +1813,7 @@ public void Dispose() { } { get { - if (_index == 0 || (_index == _dictionary._count + 1)) + if (_index <= 0) { ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } @@ -1825,7 +1823,7 @@ public void Dispose() { } return new DictionaryEntry(_current.Key, _current.Value); } - return new KeyValuePair(_current.Key, _current.Value); + return _current; } } @@ -1844,7 +1842,7 @@ DictionaryEntry IDictionaryEnumerator.Entry { get { - if (_index == 0 || (_index == _dictionary._count + 1)) + if (_index <= 0) { ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } @@ -1857,7 +1855,7 @@ object IDictionaryEnumerator.Key { get { - if (_index == 0 || (_index == _dictionary._count + 1)) + if (_index <= 0) { ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } @@ -1870,7 +1868,7 @@ object IDictionaryEnumerator.Key { get { - if (_index == 0 || (_index == _dictionary._count + 1)) + if (_index <= 0) { ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } @@ -2042,7 +2040,7 @@ public bool MoveNext() } } - _index = _dictionary._count + 1; + _index = -1; _currentKey = default; return false; } @@ -2053,7 +2051,7 @@ public bool MoveNext() { get { - if (_index == 0 || (_index == _dictionary._count + 1)) + if (_index <= 0) { ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } @@ -2235,7 +2233,7 @@ public bool MoveNext() return true; } } - _index = _dictionary._count + 1; + _index = -1; _currentValue = default; return false; } @@ -2246,7 +2244,7 @@ public bool MoveNext() { get { - if (_index == 0 || (_index == _dictionary._count + 1)) + if (_index <= 0) { ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/HashSet.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/HashSet.cs index 026456617f8997..115343410ddc62 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/HashSet.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/HashSet.cs @@ -1817,8 +1817,6 @@ public bool MoveNext() ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } - // Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends. - // dictionary.count+1 could be negative if dictionary.count is int.MaxValue while ((uint)_index < (uint)_hashSet._count) { ref Entry entry = ref _hashSet._entries![_index++]; @@ -1829,7 +1827,7 @@ public bool MoveNext() } } - _index = _hashSet._count + 1; + _index = -1; _current = default!; return false; } @@ -1842,7 +1840,7 @@ public void Dispose() { } { get { - if (_index == 0 || (_index == _hashSet._count + 1)) + if (_index <= 0) { ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs index 1df1ea89696c5f..fdcec661ee6d18 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs @@ -1205,23 +1205,19 @@ public bool MoveNext() { List localList = _list; - if (_version == localList._version && ((uint)_index < (uint)localList._size)) + if (_version != localList._version) { - _current = localList._items[_index]; - _index++; - return true; + ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } - return MoveNextRare(); - } - private bool MoveNextRare() - { - if (_version != _list._version) + if ((uint)_index < (uint)localList._size) { - ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); + _current = localList._items[_index]; + _index++; + return true; } - _index = _list._size + 1; + _index = -1; _current = default; return false; } @@ -1232,7 +1228,7 @@ private bool MoveNextRare() { get { - if (_index == 0 || _index == _list._size + 1) + if (_index <= 0) { ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen(); } diff --git a/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs b/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs index 90c8b2163d91f6..d8ec85e88f4fca 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs @@ -758,7 +758,7 @@ private static ArgumentOutOfRangeException GetArgumentOutOfRangeException(Except private static InvalidOperationException GetInvalidOperationException_EnumCurrent(int index) { return new InvalidOperationException( - index < 0 ? + index == -1 ? SR.InvalidOperation_EnumNotStarted : SR.InvalidOperation_EnumEnded); }