From 448656fd295a03e2efb88522c90b6a1ab62ae23a Mon Sep 17 00:00:00 2001 From: mlemanczyk Date: Sat, 24 Jun 2023 23:55:01 +0200 Subject: [PATCH] IVersionedLongList interface & RecyclableLongList.GetVersionedEnumerator added for use with foreach. --- Recyclable.Collections/IVersionedLongList.cs | 7 +++++++ .../RecyclableLongList.VersionedEnumerator.cs | 10 +++++++--- Recyclable.Collections/RecyclableLongList.cs | 1 - .../RecyclableLongListTests.cs | 18 ++++++++++++++++++ 4 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 Recyclable.Collections/IVersionedLongList.cs diff --git a/Recyclable.Collections/IVersionedLongList.cs b/Recyclable.Collections/IVersionedLongList.cs new file mode 100644 index 0000000..022de93 --- /dev/null +++ b/Recyclable.Collections/IVersionedLongList.cs @@ -0,0 +1,7 @@ +namespace Recyclable.Collections +{ + public interface IVersionedLongList : IEnumerable + { + new RecyclableLongList.VersionedEnumerator GetEnumerator(); + } +} diff --git a/Recyclable.Collections/RecyclableLongList.VersionedEnumerator.cs b/Recyclable.Collections/RecyclableLongList.VersionedEnumerator.cs index bd339ae..e11b112 100644 --- a/Recyclable.Collections/RecyclableLongList.VersionedEnumerator.cs +++ b/Recyclable.Collections/RecyclableLongList.VersionedEnumerator.cs @@ -3,8 +3,12 @@ using System.Diagnostics.Contracts; namespace Recyclable.Collections { - public partial class RecyclableLongList + +public partial class RecyclableLongList : IVersionedLongList { + public VersionedEnumerator GetVersionedEnumerator() => new(this); + VersionedEnumerator IVersionedLongList.GetEnumerator() => new(this); + public struct VersionedEnumerator : IEnumerator { #nullable disable @@ -26,13 +30,13 @@ namespace Recyclable.Collections public bool MoveNext() { - if (_enumeratorVersion != _list._version) + var list = _list; + if (_enumeratorVersion != list._version) { throw new InvalidOperationException(); } Contract.EndContractBlock(); - var list = _list; if (_currentBlockIndex < list._lastBlockWithData) { diff --git a/Recyclable.Collections/RecyclableLongList.cs b/Recyclable.Collections/RecyclableLongList.cs index 3b069e5..90ef792 100644 --- a/Recyclable.Collections/RecyclableLongList.cs +++ b/Recyclable.Collections/RecyclableLongList.cs @@ -1109,7 +1109,6 @@ namespace Recyclable.Collections public Enumerator GetEnumerator() => new(this); IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this); IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this); - public VersionedEnumerator GetVersionedEnumerator() => new(this); [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public int IndexOf(T item) diff --git a/Recyclable.CollectionsTests/RecyclableLongListTests.cs b/Recyclable.CollectionsTests/RecyclableLongListTests.cs index e2d610b..f1489a2 100644 --- a/Recyclable.CollectionsTests/RecyclableLongListTests.cs +++ b/Recyclable.CollectionsTests/RecyclableLongListTests.cs @@ -398,6 +398,24 @@ namespace Recyclable.CollectionsTests _ = actual.Should().ContainInConsecutiveOrder(testData); } + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))] + public void VersionedEnumerateShouldYieldAllItemsInCorrectOrder(string testCase, IEnumerable testData, long itemsCount, int targetBlockSize) + { + // Prepare + using var list = new RecyclableLongList(testData, minBlockSize: targetBlockSize); + + // Act + var actual = new List(); + foreach(var item in (IVersionedLongList)list) + { + actual.Add(item); + } + + // Validate + _ = actual.Should().ContainInConsecutiveOrder(testData); + } + [Fact] public void IndexOfShouldNotFindAnythingWhenListEmpty() {