From 11fd6e3dd0e1bf47e7918c977e5563b4268b2a37 Mon Sep 17 00:00:00 2001 From: mlemanczyk Date: Sat, 1 Jul 2023 12:53:37 +0200 Subject: [PATCH] RecyclableList.Helpers renamed to RecyclableListHelpers and made top-level class for better performance. --- .../RecyclableList.Helpers.cs | 424 +++++++++--------- Recyclable.Collections/RecyclableList.cs | 29 +- Recyclable.Collections/RecyclableQueue.cs | 14 +- .../RecyclableSortedList.cs | 2 +- .../RecyclableListTests.cs | 2 +- .../RecyclableLongListTests.cs | 2 +- 6 files changed, 235 insertions(+), 238 deletions(-) diff --git a/Recyclable.Collections/RecyclableList.Helpers.cs b/Recyclable.Collections/RecyclableList.Helpers.cs index e48f018..d5926cd 100644 --- a/Recyclable.Collections/RecyclableList.Helpers.cs +++ b/Recyclable.Collections/RecyclableList.Helpers.cs @@ -3,271 +3,269 @@ using System.Runtime.CompilerServices; namespace Recyclable.Collections { - public partial class RecyclableList + internal static class RecyclableListHelpers { - internal static class Helpers + [Obsolete("This method MAY be removed in the near future.")] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool Contains(RecyclableList arrays, T item) => arrays.Any(x => x.Contains(item)); + + [Obsolete("This method MAY be removed in the near future.")] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void CopyTo(RecyclableList arrays, long startingIndex, int blockSize, int lastBlockSize, T[] destinationArray, int destinationArrayIndex) { - [Obsolete("This method MAY be removed in the near future.")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Contains(RecyclableList arrays, T item) => arrays.Any(x => x.Contains(item)); - - [Obsolete("This method MAY be removed in the near future.")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CopyTo(RecyclableList arrays, long startingIndex, int blockSize, int lastBlockSize, T[] destinationArray, int destinationArrayIndex) + Span arrayMemory = destinationArray.AsSpan(); + arrayMemory = arrayMemory[destinationArrayIndex..]; + int startingArrayIndex = (int)(startingIndex / blockSize); + startingIndex %= blockSize; + if (arrays.Count > 0) { - Span arrayMemory = destinationArray.AsSpan(); - arrayMemory = arrayMemory[destinationArrayIndex..]; - int startingArrayIndex = (int)(startingIndex / blockSize); - startingIndex %= blockSize; - if (arrays.Count > 0) + ReadOnlySpan sourceMemory = arrays[0].AsSpan(); + var maxToCopy = (int)Math.Min(blockSize - startingIndex, arrayMemory.Length); + if (arrays.Count == 1) { - ReadOnlySpan sourceMemory = arrays[0].AsSpan(); - var maxToCopy = (int)Math.Min(blockSize - startingIndex, arrayMemory.Length); - if (arrays.Count == 1) - { - maxToCopy = Math.Min(maxToCopy, lastBlockSize); - } - - sourceMemory = sourceMemory[(int)startingIndex..maxToCopy]; - sourceMemory.CopyTo(arrayMemory); - arrayMemory = arrayMemory[maxToCopy..]; + maxToCopy = Math.Min(maxToCopy, lastBlockSize); } - for (var arrayIdx = startingArrayIndex + 1; arrayIdx < arrays.Count - 1 && arrayMemory.Length > 0; arrayIdx++) - { - ReadOnlySpan sourceMemory = arrays[arrayIdx].AsSpan(); - var maxToCopy = Math.Min(blockSize, arrayMemory.Length); - sourceMemory = sourceMemory[..maxToCopy]; - sourceMemory.CopyTo(arrayMemory); - arrayMemory = arrayMemory[maxToCopy..]; - } - - if (arrays.Count > 1 && arrayMemory.Length > 0) - { - ReadOnlySpan sourceMemory = arrays[^1].AsSpan(); - var maxToCopy = Math.Min(lastBlockSize, arrayMemory.Length); - sourceMemory = sourceMemory[..maxToCopy]; - sourceMemory.CopyTo(arrayMemory); - } + sourceMemory = sourceMemory[(int)startingIndex..maxToCopy]; + sourceMemory.CopyTo(arrayMemory); + arrayMemory = arrayMemory[maxToCopy..]; } - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - public static int EnsureCapacity(RecyclableList list, int requestedCapacity) + for (var arrayIdx = startingArrayIndex + 1; arrayIdx < arrays.Count - 1 && arrayMemory.Length > 0; arrayIdx++) { - int newCapacity; - switch (list._capacity > 0) + ReadOnlySpan sourceMemory = arrays[arrayIdx].AsSpan(); + var maxToCopy = Math.Min(blockSize, arrayMemory.Length); + sourceMemory = sourceMemory[..maxToCopy]; + sourceMemory.CopyTo(arrayMemory); + arrayMemory = arrayMemory[maxToCopy..]; + } + + if (arrays.Count > 1 && arrayMemory.Length > 0) + { + ReadOnlySpan sourceMemory = arrays[^1].AsSpan(); + var maxToCopy = Math.Min(lastBlockSize, arrayMemory.Length); + sourceMemory = sourceMemory[..maxToCopy]; + sourceMemory.CopyTo(arrayMemory); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static int EnsureCapacity(RecyclableList list, int requestedCapacity) + { + int newCapacity; + switch (list._capacity > 0) + { + case true: + newCapacity = list._capacity; + while (newCapacity < requestedCapacity) + { + newCapacity <<= 1; + } + + break; + + case false: + newCapacity = requestedCapacity; + break; + } + + list._memoryBlock = Resize(list._memoryBlock, newCapacity); + newCapacity = list._memoryBlock.Length; + list._capacity = newCapacity; + return newCapacity; + } + + + [Obsolete("This method WILL be removed in the near future. Please use the existing enumerators instead of it.")] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static IEnumerable Enumerate(RecyclableList arrays, int chunkSize, long totalCount) + { + long currentCount = 0; + for (var arrayIdx = 0; (arrayIdx < arrays.Count) && (currentCount < totalCount); arrayIdx++) + { + var array = arrays[arrayIdx]; + currentCount += Math.Min(chunkSize, totalCount); + switch (currentCount < totalCount) { case true: - newCapacity = list._capacity; - while (newCapacity < requestedCapacity) + for (var valueIdx = 0; valueIdx < chunkSize; valueIdx++) { - newCapacity <<= 1; + yield return array[valueIdx]; } break; case false: - newCapacity = requestedCapacity; + var partialCount = (int)(totalCount % chunkSize); + int maxCount = partialCount > 0 ? partialCount : chunkSize; + for (var valueIdx = 0; valueIdx < maxCount; valueIdx++) + { + yield return array[valueIdx]; + } + break; } - - list._memoryBlock = Resize(list._memoryBlock, newCapacity); - newCapacity = list._memoryBlock.Length; - list._capacity = newCapacity; - return newCapacity; } + } - [Obsolete("This method WILL be removed in the near future. Please use the existing enumerators instead of it.")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static IEnumerable Enumerate(RecyclableList arrays, int chunkSize, long totalCount) + public static void InsertionSort(IList values, int startIndex, int endIndex, IComparer comparer) + { + var left = startIndex; + while (left < endIndex) { - long currentCount = 0; - for (var arrayIdx = 0; (arrayIdx < arrays.Count) && (currentCount < totalCount); arrayIdx++) + int right = left; + T? temp = values[++left]; + while (right >= startIndex && 0 < comparer.Compare(values[right], temp)) { - var array = arrays[arrayIdx]; - currentCount += Math.Min(chunkSize, totalCount); - switch (currentCount < totalCount) + values[right + 1] = values[right--]; + } + + values[right + 1] = temp; + } + } + + public static void InsertionSort(IList values, IComparer comparer) + { + InsertionSort(values, 0, values.Count - 1, comparer); + } + + public static void InsertionSort(IList values) + { + InsertionSort(values, Comparer.Default); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long LongIndexOf(RecyclableList arrays, int blockSize, T item, IEqualityComparer comparer) + { + for (var arrayIdx = 0; arrayIdx < arrays.Count; arrayIdx++) + { + var array = arrays[arrayIdx]; + Span arrayMemory = array.AsSpan(); + for (int memoryIdx = 0; memoryIdx < arrayMemory.Length; memoryIdx++) + { + if (comparer.Equals(arrayMemory[memoryIdx], item)) { - case true: - for (var valueIdx = 0; valueIdx < chunkSize; valueIdx++) - { - yield return array[valueIdx]; - } - - break; - - case false: - var partialCount = (int)(totalCount % chunkSize); - int maxCount = partialCount > 0 ? partialCount : chunkSize; - for (var valueIdx = 0; valueIdx < maxCount; valueIdx++) - { - yield return array[valueIdx]; - } - - break; + return (arrayIdx * (long)blockSize) + memoryIdx; } } } - public static void InsertionSort(IList values, int startIndex, int endIndex, IComparer comparer) + return -1; + } + + // The source code was taken from https://codereview.stackexchange.com/questions/205407/quicksort-without-recursion. + // It was only beautified for .Net 6.0+. + public static void QuickSort(IList values, int startIndex, int endIndex, IComparer comparer, IRandomNumberGenerator randomNumberGenerator) + { + var range = (startIndex, endIndex); + var stack = new Stack<(int, int)>(); + + do { + startIndex = range.startIndex; + endIndex = range.endIndex; + + if (endIndex - startIndex + 1 < 31) + { + InsertionSort(values, startIndex, endIndex, comparer); + + continue; + } + + var pivot = SampleMedian(values, startIndex, endIndex, comparer, randomNumberGenerator); var left = startIndex; - while (left < endIndex) + var right = endIndex; + + while (left <= right) { - int right = left; - T? temp = values[++left]; - while (right >= startIndex && 0 < comparer.Compare(values[right], temp)) + while (0 > comparer.Compare(values[left], pivot)) { - values[right + 1] = values[right--]; + left++; } - values[right + 1] = temp; + while (0 > comparer.Compare(pivot, values[right])) + { + right--; + } + + if (left <= right) + { + Swap(values, left++, right--); + } + } + + if (startIndex < right) + { + stack.Push((startIndex, right)); + } + + if (left < endIndex) + { + stack.Push((left, endIndex)); } } + while (stack.TryPop(out range)); + } + public static void QuickSort(IList values, IComparer comparer, IRandomNumberGenerator randomNumberGenerator) + => QuickSort(values, 0, values.Count - 1, comparer, randomNumberGenerator); - public static void InsertionSort(IList values, IComparer comparer) + public static void QuickSort(IList values) + => QuickSort(values, Comparer.Default, new SystemRandomNumberGenerator()); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static T SampleMedian(IList values, int startIndex, int endIndex, IComparer comparer, IRandomNumberGenerator randomNumberGenerator) + { + var left = randomNumberGenerator.NextInt32(startIndex, endIndex); + var middle = randomNumberGenerator.NextInt32(startIndex, endIndex); + var right = randomNumberGenerator.NextInt32(startIndex, endIndex); + + if (0 > comparer.Compare(values[right], values[left])) { - InsertionSort(values, 0, values.Count - 1, comparer); + Swap(values, right, left); } - public static void InsertionSort(IList values) + if (0 > comparer.Compare(values[middle], values[left])) { - InsertionSort(values, Comparer.Default); + Swap(values, middle, left); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long LongIndexOf(RecyclableList arrays, int blockSize, T item, IEqualityComparer comparer) + if (0 > comparer.Compare(values[right], values[middle])) { - for (var arrayIdx = 0; arrayIdx < arrays.Count; arrayIdx++) - { - var array = arrays[arrayIdx]; - Span arrayMemory = array.AsSpan(); - for (int memoryIdx = 0; memoryIdx < arrayMemory.Length; memoryIdx++) - { - if (comparer.Equals(arrayMemory[memoryIdx], item)) - { - return (arrayIdx * (long)blockSize) + memoryIdx; - } - } - } - - return -1; + Swap(values, right, middle); } - // The source code was taken from https://codereview.stackexchange.com/questions/205407/quicksort-without-recursion. - // It was only beautified for .Net 6.0+. - public static void QuickSort(IList values, int startIndex, int endIndex, IComparer comparer, IRandomNumberGenerator randomNumberGenerator) + return values[middle]; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static T[] Resize(in T[]? source, int newSize) + { + ArrayPool arrayPool = _arrayPool; + T[] newMemoryBlock = newSize >= RecyclableDefaults.MinPooledArrayLength + ? arrayPool.Rent(newSize) + : new T[newSize]; + + if (source?.Length > 0) { - var range = (startIndex, endIndex); - var stack = new Stack<(int, int)>(); - - do + Array.Copy(source!, 0, newMemoryBlock, 0, source!.Length); + if (source!.Length >= RecyclableDefaults.MinPooledArrayLength) { - startIndex = range.startIndex; - endIndex = range.endIndex; + // TODO: Measure gain vs relying on arrayPool to clear + //if (NeedsClearing) + //{ + // Array.Clear(source); + //} - if (endIndex - startIndex + 1 < 31) - { - InsertionSort(values, startIndex, endIndex, comparer); - - continue; - } - - var pivot = SampleMedian(values, startIndex, endIndex, comparer, randomNumberGenerator); - var left = startIndex; - var right = endIndex; - - while (left <= right) - { - while (0 > comparer.Compare(values[left], pivot)) - { - left++; - } - - while (0 > comparer.Compare(pivot, values[right])) - { - right--; - } - - if (left <= right) - { - Swap(values, left++, right--); - } - } - - if (startIndex < right) - { - stack.Push((startIndex, right)); - } - - if (left < endIndex) - { - stack.Push((left, endIndex)); - } - } - while (stack.TryPop(out range)); - } - public static void QuickSort(IList values, IComparer comparer, IRandomNumberGenerator randomNumberGenerator) - => QuickSort(values, 0, values.Count - 1, comparer, randomNumberGenerator); - - public static void QuickSort(IList values) - => QuickSort(values, Comparer.Default, new SystemRandomNumberGenerator()); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static T SampleMedian(IList values, int startIndex, int endIndex, IComparer comparer, IRandomNumberGenerator randomNumberGenerator) - { - var left = randomNumberGenerator.NextInt32(startIndex, endIndex); - var middle = randomNumberGenerator.NextInt32(startIndex, endIndex); - var right = randomNumberGenerator.NextInt32(startIndex, endIndex); - - if (0 > comparer.Compare(values[right], values[left])) - { - Swap(values, right, left); - } - - if (0 > comparer.Compare(values[middle], values[left])) - { - Swap(values, middle, left); - } - - if (0 > comparer.Compare(values[right], values[middle])) - { - Swap(values, right, middle); - } - - return values[middle]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - public static T[] Resize(in T[]? source, int newSize) - { - ArrayPool arrayPool = _arrayPool; - T[] newMemoryBlock = newSize >= RecyclableDefaults.MinPooledArrayLength - ? arrayPool.Rent(newSize) - : new T[newSize]; - - if (source?.Length > 0) - { - Array.Copy(source!, 0, newMemoryBlock, 0, source!.Length); - if (source!.Length >= RecyclableDefaults.MinPooledArrayLength) - { - // TODO: Measure gain vs relying on arrayPool to clear - //if (NeedsClearing) - //{ - // Array.Clear(source); - //} - - // If anything, it has been already cleared above, so we don't need to repeat it. - arrayPool.Return(source, NeedsClearing); - } + // If anything, it has been already cleared above, so we don't need to repeat it. + arrayPool.Return(source, NeedsClearing); } + } return newMemoryBlock; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void Swap(IList values, int xIndex, int yIndex) - => (values[yIndex], values[xIndex]) = (values[xIndex], values[yIndex]); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void Swap(IList values, int xIndex, int yIndex) + => (values[yIndex], values[xIndex]) = (values[xIndex], values[yIndex]); } } diff --git a/Recyclable.Collections/RecyclableList.cs b/Recyclable.Collections/RecyclableList.cs index 8a10cca..e75b646 100644 --- a/Recyclable.Collections/RecyclableList.cs +++ b/Recyclable.Collections/RecyclableList.cs @@ -36,7 +36,7 @@ namespace Recyclable.Collections { if (targetItemIdx + growByCount > capacity) { - capacity = Helpers.EnsureCapacity(this, capacity + growByCount); + capacity = RecyclableListHelpers.EnsureCapacity(this, capacity + growByCount); memorySpan = new(_memoryBlock); available = capacity - targetItemIdx; } @@ -59,7 +59,7 @@ namespace Recyclable.Collections private void AddRangeWithKnownCount(IEnumerable source, int targetItemIdx, int requiredAdditionalCapacity) { - _ = Helpers.EnsureCapacity(this, targetItemIdx + requiredAdditionalCapacity); + _ = RecyclableListHelpers.EnsureCapacity(this, targetItemIdx + requiredAdditionalCapacity); Span memorySpan = new(_memoryBlock); foreach (var item in source) @@ -82,7 +82,7 @@ namespace Recyclable.Collections { if (initialCapacity > 0) { - _memoryBlock = Helpers.Resize(_memoryBlock, initialCapacity); + _memoryBlock = RecyclableListHelpers.Resize(_memoryBlock, initialCapacity); _capacity = _memoryBlock.Length; } } @@ -131,7 +131,7 @@ namespace Recyclable.Collections public RecyclableList(IEnumerable source, int initialCapacity = RecyclableDefaults.Capacity) { - _memoryBlock = Helpers.Resize(_memoryBlock, initialCapacity); + _memoryBlock = RecyclableListHelpers.Resize(_memoryBlock, initialCapacity); _capacity = _memoryBlock.Length; AddRange(source); } @@ -149,7 +149,7 @@ namespace Recyclable.Collections } } - private int _capacity; + internal int _capacity; public int Capacity { get => _capacity; @@ -157,7 +157,7 @@ namespace Recyclable.Collections { if (_capacity != value) { - _memoryBlock = Helpers.Resize(_memoryBlock, value); + _memoryBlock = RecyclableListHelpers.Resize(_memoryBlock, value); _capacity = _memoryBlock.Length; _version++; } @@ -175,7 +175,7 @@ namespace Recyclable.Collections int requiredCapacity = _count + 1; if (_capacity < requiredCapacity) { - _ = Helpers.EnsureCapacity(this, requiredCapacity); + _ = RecyclableListHelpers.EnsureCapacity(this, requiredCapacity); } _memoryBlock[_count++] = item; @@ -194,14 +194,13 @@ namespace Recyclable.Collections int targetCapacity = _count + sourceItemsCount; if (_capacity < targetCapacity) { - _ = Helpers.EnsureCapacity(this, targetCapacity); + _ = RecyclableListHelpers.EnsureCapacity(this, targetCapacity); } var targetSpan = new Span(_memoryBlock, _count, sourceItemsCount); Span itemsSpan = new(items); itemsSpan.CopyTo(targetSpan); _count = targetCapacity; - _version++; } @@ -217,7 +216,7 @@ namespace Recyclable.Collections int targetCapacity = _count + sourceItemsCount; if (_capacity < targetCapacity) { - _ = Helpers.EnsureCapacity(this, targetCapacity); + _ = RecyclableListHelpers.EnsureCapacity(this, targetCapacity); } var targetSpan = new Span(_memoryBlock, _count, sourceItemsCount); @@ -239,7 +238,7 @@ namespace Recyclable.Collections var targetCapacity = _count + sourceItemsCount; if (_capacity < targetCapacity) { - _ = Helpers.EnsureCapacity(this, targetCapacity); + _ = RecyclableListHelpers.EnsureCapacity(this, targetCapacity); } items.CopyTo(_memoryBlock, _count); @@ -260,7 +259,7 @@ namespace Recyclable.Collections var targetCapacity = _count + sourceItemsCount; if (_capacity < targetCapacity) { - _ = Helpers.EnsureCapacity(this, targetCapacity); + _ = RecyclableListHelpers.EnsureCapacity(this, targetCapacity); } items.CopyTo(_memoryBlock, _count); @@ -281,7 +280,7 @@ namespace Recyclable.Collections var targetCapacity = _count + sourceItemsCount; if (_capacity < targetCapacity) { - _ = Helpers.EnsureCapacity(this, targetCapacity); + _ = RecyclableListHelpers.EnsureCapacity(this, targetCapacity); } var targetSpan = new Span(_memoryBlock, _count, sourceItemsCount); @@ -314,7 +313,7 @@ namespace Recyclable.Collections int targetCapacity = _count + (int)sourceItemsCount; if (_capacity < targetCapacity) { - _ = Helpers.EnsureCapacity(this, targetCapacity); + _ = RecyclableListHelpers.EnsureCapacity(this, targetCapacity); } Span targetSpan = new Span(_memoryBlock)[_count..], @@ -415,7 +414,7 @@ namespace Recyclable.Collections int requestedCapacity = oldCount + 1; if (_capacity < requestedCapacity) { - _ = Helpers.EnsureCapacity(this, requestedCapacity); + _ = RecyclableListHelpers.EnsureCapacity(this, requestedCapacity); } if (oldCount > 0) diff --git a/Recyclable.Collections/RecyclableQueue.cs b/Recyclable.Collections/RecyclableQueue.cs index 2f4c91b..8d1216e 100644 --- a/Recyclable.Collections/RecyclableQueue.cs +++ b/Recyclable.Collections/RecyclableQueue.cs @@ -171,13 +171,13 @@ namespace Recyclable.Collections } } - public bool Contains(T item) => RecyclableList.Helpers.Contains(Memory, item); - public void CopyTo(T[] array, int arrayIndex) => RecyclableList.Helpers.CopyTo(Memory, RemovedCount, BlockSize, (int)(LongCount % BlockSize), array, arrayIndex); - public IEnumerable Enumerate() => RecyclableList.Helpers.Enumerate(Memory, BlockSize, LongCount); - public IEnumerator GetEnumerator() => RecyclableList.Helpers.Enumerate(Memory, BlockSize, LongCount).GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => RecyclableList.Helpers.Enumerate(Memory, BlockSize, LongCount).GetEnumerator(); - public int IndexOf(T item) => (int)GetRelativeIndex(RecyclableList.Helpers.LongIndexOf(Memory, BlockSize, item, _equalityComparer)); - public long LongIndexOf(T item) => GetRelativeIndex(RecyclableList.Helpers.LongIndexOf(Memory, BlockSize, item, _equalityComparer)); + public bool Contains(T item) => RecyclableListHelpers.Contains(Memory, item); + public void CopyTo(T[] array, int arrayIndex) => RecyclableListHelpers.CopyTo(Memory, RemovedCount, BlockSize, (int)(LongCount % BlockSize), array, arrayIndex); + public IEnumerable Enumerate() => RecyclableListHelpers.Enumerate(Memory, BlockSize, LongCount); + public IEnumerator GetEnumerator() => RecyclableListHelpers.Enumerate(Memory, BlockSize, LongCount).GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => RecyclableListHelpers.Enumerate(Memory, BlockSize, LongCount).GetEnumerator(); + public int IndexOf(T item) => (int)GetRelativeIndex(RecyclableListHelpers.LongIndexOf(Memory, BlockSize, item, _equalityComparer)); + public long LongIndexOf(T item) => GetRelativeIndex(RecyclableListHelpers.LongIndexOf(Memory, BlockSize, item, _equalityComparer)); public void Insert(int index, T item) => throw new NotSupportedException(); public void RemoveAt(int index) => throw new NotSupportedException(); public bool TryDequeue(out T? item) => TryDequeue(this, out item); diff --git a/Recyclable.Collections/RecyclableSortedList.cs b/Recyclable.Collections/RecyclableSortedList.cs index 11968cd..b347a5f 100644 --- a/Recyclable.Collections/RecyclableSortedList.cs +++ b/Recyclable.Collections/RecyclableSortedList.cs @@ -68,7 +68,7 @@ BeginUpdate(); try { - RecyclableList<(TKey Key, TValue Value)>.Helpers.QuickSort(this, _comparer, _randomNumberGenerator); + RecyclableListHelpers<(TKey, TValue)>.QuickSort(this, _comparer, _randomNumberGenerator); } finally { diff --git a/Recyclable.CollectionsTests/RecyclableListTests.cs b/Recyclable.CollectionsTests/RecyclableListTests.cs index 2ae5f0c..327529e 100644 --- a/Recyclable.CollectionsTests/RecyclableListTests.cs +++ b/Recyclable.CollectionsTests/RecyclableListTests.cs @@ -422,7 +422,7 @@ namespace Recyclable.CollectionsTests // Act using RecyclableList list = new(testData); - RecyclableList.Helpers.QuickSort(list); + RecyclableListHelpers.QuickSort(list); // Validate _ = list.Count.Should().Be((int)itemsCount); diff --git a/Recyclable.CollectionsTests/RecyclableLongListTests.cs b/Recyclable.CollectionsTests/RecyclableLongListTests.cs index 30d091f..2125171 100644 --- a/Recyclable.CollectionsTests/RecyclableLongListTests.cs +++ b/Recyclable.CollectionsTests/RecyclableLongListTests.cs @@ -479,7 +479,7 @@ namespace Recyclable.CollectionsTests // Act using RecyclableLongList list = new(testData, minBlockSize: targetBlockSize); - RecyclableList.Helpers.QuickSort(list); + RecyclableListHelpers.QuickSort(list); // Validate _ = list.LongCount.Should().Be(itemsCount);