From 6ba7183870b7791f40e541501c7d8b34c148d9a7 Mon Sep 17 00:00:00 2001 From: hrrrrustic Date: Sun, 7 May 2023 00:07:24 +0300 Subject: [PATCH 01/17] Implement hashset --- .../System.Collections/ref/System.Collections.cs | 2 ++ .../src/System/Collections/Generic/HashSet.cs | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Collections/ref/System.Collections.cs b/src/libraries/System.Collections/ref/System.Collections.cs index c12b04c3a3cf07..64b4eb3ba5be1f 100644 --- a/src/libraries/System.Collections/ref/System.Collections.cs +++ b/src/libraries/System.Collections/ref/System.Collections.cs @@ -582,6 +582,7 @@ public HashSet(int capacity, System.Collections.Generic.IEqualityComparer? co protected HashSet(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } public System.Collections.Generic.IEqualityComparer Comparer { get { throw null; } } public int Count { get { throw null; } } + public int Capacity { get { throw null; } } bool System.Collections.Generic.ICollection.IsReadOnly { get { throw null; } } public bool Add(T item) { throw null; } public void Clear() { } @@ -611,6 +612,7 @@ void System.Collections.Generic.ICollection.Add(T item) { } System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() { throw null; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } public void TrimExcess() { } + public void TrimExcess(int capacity) { } public bool TryGetValue(T equalValue, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out T actualValue) { throw null; } public void UnionWith(System.Collections.Generic.IEnumerable other) { } public partial struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable 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 668550bddf66b5..7bb47c1a701476 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 @@ -353,6 +353,8 @@ public bool Remove(T item) /// Gets the number of elements that are contained in the set. public int Count => _count - _freeCount; + public int Capacity => _count; + bool ICollection.IsReadOnly => false; #endregion @@ -1005,10 +1007,10 @@ private void Resize(int newSize, bool forceNewHashCodes) /// Sets the capacity of a object to the actual number of elements it contains, /// rounded up to a nearby, implementation-specific value. /// - public void TrimExcess() - { - int capacity = Count; + public void TrimExcess() => TrimExcess(Count); + public void TrimExcess(int capacity) + { int newSize = HashHelpers.GetPrime(capacity); Entry[]? oldEntries = _entries; int currentCapacity = oldEntries == null ? 0 : oldEntries.Length; From 9dcfca968b53340d2f8eaa36bdca66de680c6ef0 Mon Sep 17 00:00:00 2001 From: hrrrrustic Date: Sun, 7 May 2023 00:07:47 +0300 Subject: [PATCH 02/17] Implement queue & stack & dictionary --- .../ref/System.Collections.cs | 5 ++++ .../src/System/Collections/Generic/Stack.cs | 23 ++++++++++++------- .../System/Collections/Generic/Dictionary.cs | 2 ++ .../src/System/Collections/Generic/Queue.cs | 23 ++++++++++++------- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/libraries/System.Collections/ref/System.Collections.cs b/src/libraries/System.Collections/ref/System.Collections.cs index 64b4eb3ba5be1f..2fa8f622b611f6 100644 --- a/src/libraries/System.Collections/ref/System.Collections.cs +++ b/src/libraries/System.Collections/ref/System.Collections.cs @@ -379,6 +379,7 @@ public Stack() { } public Stack(System.Collections.Generic.IEnumerable collection) { } public Stack(int capacity) { } public int Count { get { throw null; } } + public int Capacity { get { throw null; } } bool System.Collections.ICollection.IsSynchronized { get { throw null; } } object System.Collections.ICollection.SyncRoot { get { throw null; } } public void Clear() { } @@ -394,6 +395,7 @@ void System.Collections.ICollection.CopyTo(System.Array array, int arrayIndex) { public int EnsureCapacity(int capacity) { throw null; } public T[] ToArray() { throw null; } public void TrimExcess() { } + public void TrimExcess(int capacity) { } public bool TryPeek([System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out T result) { throw null; } public bool TryPop([System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out T result) { throw null; } public partial struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable @@ -447,6 +449,7 @@ public Dictionary(int capacity, System.Collections.Generic.IEqualityComparer Comparer { get { throw null; } } public int Count { get { throw null; } } + public int Capacity { get { throw null; } } public TValue this[TKey key] { get { throw null; } set { } } public System.Collections.Generic.Dictionary.KeyCollection Keys { get { throw null; } } bool System.Collections.Generic.ICollection>.IsReadOnly { get { throw null; } } @@ -715,6 +718,7 @@ public Queue() { } public Queue(System.Collections.Generic.IEnumerable collection) { } public Queue(int capacity) { } public int Count { get { throw null; } } + public int Capacity { get { throw null; } } bool System.Collections.ICollection.IsSynchronized { get { throw null; } } object System.Collections.ICollection.SyncRoot { get { throw null; } } public void Clear() { } @@ -729,6 +733,7 @@ void System.Collections.ICollection.CopyTo(System.Array array, int index) { } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } public T[] ToArray() { throw null; } public void TrimExcess() { } + public void TrimExcess(int capacity) { } public int EnsureCapacity(int capacity) { throw null; } public bool TryDequeue([System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out T result) { throw null; } public bool TryPeek([System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out T result) { throw null; } diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs b/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs index 2bc209c6a01e0b..19e057538304a0 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs @@ -54,15 +54,11 @@ public Stack(IEnumerable collection) _array = EnumerableHelpers.ToArray(collection, out _size); } - public int Count - { - get { return _size; } - } + public int Count => _size; - bool ICollection.IsSynchronized - { - get { return false; } - } + public int Capacity => _array.Length; + + bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; @@ -170,6 +166,17 @@ public void TrimExcess() } } + public void TrimExcess(int capacity) + { + ArgumentOutOfRangeException.ThrowIfNegativeOrZero(capacity); + ArgumentOutOfRangeException.ThrowIfLessThan(capacity, _size); + + if (capacity == _size) + return; + + Array.Resize(ref _array, capacity); + } + // Returns the top object on the stack without removing it. If the stack // is empty, Peek throws an InvalidOperationException. public T Peek() 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 39770356157442..8c2c3504e75320 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 @@ -208,6 +208,8 @@ public IEqualityComparer Comparer public int Count => _count - _freeCount; + public int Capacity => _count; + public KeyCollection Keys => _keys ??= new KeyCollection(this); ICollection IDictionary.Keys => Keys; diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs index 9d9ec66416736d..ed77bedb0208af 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs @@ -52,15 +52,11 @@ public Queue(IEnumerable collection) if (_size != _array.Length) _tail = _size; } - public int Count - { - get { return _size; } - } + public int Count => _size; - bool ICollection.IsSynchronized - { - get { return false; } - } + public int Capacity => _array.Length; + + bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; @@ -358,6 +354,17 @@ public void TrimExcess() } } + public void TrimExcess(int capacity) + { + ArgumentOutOfRangeException.ThrowIfNegative(capacity); + ArgumentOutOfRangeException.ThrowIfLessThan(capacity, _size); + + if (capacity == _size) + return; + + SetCapacity(capacity); + } + /// /// Ensures that the capacity of this Queue is at least the specified . /// From 3755185e125b182e0fe668cd7ff8394a9c6c58f6 Mon Sep 17 00:00:00 2001 From: hrrrrustic Date: Sun, 7 May 2023 00:27:31 +0300 Subject: [PATCH 03/17] Add doc comments --- .../src/System/Collections/Generic/Stack.cs | 8 ++++++++ .../src/System/Collections/Generic/Dictionary.cs | 3 +++ .../src/System/Collections/Generic/HashSet.cs | 8 ++++++++ .../src/System/Collections/Generic/Queue.cs | 7 +++++++ 4 files changed, 26 insertions(+) diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs b/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs index 19e057538304a0..30c2ad70dce6af 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs @@ -56,6 +56,10 @@ public Stack(IEnumerable collection) public int Count => _size; + + /// + /// Gets the total numbers of elements the internal data structure can hold without resizing. + /// public int Capacity => _array.Length; bool ICollection.IsSynchronized => false; @@ -166,6 +170,10 @@ public void TrimExcess() } } + /// + /// Sets the capacity of a object to a specified number of entries. + /// + /// The new capacity. public void TrimExcess(int capacity) { ArgumentOutOfRangeException.ThrowIfNegativeOrZero(capacity); 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 8c2c3504e75320..ad02792c7476e6 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 @@ -208,6 +208,9 @@ public IEqualityComparer Comparer public int Count => _count - _freeCount; + /// + /// Gets the total numbers of elements the internal data structure can hold without resizing. + /// public int Capacity => _count; public KeyCollection Keys => _keys ??= new KeyCollection(this); 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 7bb47c1a701476..471e373b50340b 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 @@ -353,6 +353,9 @@ public bool Remove(T item) /// Gets the number of elements that are contained in the set. public int Count => _count - _freeCount; + /// + /// Gets the total numbers of elements the internal data structure can hold without resizing. + /// public int Capacity => _count; bool ICollection.IsReadOnly => false; @@ -1009,6 +1012,11 @@ private void Resize(int newSize, bool forceNewHashCodes) /// public void TrimExcess() => TrimExcess(Count); + /// + /// Sets the capacity of a object to the specified number of entries, + /// rounded up to a nearby, implementation-specific value. + /// + /// The new capacity. public void TrimExcess(int capacity) { int newSize = HashHelpers.GetPrime(capacity); diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs index ed77bedb0208af..ad9b30d7a3cee4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs @@ -54,6 +54,9 @@ public Queue(IEnumerable collection) public int Count => _size; + /// + /// Gets the total numbers of elements the internal data structure can hold without resizing. + /// public int Capacity => _array.Length; bool ICollection.IsSynchronized => false; @@ -354,6 +357,10 @@ public void TrimExcess() } } + /// + /// Sets the capacity of a object to the specified number of entries. + /// + /// The new capacity. public void TrimExcess(int capacity) { ArgumentOutOfRangeException.ThrowIfNegative(capacity); From 5194c0bc6e3298d237758b5c3b14736da8b486e8 Mon Sep 17 00:00:00 2001 From: hrrrrustic Date: Sun, 7 May 2023 01:21:02 +0300 Subject: [PATCH 04/17] Add some tests --- .../Dictionary/Dictionary.Generic.Tests.cs | 9 ++++++ .../Generic/HashSet/HashSet.Generic.Tests.cs | 29 +++++++++++++++++++ .../Generic/Queue/Queue.Generic.Tests.cs | 29 +++++++++++++++++++ .../Generic/Stack/Stack.Generic.Tests.cs | 29 +++++++++++++++++++ 4 files changed, 96 insertions(+) diff --git a/src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.cs b/src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.cs index fa12ef55d6c540..ed8c1860b1dc9c 100644 --- a/src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.cs +++ b/src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.cs @@ -83,6 +83,15 @@ public void Dictionary_Generic_Constructor_int_IEqualityComparer(int count) Assert.Equal(comparer, dictionary.Comparer); } + [Theory] + [InlineData(1)] + [InlineData(100)] + public void Stack_CreateWithCapacity_EqualsCapacityProperty(int capacity) + { + Dictionary dict = new Dictionary(capacity); + Assert.Equal(capacity, dict.Capacity); + } + #endregion #region ContainsValue diff --git a/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs b/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs index afbcad3c357cf6..016a9ad4ed0751 100644 --- a/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs +++ b/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs @@ -126,6 +126,15 @@ public void HashSet_Generic_Constructor_IEnumerable_IEqualityComparer(Enumerable Assert.True(set.SetEquals(enumerable)); } + [Theory] + [InlineData(1)] + [InlineData(100)] + public void Stack_CreateWithCapacity_EqualsCapacityProperty(int capacity) + { + var hashSet = new HashSet(capacity); + Assert.Equal(capacity, hashSet.Capacity); + } + #endregion #region RemoveWhere @@ -175,6 +184,26 @@ public void HashSet_Generic_RemoveWhere_NullMatchPredicate(int setLength) #region TrimExcess + [Theory] + [InlineData(1, -1)] + [InlineData(2, 1)] + public void HashSet_TrimAccessWithInvalidArg_ThrowOutOfRange(int size, int newCapacity) + { + HashSet hashSet = (HashSet)GenericISetFactory(size); + + AssertExtensions.Throws(() => hashSet.TrimExcess(newCapacity)); + } + + public void HashSet_TrimAccessCurrentCapacity_DoesNothing() + { + var hashSet = new HashSet(10); + var initialCapacity = hashSet.Capacity; + hashSet.TrimExcess(initialCapacity); + var afterTrimCapacity = hashSet.Capacity; + + Assert.Equal(initialCapacity, afterTrimCapacity); + } + [Theory] [MemberData(nameof(ValidCollectionSizes))] public void HashSet_Generic_TrimExcess_OnValidSetThatHasntBeenRemovedFrom(int setLength) diff --git a/src/libraries/System.Collections/tests/Generic/Queue/Queue.Generic.Tests.cs b/src/libraries/System.Collections/tests/Generic/Queue/Queue.Generic.Tests.cs index 3fd069023ca253..0810ead9a984bf 100644 --- a/src/libraries/System.Collections/tests/Generic/Queue/Queue.Generic.Tests.cs +++ b/src/libraries/System.Collections/tests/Generic/Queue/Queue.Generic.Tests.cs @@ -97,6 +97,15 @@ public void Queue_Generic_Constructor_int_Negative_ThrowsArgumentOutOfRangeExcep AssertExtensions.Throws("capacity", () => new Queue(int.MinValue)); } + [Theory] + [InlineData(1)] + [InlineData(100)] + public void Queue_CreateWithCapacity_EqualsCapacityProperty(int capacity) + { + var queue = new Queue(capacity); + Assert.Equal(capacity, queue.Capacity); + } + #endregion #region Dequeue @@ -203,6 +212,26 @@ public void Queue_Generic_Peek_OnEmptyQueue_ThrowsInvalidOperationException() #region TrimExcess + [Theory] + [InlineData(1, -1)] + [InlineData(2, 1)] + public void Queue_TrimAccessWithInvalidArg_ThrowOutOfRange(int size, int newCapacity) + { + Queue queue = GenericQueueFactory(size); + + AssertExtensions.Throws(() => queue.TrimExcess(newCapacity)); + } + + public void Queue_TrimAccessCurrentCapacity_DoesNothing() + { + var queue = new Queue(10); + var initialCapacity = queue.Capacity; + queue.TrimExcess(initialCapacity); + var afterTrimCapacity = queue.Capacity; + + Assert.Equal(initialCapacity, afterTrimCapacity); + } + [Theory] [MemberData(nameof(ValidCollectionSizes))] public void Queue_Generic_TrimExcess_OnValidQueueThatHasntBeenRemovedFrom(int count) diff --git a/src/libraries/System.Collections/tests/Generic/Stack/Stack.Generic.Tests.cs b/src/libraries/System.Collections/tests/Generic/Stack/Stack.Generic.Tests.cs index 4c5c5a49d243e1..9babd0b3beae74 100644 --- a/src/libraries/System.Collections/tests/Generic/Stack/Stack.Generic.Tests.cs +++ b/src/libraries/System.Collections/tests/Generic/Stack/Stack.Generic.Tests.cs @@ -108,6 +108,15 @@ public void Stack_Generic_Constructor_int_Negative_ThrowsArgumentOutOfRangeExcep AssertExtensions.Throws("capacity", () => new Stack(int.MinValue)); } + [Theory] + [InlineData(1)] + [InlineData(100)] + public void Stack_CreateWithCapacity_EqualsCapacityProperty(int capacity) + { + var stack = new Stack(capacity); + Assert.Equal(capacity, stack.Capacity); + } + #endregion #region Pop @@ -167,6 +176,26 @@ public void Stack_Generic_Peek_OnEmptyStack_ThrowsInvalidOperationException() #region TrimExcess + [Theory] + [InlineData(1, -1)] + [InlineData(2, 1)] + public void Stack_TrimAccessWithInvalidArg_ThrowOutOfRange(int size, int newCapacity) + { + Stack stack = GenericStackFactory(size); + + AssertExtensions.Throws(() => stack.TrimExcess(newCapacity)); + } + + public void Stack_TrimAccessCurrentCapacity_DoesNothing() + { + var stack = new Stack(10); + var initialCapacity = stack.Capacity; + stack.TrimExcess(initialCapacity); + var afterTrimCapacity = stack.Capacity; + + Assert.Equal(initialCapacity, afterTrimCapacity); + } + [Theory] [MemberData(nameof(ValidCollectionSizes))] public void Stack_Generic_TrimExcess_OnValidStackThatHasntBeenRemovedFrom(int count) From 66c488b8d22196810174aaf1333033ca8b246730 Mon Sep 17 00:00:00 2001 From: hrrrrustic Date: Sun, 7 May 2023 01:25:41 +0300 Subject: [PATCH 05/17] Update implementation --- .../src/System/Collections/Generic/Stack.cs | 2 +- .../src/System/Collections/Generic/HashSet.cs | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs b/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs index 30c2ad70dce6af..25a98c5ac1d2ec 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs @@ -176,7 +176,7 @@ public void TrimExcess() /// The new capacity. public void TrimExcess(int capacity) { - ArgumentOutOfRangeException.ThrowIfNegativeOrZero(capacity); + ArgumentOutOfRangeException.ThrowIfNegative(capacity); ArgumentOutOfRangeException.ThrowIfLessThan(capacity, _size); if (capacity == _size) 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 471e373b50340b..abffedd141288d 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 @@ -1010,7 +1010,7 @@ private void Resize(int newSize, bool forceNewHashCodes) /// Sets the capacity of a object to the actual number of elements it contains, /// rounded up to a nearby, implementation-specific value. /// - public void TrimExcess() => TrimExcess(Count); + public void TrimExcess() => SetCapacity(Count); /// /// Sets the capacity of a object to the specified number of entries, @@ -1018,6 +1018,16 @@ private void Resize(int newSize, bool forceNewHashCodes) /// /// The new capacity. public void TrimExcess(int capacity) + { + ArgumentOutOfRangeException.ThrowIfNegative(capacity); + ArgumentOutOfRangeException.ThrowIfLessThan(capacity, _size); + + if (capacity == _size) + return; + + SetCapacity(capacity); + } + private void SetCapacity(int capacity) { int newSize = HashHelpers.GetPrime(capacity); Entry[]? oldEntries = _entries; From 99404a47bc670d3901738d3d22142efb82faeb3b Mon Sep 17 00:00:00 2001 From: hrrrrustic Date: Sun, 7 May 2023 01:39:21 +0300 Subject: [PATCH 06/17] Update dict and hashset Capacity --- .../src/System/Collections/Generic/Dictionary.cs | 2 +- .../src/System/Collections/Generic/HashSet.cs | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) 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 ad02792c7476e6..57e7ae04470468 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 @@ -211,7 +211,7 @@ public IEqualityComparer Comparer /// /// Gets the total numbers of elements the internal data structure can hold without resizing. /// - public int Capacity => _count; + public int Capacity => _entries?.Length ?? 0; public KeyCollection Keys => _keys ??= new KeyCollection(this); 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 abffedd141288d..ed456fb9c41b83 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 @@ -356,7 +356,7 @@ public bool Remove(T item) /// /// Gets the total numbers of elements the internal data structure can hold without resizing. /// - public int Capacity => _count; + public int Capacity => _entries?.Length ?? 0; bool ICollection.IsReadOnly => false; @@ -1012,11 +1012,6 @@ private void Resize(int newSize, bool forceNewHashCodes) /// public void TrimExcess() => SetCapacity(Count); - /// - /// Sets the capacity of a object to the specified number of entries, - /// rounded up to a nearby, implementation-specific value. - /// - /// The new capacity. public void TrimExcess(int capacity) { ArgumentOutOfRangeException.ThrowIfNegative(capacity); From 1c1d3c9cab28a6c9ebdc35f0cd6e59835307a2a5 Mon Sep 17 00:00:00 2001 From: hrrrrustic Date: Sun, 7 May 2023 02:20:41 +0300 Subject: [PATCH 07/17] size -> count --- .../src/System/Collections/Generic/HashSet.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 ed456fb9c41b83..7d0cda6a6a0bdc 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 @@ -1015,9 +1015,9 @@ private void Resize(int newSize, bool forceNewHashCodes) public void TrimExcess(int capacity) { ArgumentOutOfRangeException.ThrowIfNegative(capacity); - ArgumentOutOfRangeException.ThrowIfLessThan(capacity, _size); + ArgumentOutOfRangeException.ThrowIfLessThan(capacity, _count); - if (capacity == _size) + if (capacity == _count) return; SetCapacity(capacity); From c1f68373ac53a8296c100dc934bbf841bf1c1235 Mon Sep 17 00:00:00 2001 From: hrrrrustic Date: Sun, 7 May 2023 03:15:23 +0300 Subject: [PATCH 08/17] Fix test names --- .../tests/Generic/Dictionary/Dictionary.Generic.Tests.cs | 2 +- .../tests/Generic/HashSet/HashSet.Generic.Tests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.cs b/src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.cs index ed8c1860b1dc9c..17cdaeb84c4555 100644 --- a/src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.cs +++ b/src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.cs @@ -86,7 +86,7 @@ public void Dictionary_Generic_Constructor_int_IEqualityComparer(int count) [Theory] [InlineData(1)] [InlineData(100)] - public void Stack_CreateWithCapacity_EqualsCapacityProperty(int capacity) + public void Dictionary_CreateWithCapacity_EqualsCapacityProperty(int capacity) { Dictionary dict = new Dictionary(capacity); Assert.Equal(capacity, dict.Capacity); diff --git a/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs b/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs index 016a9ad4ed0751..1f7611e477985c 100644 --- a/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs +++ b/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs @@ -129,7 +129,7 @@ public void HashSet_Generic_Constructor_IEnumerable_IEqualityComparer(Enumerable [Theory] [InlineData(1)] [InlineData(100)] - public void Stack_CreateWithCapacity_EqualsCapacityProperty(int capacity) + public void HashSet_CreateWithCapacity_EqualsCapacityProperty(int capacity) { var hashSet = new HashSet(capacity); Assert.Equal(capacity, hashSet.Capacity); From fd3eacd4e9f9c1751e7af6b776c93406a6925398 Mon Sep 17 00:00:00 2001 From: hrrrrustic Date: Mon, 31 Jul 2023 20:25:47 +0300 Subject: [PATCH 09/17] Update implementation --- .../src/System/Collections/Generic/Stack.cs | 5 +++-- .../src/System/Collections/Generic/Dictionary.cs | 1 + .../src/System/Collections/Generic/HashSet.cs | 12 +++++++++--- .../src/System/Collections/Generic/Queue.cs | 5 +++-- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs b/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs index 25a98c5ac1d2ec..63d37ba0b186c4 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs @@ -174,12 +174,13 @@ public void TrimExcess() /// Sets the capacity of a object to a specified number of entries. /// /// The new capacity. + /// Passed capacity is lower than 0 or entries count. public void TrimExcess(int capacity) { ArgumentOutOfRangeException.ThrowIfNegative(capacity); - ArgumentOutOfRangeException.ThrowIfLessThan(capacity, _size); + ArgumentOutOfRangeException.ThrowIfLessThan(capacity, _array.Length); - if (capacity == _size) + if (capacity == _array.Length) return; Array.Resize(ref _array, capacity); 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 57e7ae04470468..6007efe778ce21 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 @@ -1185,6 +1185,7 @@ public int EnsureCapacity(int capacity) /// This method can be used to minimize the memory overhead /// once it is known that no new elements will be added. /// + /// Passed capacity is lower than entries count. public void TrimExcess(int capacity) { if (capacity < Count) 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 7d0cda6a6a0bdc..e8d974423d2217 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 @@ -1012,16 +1012,22 @@ private void Resize(int newSize, bool forceNewHashCodes) /// public void TrimExcess() => SetCapacity(Count); + /// + /// Sets the capacity of a object to the specified number of entries. + /// + /// The new capacity. + /// Passed capacity is lower than entries count. public void TrimExcess(int capacity) { - ArgumentOutOfRangeException.ThrowIfNegative(capacity); - ArgumentOutOfRangeException.ThrowIfLessThan(capacity, _count); + var currentCount = Count; + ArgumentOutOfRangeException.ThrowIfLessThan(capacity, currentCount); - if (capacity == _count) + if (capacity == currentCount) return; SetCapacity(capacity); } + private void SetCapacity(int capacity) { int newSize = HashHelpers.GetPrime(capacity); diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs index ad9b30d7a3cee4..144ad3af777b2d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs @@ -361,12 +361,13 @@ public void TrimExcess() /// Sets the capacity of a object to the specified number of entries. /// /// The new capacity. + /// Passed capacity is lower than entries count. public void TrimExcess(int capacity) { ArgumentOutOfRangeException.ThrowIfNegative(capacity); - ArgumentOutOfRangeException.ThrowIfLessThan(capacity, _size); + ArgumentOutOfRangeException.ThrowIfLessThan(capacity, _array.Length); - if (capacity == _size) + if (capacity == _array.Length) return; SetCapacity(capacity); From 85a2ecc4fb74ecf0efacb68d555bb34901eb28c7 Mon Sep 17 00:00:00 2001 From: hrrrrustic Date: Mon, 31 Jul 2023 23:15:20 +0300 Subject: [PATCH 10/17] Update tests --- .../Dictionary/Dictionary.Generic.Tests.cs | 23 +++++++++++- .../Generic/HashSet/HashSet.Generic.Tests.cs | 37 ++++++++++++++----- .../Generic/Queue/Queue.Generic.Tests.cs | 28 ++++++++++---- .../Generic/Stack/Stack.Generic.Tests.cs | 24 +++++++++--- 4 files changed, 88 insertions(+), 24 deletions(-) diff --git a/src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.cs b/src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.cs index 17cdaeb84c4555..aa6133538895d4 100644 --- a/src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.cs +++ b/src/libraries/System.Collections/tests/Generic/Dictionary/Dictionary.Generic.Tests.cs @@ -86,14 +86,33 @@ public void Dictionary_Generic_Constructor_int_IEqualityComparer(int count) [Theory] [InlineData(1)] [InlineData(100)] - public void Dictionary_CreateWithCapacity_EqualsCapacityProperty(int capacity) + public void Dictionary_CreateWithCapacity_CapacityAtLeastPassedValue(int capacity) { Dictionary dict = new Dictionary(capacity); - Assert.Equal(capacity, dict.Capacity); + Assert.True(capacity <= dict.Capacity); } #endregion + #region Properties + + public void DictResized_CapacityChanged() + { + var dict = (Dictionary)GenericIDictionaryFactory(1); + int initialCapacity = dict.Capacity; + + int seed = 85877; + for (int i = 0; i < dict.Capacity; i++) + { + dict.Add(CreateTKey(seed++), CreateTValue(seed++)); + } + + int afterCapacity = dict.Capacity; + + Assert.True(afterCapacity > initialCapacity); + } + + #endregion #region ContainsValue [Theory] diff --git a/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs b/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs index 1f7611e477985c..19b2e3f000bba2 100644 --- a/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs +++ b/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs @@ -129,10 +129,31 @@ public void HashSet_Generic_Constructor_IEnumerable_IEqualityComparer(Enumerable [Theory] [InlineData(1)] [InlineData(100)] - public void HashSet_CreateWithCapacity_EqualsCapacityProperty(int capacity) + public void HashSet_CreateWithCapacity_CapacityAtLeastPassedValue(int capacity) { var hashSet = new HashSet(capacity); - Assert.Equal(capacity, hashSet.Capacity); + Assert.True(capacity <= hashSet.Capacity); + } + + #endregion + + #region Properties + + [Fact] + public void HashSetResized_CapacityChanged() + { + var hashSet = (HashSet)GenericISetFactory(10); + int initialCapacity = hashSet.Capacity; + + int seed = 85877; + for (int i = 0; i < hashSet.Capacity; i++) + { + hashSet.Add(CreateT(seed++)); + } + + int afterCapacity = hashSet.Capacity; + + Assert.True(afterCapacity > initialCapacity); } #endregion @@ -194,14 +215,12 @@ public void HashSet_TrimAccessWithInvalidArg_ThrowOutOfRange(int size, int newCa AssertExtensions.Throws(() => hashSet.TrimExcess(newCapacity)); } - public void HashSet_TrimAccessCurrentCapacity_DoesNothing() + [Fact] + public void TrimExcess_Generic_LargeInitialCapacity_TrimReducesSize() { - var hashSet = new HashSet(10); - var initialCapacity = hashSet.Capacity; - hashSet.TrimExcess(initialCapacity); - var afterTrimCapacity = hashSet.Capacity; - - Assert.Equal(initialCapacity, afterTrimCapacity); + var dictionary = new HashSet(20); + dictionary.TrimExcess(7); + Assert.Equal(7, dictionary.EnsureCapacity(0)); } [Theory] diff --git a/src/libraries/System.Collections/tests/Generic/Queue/Queue.Generic.Tests.cs b/src/libraries/System.Collections/tests/Generic/Queue/Queue.Generic.Tests.cs index 0810ead9a984bf..dc857cb5867eac 100644 --- a/src/libraries/System.Collections/tests/Generic/Queue/Queue.Generic.Tests.cs +++ b/src/libraries/System.Collections/tests/Generic/Queue/Queue.Generic.Tests.cs @@ -222,14 +222,16 @@ public void Queue_TrimAccessWithInvalidArg_ThrowOutOfRange(int size, int newCapa AssertExtensions.Throws(() => queue.TrimExcess(newCapacity)); } - public void Queue_TrimAccessCurrentCapacity_DoesNothing() + [Fact] + public void Queue_TrimAccessCurrentCount_DoesNothing() { - var queue = new Queue(10); - var initialCapacity = queue.Capacity; - queue.TrimExcess(initialCapacity); - var afterTrimCapacity = queue.Capacity; - - Assert.Equal(initialCapacity, afterTrimCapacity); + var queue = new Queue(); + queue.Enqueue(CreateT(85877)); + queue.TrimExcess(queue.Count); + int capacity = queue.Capacity; + queue.TrimExcess(queue.Count); + int capacityAgain = queue.Capacity; + Assert.Equal(capacity, capacityAgain); } [Theory] @@ -495,5 +497,17 @@ public void Queue_Generic_EnsureCapacity_RequestingLargerCapacity_DoesNotImpactQ Assert.Equal(copiedList[i], queue.Dequeue()); } } + + [Fact] + public void QueueResized_CapacityUpdates() + { + var queue = GenericQueueFactory(1); + + int initialCapacity = queue.Capacity; + + queue.Enqueue(CreateT(85877)); + + Assert.True(initialCapacity < queue.Capacity); + } } } diff --git a/src/libraries/System.Collections/tests/Generic/Stack/Stack.Generic.Tests.cs b/src/libraries/System.Collections/tests/Generic/Stack/Stack.Generic.Tests.cs index 9babd0b3beae74..a3e04713f1d6aa 100644 --- a/src/libraries/System.Collections/tests/Generic/Stack/Stack.Generic.Tests.cs +++ b/src/libraries/System.Collections/tests/Generic/Stack/Stack.Generic.Tests.cs @@ -186,14 +186,15 @@ public void Stack_TrimAccessWithInvalidArg_ThrowOutOfRange(int size, int newCapa AssertExtensions.Throws(() => stack.TrimExcess(newCapacity)); } - public void Stack_TrimAccessCurrentCapacity_DoesNothing() + [Fact] + public void Stack_TrimAccessCurrentCount_DoesNothing() { - var stack = new Stack(10); - var initialCapacity = stack.Capacity; - stack.TrimExcess(initialCapacity); - var afterTrimCapacity = stack.Capacity; + var stack = GenericStackFactory(10); + stack.TrimExcess(stack.Count); + int capacity = stack.Capacity; + stack.TrimExcess(stack.Count); - Assert.Equal(initialCapacity, afterTrimCapacity); + Assert.Equal(capacity, stack.Capacity); } [Theory] @@ -424,5 +425,16 @@ public void Stack_Generic_EnsureCapacity_RequestingLargerCapacity_DoesNotImpactS Assert.Equal(copiedList[i], stack.Pop()); } } + + [Fact] + public void StackResized_CapacityUpdates() + { + Stack stack = GenericStackFactory(10); + int initialCapacity = stack.Capacity; + + stack.Push(CreateT(85877)); + + Assert.True(initialCapacity < stack.Capacity); + } } } From c81d144b64e5c7181805402e1d290264efb2390c Mon Sep 17 00:00:00 2001 From: hrrrrustic Date: Fri, 4 Aug 2023 01:18:28 +0300 Subject: [PATCH 11/17] Remove loop to try avoid oom --- .../tests/Generic/HashSet/HashSet.Generic.Tests.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs b/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs index 19b2e3f000bba2..d3be892a88bd96 100644 --- a/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs +++ b/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs @@ -142,14 +142,11 @@ public void HashSet_CreateWithCapacity_CapacityAtLeastPassedValue(int capacity) [Fact] public void HashSetResized_CapacityChanged() { - var hashSet = (HashSet)GenericISetFactory(10); + var hashSet = (HashSet)GenericISetFactory(3); int initialCapacity = hashSet.Capacity; int seed = 85877; - for (int i = 0; i < hashSet.Capacity; i++) - { - hashSet.Add(CreateT(seed++)); - } + hashSet.Add(CreateT(seed++)); int afterCapacity = hashSet.Capacity; From aa3ed0690bd1b8127d2446950bf5ad406c232554 Mon Sep 17 00:00:00 2001 From: hrrrrustic Date: Fri, 4 Aug 2023 22:29:32 +0300 Subject: [PATCH 12/17] stack & queue update --- .../System.Collections/src/System/Collections/Generic/Stack.cs | 2 +- .../src/System/Collections/Generic/Queue.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs b/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs index 63d37ba0b186c4..10f1b58c4fa149 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs @@ -178,7 +178,7 @@ public void TrimExcess() public void TrimExcess(int capacity) { ArgumentOutOfRangeException.ThrowIfNegative(capacity); - ArgumentOutOfRangeException.ThrowIfLessThan(capacity, _array.Length); + ArgumentOutOfRangeException.ThrowIfLessThan(capacity, _size); if (capacity == _array.Length) return; diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs index 144ad3af777b2d..8433cda6896401 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs @@ -365,7 +365,7 @@ public void TrimExcess() public void TrimExcess(int capacity) { ArgumentOutOfRangeException.ThrowIfNegative(capacity); - ArgumentOutOfRangeException.ThrowIfLessThan(capacity, _array.Length); + ArgumentOutOfRangeException.ThrowIfLessThan(capacity, _size); if (capacity == _array.Length) return; From 03111906e9e266a420550727f26243e8677e137a Mon Sep 17 00:00:00 2001 From: hrrrrustic Date: Sun, 24 Sep 2023 23:03:03 +0300 Subject: [PATCH 13/17] Fix hashset --- .../src/System/Collections/Generic/HashSet.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) 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 e8d974423d2217..d49c0467c5e88c 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 @@ -1013,17 +1013,14 @@ private void Resize(int newSize, bool forceNewHashCodes) public void TrimExcess() => SetCapacity(Count); /// - /// Sets the capacity of a object to the specified number of entries. + /// Sets the capacity of a object to the specified number of entries, + /// rounded up to a nearby, implementation-specific value. /// /// The new capacity. /// Passed capacity is lower than entries count. public void TrimExcess(int capacity) { - var currentCount = Count; - ArgumentOutOfRangeException.ThrowIfLessThan(capacity, currentCount); - - if (capacity == currentCount) - return; + ArgumentOutOfRangeException.ThrowIfLessThan(capacity, Count); SetCapacity(capacity); } From 6e055cdad0a2745da0224a4f0d4faa2426f74061 Mon Sep 17 00:00:00 2001 From: hrrrrustic Date: Sun, 24 Sep 2023 23:09:21 +0300 Subject: [PATCH 14/17] inherit doc --- .../System.Collections/src/System/Collections/Generic/Stack.cs | 1 + .../src/System/Collections/Generic/Queue.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs b/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs index 10f1b58c4fa149..ccc83e9d6504f2 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs @@ -62,6 +62,7 @@ public Stack(IEnumerable collection) /// public int Capacity => _array.Length; + /// bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs index 8433cda6896401..fe8f1138d1c337 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs @@ -59,6 +59,7 @@ public Queue(IEnumerable collection) /// public int Capacity => _array.Length; + /// bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; From 534c2f446fe4484277a919140fdee7da72cde600 Mon Sep 17 00:00:00 2001 From: hrrrrustic Date: Sun, 24 Sep 2023 23:37:51 +0300 Subject: [PATCH 15/17] update inherit docs --- .../System.Collections/src/System/Collections/Generic/Stack.cs | 2 +- .../src/System/Collections/Generic/Queue.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs b/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs index ccc83e9d6504f2..1317ed240c06a3 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/Stack.cs @@ -62,7 +62,7 @@ public Stack(IEnumerable collection) /// public int Capacity => _array.Length; - /// + /// bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs index fe8f1138d1c337..4a7efdf06b54da 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs @@ -59,7 +59,7 @@ public Queue(IEnumerable collection) /// public int Capacity => _array.Length; - /// + /// bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; From a66770dcf3dbac055a4dac4b111d5c4c5c3271bc Mon Sep 17 00:00:00 2001 From: hrrrrustic Date: Mon, 25 Sep 2023 00:03:47 +0300 Subject: [PATCH 16/17] update tests --- .../tests/Generic/HashSet/HashSet.Generic.Tests.cs | 6 +++--- .../tests/Generic/Queue/Queue.Generic.Tests.cs | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs b/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs index d3be892a88bd96..038bbbdb960c3f 100644 --- a/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs +++ b/src/libraries/System.Collections/tests/Generic/HashSet/HashSet.Generic.Tests.cs @@ -215,9 +215,9 @@ public void HashSet_TrimAccessWithInvalidArg_ThrowOutOfRange(int size, int newCa [Fact] public void TrimExcess_Generic_LargeInitialCapacity_TrimReducesSize() { - var dictionary = new HashSet(20); - dictionary.TrimExcess(7); - Assert.Equal(7, dictionary.EnsureCapacity(0)); + var set = new HashSet(20); + set.TrimExcess(7); + Assert.Equal(7, set.Capacity); } [Theory] diff --git a/src/libraries/System.Collections/tests/Generic/Queue/Queue.Generic.Tests.cs b/src/libraries/System.Collections/tests/Generic/Queue/Queue.Generic.Tests.cs index dc857cb5867eac..a2ce3d94f9c665 100644 --- a/src/libraries/System.Collections/tests/Generic/Queue/Queue.Generic.Tests.cs +++ b/src/libraries/System.Collections/tests/Generic/Queue/Queue.Generic.Tests.cs @@ -225,8 +225,7 @@ public void Queue_TrimAccessWithInvalidArg_ThrowOutOfRange(int size, int newCapa [Fact] public void Queue_TrimAccessCurrentCount_DoesNothing() { - var queue = new Queue(); - queue.Enqueue(CreateT(85877)); + var queue = GenericQueueFactory(100); queue.TrimExcess(queue.Count); int capacity = queue.Capacity; queue.TrimExcess(queue.Count); From 12467769cda68dcd0f6cbc49829984b0a033328e Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Wed, 22 Nov 2023 10:58:38 +0000 Subject: [PATCH 17/17] Address remaining feedback --- .../Generic/Queue/Queue.Generic.Tests.cs | 21 ++++++++++++------- .../src/System/Collections/Generic/HashSet.cs | 1 + .../src/System/Collections/Generic/Queue.cs | 1 + 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/libraries/System.Collections/tests/Generic/Queue/Queue.Generic.Tests.cs b/src/libraries/System.Collections/tests/Generic/Queue/Queue.Generic.Tests.cs index a2ce3d94f9c665..7c900d4c6ef325 100644 --- a/src/libraries/System.Collections/tests/Generic/Queue/Queue.Generic.Tests.cs +++ b/src/libraries/System.Collections/tests/Generic/Queue/Queue.Generic.Tests.cs @@ -21,9 +21,9 @@ protected Queue GenericQueueFactory() return new Queue(); } - protected Queue GenericQueueFactory(int count) + protected Queue GenericQueueFactory(int count, int? capacity = null) { - Queue queue = new Queue(count); + Queue queue = new Queue(capacity ?? count); int seed = count * 34; for (int i = 0; i < count; i++) queue.Enqueue(CreateT(seed++)); @@ -223,14 +223,21 @@ public void Queue_TrimAccessWithInvalidArg_ThrowOutOfRange(int size, int newCapa } [Fact] - public void Queue_TrimAccessCurrentCount_DoesNothing() + public void Queue_TrimAccessCurrentCount_ReducesToCount() { - var queue = GenericQueueFactory(100); + var queue = GenericQueueFactory(20, capacity: 30); + Assert.Equal(30, queue.Capacity); + Assert.Equal(20, queue.Count); + queue.TrimExcess(queue.Count); - int capacity = queue.Capacity; + + Assert.Equal(20, queue.Capacity); + Assert.Equal(20, queue.Count); + queue.TrimExcess(queue.Count); - int capacityAgain = queue.Capacity; - Assert.Equal(capacity, capacityAgain); + + Assert.Equal(20, queue.Capacity); + Assert.Equal(20, queue.Count); } [Theory] 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 d49c0467c5e88c..460e6a8940d6a9 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 @@ -1027,6 +1027,7 @@ public void TrimExcess(int capacity) private void SetCapacity(int capacity) { + Debug.Assert(capacity >= Count); int newSize = HashHelpers.GetPrime(capacity); Entry[]? oldEntries = _entries; int currentCapacity = oldEntries == null ? 0 : oldEntries.Length; diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs index 4a7efdf06b54da..58afecf920c442 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs @@ -309,6 +309,7 @@ public T[] ToArray() // must be >= _size. private void SetCapacity(int capacity) { + Debug.Assert(capacity >= _size); T[] newarray = new T[capacity]; if (_size > 0) {