diff --git a/Recyclable.Collections/Recyclable.Collections.csproj b/Recyclable.Collections/Recyclable.Collections.csproj
index 8ba20c8..a60db64 100644
--- a/Recyclable.Collections/Recyclable.Collections.csproj
+++ b/Recyclable.Collections/Recyclable.Collections.csproj
@@ -35,6 +35,6 @@
-
+
diff --git a/Recyclable.Collections/RecyclableLongList.cs b/Recyclable.Collections/RecyclableLongList.cs
index 9047d9b..cd89622 100644
--- a/Recyclable.Collections/RecyclableLongList.cs
+++ b/Recyclable.Collections/RecyclableLongList.cs
@@ -1,4 +1,5 @@
using System.Collections;
+using System.Diagnostics.Contracts;
using System.Numerics;
using System.Runtime.CompilerServices;
using Recyclable.Collections.Pools;
@@ -399,9 +400,18 @@ namespace Recyclable.Collections
public int IndexOf(T item, int index)
{
+ if (index < 0 || index >= _longCount)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException_Index();
+ }
+
+ Contract.Requires(index >= 0);
+ Contract.Requires(index < _longCount);
+ Contract.EndContractBlock();
+
if (_lastBlockWithData == 0)
{
- return Array.IndexOf(_memoryBlocks[0], item, index, _longCount < _blockSize ? _nextItemIndex : _blockSize);
+ return Array.IndexOf(_memoryBlocks[0], item, index, (_longCount < _blockSize ? _nextItemIndex : _blockSize) - index);
}
else if (_longCount == 0)
{
@@ -410,12 +420,12 @@ namespace Recyclable.Collections
int firstBlockIndex = index >> _blockSizePow2BitShift;
int firstItemIndex = index & _blockSizeMinus1;
- int itemIndex = Array.IndexOf(_memoryBlocks[firstBlockIndex], item, firstItemIndex, (firstBlockIndex == _lastBlockWithData ? _nextItemIndex : _blockSize) - firstItemIndex);
+ int itemIndex = Array.IndexOf(_memoryBlocks[firstBlockIndex], item, firstItemIndex, (firstBlockIndex == _lastBlockWithData && _nextItemIndex > 0 ? _nextItemIndex : _blockSize) - firstItemIndex);
if (itemIndex >= 0)
{
return (firstBlockIndex << _blockSizePow2BitShift) + itemIndex;
}
- else if (_longCount < RecyclableDefaults.MinItemsCountForParallelization)
+ else if (_longCount < RecyclableDefaults.MinItemsCountForParallelization && firstBlockIndex + 1 <= _lastBlockWithData)
{
return (int)RecyclableLongList.IndexOfHelpers.IndexOfSequential(this, item, firstBlockIndex + 1);
}
@@ -435,6 +445,20 @@ namespace Recyclable.Collections
public int IndexOf(T item, int index, int count)
{
+ if (index < 0)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException_Index();
+ }
+
+ if (count + index > _longCount)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException_Count();
+ }
+
+ Contract.Requires(index >= 0);
+ Contract.Requires(count + index <= _longCount);
+ Contract.EndContractBlock();
+
if (_lastBlockWithData == 0)
{
return Array.IndexOf(_memoryBlocks[0], item, index, count);
@@ -454,13 +478,13 @@ namespace Recyclable.Collections
{
return (firstBlockIndex << _blockSizePow2BitShift) + itemIndex;
}
- else if (_longCount < RecyclableDefaults.MinItemsCountForParallelization)
+ else if (_longCount < RecyclableDefaults.MinItemsCountForParallelization && firstBlockIndex + 1 <= _lastBlockWithData)
{
return (int)RecyclableLongList.IndexOfHelpers.IndexOfSequential(this, item, firstBlockIndex + 1, count - firstBlockItemsCount);
}
else
{
- if (_longCount > blockSize)
+ if (firstBlockIndex + 1 <= _lastBlockWithData)
{
itemIndex = Array.IndexOf(_memoryBlocks[firstBlockIndex + 1], item, 0, (int)MathUtils.Min(blockSize, _longCount - blockSize, count - firstBlockItemsCount));
return itemIndex >= 0 ? ((firstBlockIndex + 1) << _blockSizePow2BitShift) + itemIndex : checked((int)RecyclableLongList.IndexOfHelpers.IndexOfParallel(this, item, firstBlockIndex + 2, count - firstBlockItemsCount - blockSize));
diff --git a/Recyclable.CollectionsTests/Recyclable.CollectionsTests.csproj b/Recyclable.CollectionsTests/Recyclable.CollectionsTests.csproj
index 7194de6..9851ec6 100644
--- a/Recyclable.CollectionsTests/Recyclable.CollectionsTests.csproj
+++ b/Recyclable.CollectionsTests/Recyclable.CollectionsTests.csproj
@@ -10,18 +10,20 @@
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/Recyclable.CollectionsTests/RecyclableListTests.cs b/Recyclable.CollectionsTests/RecyclableListTests.cs
index 237175b..587ca31 100644
--- a/Recyclable.CollectionsTests/RecyclableListTests.cs
+++ b/Recyclable.CollectionsTests/RecyclableListTests.cs
@@ -3,6 +3,7 @@ using Recyclable.Collections;
using Recyclable.Collections.TestData;
using Recyclable.Collections.Linq;
using System.Collections;
+using Recyclable.Collections.TestData.xUnit;
#pragma warning disable xUnit1026, RCS1163, IDE0060, RCS1235
@@ -29,7 +30,7 @@ namespace Recyclable.CollectionsTests
}
[Theory]
- [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))]
+ [ClassData(typeof(SourceDataTheoryData))]
public void AddRangeShouldAddItemsInCorrectOrder(string testCase, IEnumerable testData, int itemsCount)
{
// Prepare
@@ -103,7 +104,7 @@ namespace Recyclable.CollectionsTests
}
[Theory]
- [MemberData(nameof(RecyclableLongListTestData.EmptySourceDataVariants), MemberType = typeof(RecyclableLongListTestData))]
+ [ClassData(typeof(EmptySourceDataTheoryData))]
public void AddRangeShouldDoNothingWhenSourceIsEmpty(string testCase, IEnumerable testData, int itemsCount)
{
// Prepare
@@ -177,7 +178,7 @@ namespace Recyclable.CollectionsTests
}
[Theory]
- [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))]
+ [ClassData(typeof(SourceDataTheoryData))]
public void AddRangeShouldNotOverrideItems(string testCase, IEnumerable testData, int itemsCount)
{
// Prepare
@@ -268,7 +269,7 @@ namespace Recyclable.CollectionsTests
}
[Theory]
- [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))]
+ [ClassData(typeof(SourceDataTheoryData))]
public void AddShouldAcceptDuplicates(string testCase, IEnumerable testData, int itemsCount)
{
// Prepare
@@ -312,7 +313,7 @@ namespace Recyclable.CollectionsTests
}
[Theory]
- [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))]
+ [ClassData(typeof(SourceDataTheoryData))]
public void AddShouldAddItems(string testCase, IEnumerable testData, int itemsCount)
{
// Prepare
@@ -334,7 +335,7 @@ namespace Recyclable.CollectionsTests
}
[Theory]
- [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))]
+ [ClassData(typeof(SourceDataTheoryData))]
public void AddShouldAddItemWhenAfterAddRange(string testCase, IEnumerable testData, int itemsCount)
{
// Prepare
@@ -359,7 +360,7 @@ namespace Recyclable.CollectionsTests
}
[Theory]
- [MemberData(nameof(RecyclableLongListTestData.SourceRefDataVariants), MemberType = typeof(RecyclableLongListTestData))]
+ [ClassData(typeof(SourceRefDataTheoryData))]
public void ClearShouldClearItemsWhenReferenceType(string testCase, IEnumerable