diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2ca81426..797b8cee 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,9 +11,10 @@ on: pull_request: branches: - master + - releases/* paths-ignore: - "*.md" - + workflow_dispatch: env: @@ -52,7 +53,7 @@ jobs: deploy: name: Deploy - if: ${{ github.ref == 'refs/heads/master' }} + if: ${{ github.ref == 'refs/heads/master' && startsWith(github.ref, 'refs/tags/v') }} runs-on: ubuntu-latest diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..520c3162 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + "recommendations": [ + "davidanson.vscode-markdownlint", + "github.vscode-github-actions", + "ms-dotnettools.csharp", + "streetsidesoftware.code-spell-checker", + "redhat.vscode-yaml" + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..1964c373 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,25 @@ +{ + "[yaml]": { + "editor.insertSpaces": true, + "editor.tabSize": 2, + "editor.autoIndent": "advanced" + }, + "[json]": { + "editor.insertSpaces": true, + "editor.tabSize": 2, + "editor.autoIndent": "advanced" + }, + "editor.tabSize": 4, + "editor.trimAutoWhitespace": true, + "files.autoSave": "afterDelay", + "files.trimFinalNewlines": true, + "files.trimTrailingWhitespace": true, + "cSpell.language": "en", + "cSpell.enabled": true, + "cSpell.enableFiletypes": [ + "*" + ], + "cSpell.words": [ + "showable" + ] +} \ No newline at end of file diff --git a/C5.Tests/Arrays/ArrayListTest.cs b/C5.Tests/Arrays/ArrayListTest.cs index 06aef00e..510efdad 100644 --- a/C5.Tests/Arrays/ArrayListTest.cs +++ b/C5.Tests/Arrays/ArrayListTest.cs @@ -7,34 +7,23 @@ namespace C5.Tests.arrays.list { - using CollectionOfInt = ArrayList; - [TestFixture] public class GenericTesters { [Test] public void TestEvents() { - CollectionOfInt factory() { return new CollectionOfInt(TenEqualityComparer.Default); } - new C5.Tests.Templates.Events.ListTester().Test(factory); - new C5.Tests.Templates.Events.QueueTester().Test(factory); - new C5.Tests.Templates.Events.StackTester().Test(factory); + ArrayList factory() { return new ArrayList(TenEqualityComparer.Default); } + new C5.Tests.Templates.Events.ListTester>().Test(factory); + new C5.Tests.Templates.Events.QueueTester>().Test(factory); + new C5.Tests.Templates.Events.StackTester>().Test(factory); } - //[Test] - //public void Extensible() - //{ - // C5.Tests.Templates.Extensible.Clone.Tester(); - // C5.Tests.Templates.Extensible.Clone.ViewTester(); - // C5.Tests.Templates.Extensible.Serialization.Tester(); - // C5.Tests.Templates.Extensible.Serialization.ViewTester(); - //} - [Test] public void List() { - C5.Tests.Templates.List.Dispose.Tester(); - C5.Tests.Templates.List.SCG_IList.Tester(); + Templates.List.Dispose.Tester>(); + Templates.List.SCG_IList.Tester>(); } } @@ -55,7 +44,7 @@ public class IList_ public void Init() { list = new ArrayList(TenEqualityComparer.Default); - seen = new CollectionEventList(System.Collections.Generic.EqualityComparer.Default); + seen = new CollectionEventList(SCG.EqualityComparer.Default); } private void listen() { seen.Listen(list, EventType.Added); } @@ -63,10 +52,13 @@ public void Init() [Test] public void Listenable() { - Assert.AreEqual(EventType.All, list.ListenableEvents); - Assert.AreEqual(EventType.None, list.ActiveEvents); + Assert.Multiple(() => + { + Assert.That(list.ListenableEvents, Is.EqualTo(EventType.All)); + Assert.That(list.ActiveEvents, Is.EqualTo(EventType.None)); + }); listen(); - Assert.AreEqual(EventType.Added, list.ActiveEvents); + Assert.That(list.ActiveEvents, Is.EqualTo(EventType.Added)); } [Test] @@ -75,13 +67,13 @@ public void SetThis() list.Add(4); list.Add(56); list.Add(8); listen(); list[1] = 45; - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), list), new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(56,1), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(45, 1), list), new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(45,1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); } [Test] @@ -90,11 +82,11 @@ public void Insert() list.Add(4); list.Add(56); list.Add(8); listen(); list.Insert(1, 45); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(45,1), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(45, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); } [Test] @@ -102,9 +94,9 @@ public void InsertAll() { list.Add(4); list.Add(56); list.Add(8); listen(); - list.InsertAll(1, new int[] { 666, 777, 888 }); + list.InsertAll(1, [666, 777, 888]); //seen.Print(Console.Error); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(666,1), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(666, 1), list), new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(777,2), list), @@ -112,9 +104,9 @@ public void InsertAll() new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(888,3), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(888, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); - list.InsertAll(1, new int[] { }); - seen.Check(new CollectionEvent[] { }); + ]); + list.InsertAll(1, []); + seen.Check([]); } [Test] @@ -123,17 +115,17 @@ public void InsertFirstLast() list.Add(4); list.Add(56); list.Add(8); listen(); list.InsertFirst(45); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(45,0), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(45, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.InsertLast(88); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(88,4), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(88, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); } [Test] @@ -142,9 +134,9 @@ public void Remove() list.Add(4); list.Add(56); list.Add(8); listen(); list.Remove(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(8, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); } [Test] @@ -153,10 +145,10 @@ public void RemoveFirst() list.Add(4); list.Add(56); list.Add(8); listen(); list.RemoveFirst(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(4,0), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(4, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); } [Test] @@ -165,10 +157,10 @@ public void RemoveLast() list.Add(4); list.Add(56); list.Add(8); listen(); list.RemoveLast(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(8,2), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(8, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); } [Test] @@ -177,11 +169,11 @@ public void Reverse() list.Add(4); list.Add(56); list.Add(8); listen(); list.Reverse(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.View(1, 0).Reverse(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } @@ -191,11 +183,11 @@ public void Sort() list.Add(4); list.Add(56); list.Add(8); listen(); list.Sort(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.View(1, 0).Sort(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } [Test] @@ -204,11 +196,11 @@ public void Shuffle() list.Add(4); list.Add(56); list.Add(8); listen(); list.Shuffle(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.View(1, 0).Shuffle(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } [Test] @@ -217,10 +209,10 @@ public void RemoveAt() list.Add(4); list.Add(56); list.Add(8); listen(); list.RemoveAt(1); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(56,1), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); } [Test] @@ -229,12 +221,12 @@ public void RemoveInterval() list.Add(4); list.Add(56); list.Add(8); listen(); list.RemoveInterval(1, 2); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Cleared, new ClearedRangeEventArgs(false,2,1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.RemoveInterval(1, 0); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } [Test] @@ -243,13 +235,13 @@ public void Update() list.Add(4); list.Add(56); list.Add(8); listen(); list.Update(53); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(53, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.Update(67); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } [Test] @@ -259,13 +251,13 @@ public void FindOrAdd() listen(); int val = 53; list.FindOrAdd(ref val); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); val = 67; list.FindOrAdd(ref val); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(67, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); } [Test] @@ -275,29 +267,29 @@ public void UpdateOrAdd() listen(); int val = 53; list.UpdateOrAdd(val); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(53, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); val = 67; list.UpdateOrAdd(val); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(67, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.UpdateOrAdd(51, out _); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(53, 1), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(51, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); // val = 67; list.UpdateOrAdd(81, out _); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(81, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); } [Test] @@ -306,13 +298,13 @@ public void RemoveItem() list.Add(4); list.Add(56); list.Add(18); listen(); list.Remove(53); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); list.Remove(11); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(18, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); } [Test] @@ -323,14 +315,14 @@ public void RemoveAll() list.Add(10 * i + 5); } listen(); - list.RemoveAll(new int[] { 32, 187, 45 }); + list.RemoveAll([32, 187, 45]); //TODO: the order depends on internals of the HashSet - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(35, 1), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(45, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); - list.RemoveAll(new int[] { 200, 300 }); - seen.Check(new CollectionEvent[] { }); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); + list.RemoveAll([200, 300]); + seen.Check([]); } [Test] @@ -339,17 +331,17 @@ public void Clear() list.Add(4); list.Add(56); list.Add(8); listen(); list.View(1, 1).Clear(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Cleared, new ClearedRangeEventArgs(false,1,1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.Clear(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Cleared, new ClearedRangeEventArgs(true,2,0), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.Clear(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } [Test] @@ -358,14 +350,14 @@ public void ListDispose() list.Add(4); list.Add(56); list.Add(8); listen(); list.View(1, 1).Dispose(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); list.Dispose(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Cleared, new ClearedRangeEventArgs(true,3,0), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.Dispose(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } @@ -377,15 +369,15 @@ public void RetainAll() list.Add(10 * i + 5); } listen(); - list.RetainAll(new int[] { 32, 187, 45, 62, 82, 95, 2 }); - seen.Check(new CollectionEvent[] { + list.RetainAll([32, 187, 45, 62, 82, 95, 2]); + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(15, 1), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(25, 1), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(55, 1), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(75, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); - list.RetainAll(new int[] { 32, 187, 45, 62, 82, 95, 2 }); - seen.Check(new CollectionEvent[] { }); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); + list.RetainAll([32, 187, 45, 62, 82, 95, 2]); + seen.Check([]); } [Test] @@ -397,24 +389,24 @@ public void RemoveAllCopies() } listen(); list.RemoveAllCopies(14); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(11, 1), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(14, 1), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(17, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); list.RemoveAllCopies(14); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } [Test] public void Add() { listen(); - seen.Check(new CollectionEvent[0]); + seen.Check([]); list.Add(23); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(23, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); } [Test] @@ -425,19 +417,19 @@ public void AddAll() list.Add(10 * i + 5); } listen(); - list.AddAll(new int[] { 45, 56, 67 }); - seen.Check(new CollectionEvent[] { + list.AddAll([45, 56, 67]); + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(45, 1), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(56, 1), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(67, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); - list.AddAll(new int[] { }); - seen.Check(new CollectionEvent[] { }); + ]); + list.AddAll([]); + seen.Check([]); } [TearDown] - public void Dispose() { list = null; seen = null; } + public void Dispose() { list.Dispose(); seen = null; } [Test] public void ViewChanged() @@ -523,7 +515,7 @@ public class StackQueue public void Init() { list = new ArrayList(TenEqualityComparer.Default); - seen = new CollectionEventList(System.Collections.Generic.EqualityComparer.Default); + seen = new CollectionEventList(SCG.EqualityComparer.Default); } private void listen() { seen.Listen(list, EventType.All); } @@ -533,56 +525,56 @@ public void EnqueueDequeue() { listen(); list.Enqueue(67); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(67,0), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(67, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); list.Enqueue(2); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(2,1), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(2, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); list.Dequeue(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(67,0), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(67, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); list.Dequeue(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(2,0), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(2, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); } [Test] public void PushPop() { listen(); - seen.Check(new CollectionEvent[0]); + seen.Check([]); list.Push(23); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(23,0), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(23, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); list.Push(-12); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(-12,1), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(-12, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); list.Pop(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(-12,1), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(-12, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); list.Pop(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(23,0), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(23, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); } [TearDown] - public void Dispose() { list = null; seen = null; } + public void Dispose() { list.Dispose(); seen = null; } } } @@ -612,8 +604,12 @@ public void InsertAll() Assert.Fail("Should not get here"); } catch (BadEnumerableException) { } - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 9, 8, 7, 56, 8)); + + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 9, 8, 7, 56, 8), Is.True); + }); } @@ -627,8 +623,12 @@ public void AddAll() Assert.Fail("Should not get here"); } catch (BadEnumerableException) { } - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 9, 8, 7, 56, 8)); + + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 9, 8, 7, 56, 8), Is.True); + }); } [Test] @@ -641,8 +641,12 @@ public void RemoveAll() Assert.Fail("Should not get here"); } catch (BadEnumerableException) { } - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 56, 8)); + + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 56, 8), Is.True); + }); } [Test] @@ -655,8 +659,12 @@ public void RetainAll() Assert.Fail("Should not get here"); } catch (BadEnumerableException) { } - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 56, 8)); + + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 56, 8), Is.True); + }); } @@ -670,13 +678,17 @@ public void ContainsAll() Assert.Fail("Should not get here"); } catch (BadEnumerableException) { } - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 56, 8)); + + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 56, 8), Is.True); + }); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } /// @@ -722,34 +734,52 @@ public void Init() [Test] public void All() { - Assert.IsTrue(list.All(always)); - Assert.IsTrue(list.All(never)); - Assert.IsTrue(list.All(even)); + Assert.Multiple(() => + { + Assert.That(list.All(always), Is.True); + Assert.That(list.All(never), Is.True); + Assert.That(list.All(even), Is.True); + }); list.Add(8); - Assert.IsTrue(list.All(always)); - Assert.IsFalse(list.All(never)); - Assert.IsTrue(list.All(even)); + Assert.Multiple(() => + { + Assert.That(list.All(always), Is.True); + Assert.That(list.All(never), Is.False); + Assert.That(list.All(even), Is.True); + }); list.Add(5); - Assert.IsTrue(list.All(always)); - Assert.IsFalse(list.All(never)); - Assert.IsFalse(list.All(even)); + Assert.Multiple(() => + { + Assert.That(list.All(always), Is.True); + Assert.That(list.All(never), Is.False); + Assert.That(list.All(even), Is.False); + }); } [Test] public void Exists() { - Assert.IsFalse(list.Exists(always)); - Assert.IsFalse(list.Exists(never)); - Assert.IsFalse(list.Exists(even)); + Assert.Multiple(() => + { + Assert.That(list.Exists(always), Is.False); + Assert.That(list.Exists(never), Is.False); + Assert.That(list.Exists(even), Is.False); + }); list.Add(5); - Assert.IsTrue(list.Exists(always)); - Assert.IsFalse(list.Exists(never)); - Assert.IsFalse(list.Exists(even)); + Assert.Multiple(() => + { + Assert.That(list.Exists(always), Is.True); + Assert.That(list.Exists(never), Is.False); + Assert.That(list.Exists(even), Is.False); + }); list.Add(8); - Assert.IsTrue(list.Exists(always)); - Assert.IsFalse(list.Exists(never)); - Assert.IsTrue(list.Exists(even)); + Assert.Multiple(() => + { + Assert.That(list.Exists(always), Is.True); + Assert.That(list.Exists(never), Is.False); + Assert.That(list.Exists(even), Is.True); + }); } @@ -760,16 +790,16 @@ public void Apply() void a(int i) { sum = i + 10 * sum; } list.Apply(a); - Assert.AreEqual(0, sum); + Assert.That(sum, Is.EqualTo(0)); sum = 0; list.Add(5); list.Add(8); list.Add(7); list.Add(5); list.Apply(a); - Assert.AreEqual(5875, sum); + Assert.That(sum, Is.EqualTo(5875)); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } @@ -789,7 +819,7 @@ public void Empty() { SCG.IEnumerator e = list.GetEnumerator(); - Assert.IsFalse(e.MoveNext()); + Assert.That(e.MoveNext(), Is.False); } @@ -805,19 +835,22 @@ public void Normal() SCG.IEnumerator e = list.GetEnumerator(); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(5, e.Current); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(8, e.Current); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(5, e.Current); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(5, e.Current); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(10, e.Current); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(1, e.Current); - Assert.IsFalse(e.MoveNext()); + Assert.Multiple(() => + { + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(5)); + }); + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(8)); + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(5)); + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(5)); + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(10)); + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(1)); + Assert.That(e.MoveNext(), Is.False); } @@ -851,7 +884,7 @@ public void MoveNextAfterUpdate() } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } } @@ -869,12 +902,15 @@ public class Formatting [Test] public void Format() { - Assert.AreEqual("[ ]", coll.ToString()); - coll.AddAll(new int[] { -4, 28, 129, 65530 }); - Assert.AreEqual("[ 0:-4, 1:28, 2:129, 3:65530 ]", coll.ToString()); - Assert.AreEqual("[ 0:-4, 1:1C, 2:81, 3:FFFA ]", coll.ToString(null, rad16)); - Assert.AreEqual("[ 0:-4, 1:28... ]", coll.ToString("L14", null)); - Assert.AreEqual("[ 0:-4, 1:1C... ]", coll.ToString("L14", rad16)); + Assert.That(coll.ToString(), Is.EqualTo("[ ]")); + coll.AddAll([-4, 28, 129, 65530]); + Assert.Multiple(() => + { + Assert.That(coll.ToString(), Is.EqualTo("[ 0:-4, 1:28, 2:129, 3:65530 ]")); + Assert.That(coll.ToString(null, rad16), Is.EqualTo("[ 0:-4, 1:1C, 2:81, 3:FFFA ]")); + Assert.That(coll.ToString("L14", null), Is.EqualTo("[ 0:-4, 1:28... ]")); + Assert.That(coll.ToString("L14", rad16), Is.EqualTo("[ 0:-4, 1:1C... ]")); + }); } } @@ -891,7 +927,7 @@ public class CollectionOrSink public void Choose() { list.Add(7); - Assert.AreEqual(7, list.Choose()); + Assert.That(list.Choose(), Is.EqualTo(7)); } [Test] @@ -903,17 +939,20 @@ public void BadChoose() [Test] public void CountEtAl() { - Assert.AreEqual(0, list.Count); - Assert.IsTrue(list.IsEmpty); - Assert.IsTrue(list.AllowsDuplicates); + Assert.That(list, Is.Empty); + Assert.Multiple(() => + { + Assert.That(list.IsEmpty, Is.True); + Assert.That(list.AllowsDuplicates, Is.True); + }); list.Add(5); - Assert.AreEqual(1, list.Count); - Assert.IsFalse(list.IsEmpty); + Assert.That(list, Has.Count.EqualTo(1)); + Assert.That(list.IsEmpty, Is.False); list.Add(5); - Assert.AreEqual(2, list.Count); - Assert.IsFalse(list.IsEmpty); + Assert.That(list, Has.Count.EqualTo(2)); + Assert.That(list.IsEmpty, Is.False); list.Add(8); - Assert.AreEqual(3, list.Count); + Assert.That(list, Has.Count.EqualTo(3)); } [Test] @@ -921,17 +960,20 @@ public void AddAll() { list.Add(3); list.Add(4); list.Add(5); - ArrayList list2 = new ArrayList(); + ArrayList list2 = new(); list2.AddAll(list); - Assert.IsTrue(IC.Eq(list2, 3, 4, 5)); + Assert.That(IC.Eq(list2, 3, 4, 5), Is.True); list.AddAll(list2); - Assert.IsTrue(IC.Eq(list2, 3, 4, 5)); - Assert.IsTrue(IC.Eq(list, 3, 4, 5, 3, 4, 5)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list2, 3, 4, 5), Is.True); + Assert.That(IC.Eq(list, 3, 4, 5, 3, 4, 5), Is.True); + }); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } [TestFixture] @@ -948,48 +990,54 @@ public void Init() } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } [Test] public void Find() { - Assert.IsFalse(list.Find(pred, out int i)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(list.Find(pred, out i)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.IsTrue(list.Find(pred, out i)); - Assert.AreEqual(45, i); + Assert.That(list.Find(pred, out int i), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(list.Find(pred, out i), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.Multiple(() => + { + Assert.That(list.Find(pred, out i), Is.True); + Assert.That(i, Is.EqualTo(45)); + }); } [Test] public void FindLast() { - Assert.IsFalse(list.FindLast(pred, out int i)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(list.FindLast(pred, out i)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.IsTrue(list.FindLast(pred, out i)); - Assert.AreEqual(675, i); + Assert.That(list.FindLast(pred, out int i), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(list.FindLast(pred, out i), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.Multiple(() => + { + Assert.That(list.FindLast(pred, out i), Is.True); + Assert.That(i, Is.EqualTo(675)); + }); } [Test] public void FindIndex() { - Assert.IsFalse(0 <= list.FindIndex(pred)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(0 <= list.FindIndex(pred)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.AreEqual(4, list.FindIndex(pred)); + Assert.That(0 <= list.FindIndex(pred), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(0 <= list.FindIndex(pred), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.That(list.FindIndex(pred), Is.EqualTo(4)); } [Test] public void FindLastIndex() { - Assert.IsFalse(0 <= list.FindLastIndex(pred)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(0 <= list.FindLastIndex(pred)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.AreEqual(6, list.FindLastIndex(pred)); + Assert.That(0 <= list.FindLastIndex(pred), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(0 <= list.FindLastIndex(pred), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.That(list.FindLastIndex(pred), Is.EqualTo(6)); } } @@ -1002,16 +1050,22 @@ public class UniqueItems public void Init() { list = new ArrayList(); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } [Test] public void Test() { - Assert.IsTrue(IC.SetEq(list.UniqueItems())); - Assert.IsTrue(IC.SetEq(list.ItemMultiplicities())); - list.AddAll(new int[] { 7, 9, 7 }); - Assert.IsTrue(IC.SetEq(list.UniqueItems(), 7, 9)); - Assert.IsTrue(IC.SetEq(list.ItemMultiplicities(), 7, 2, 9, 1)); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(list.UniqueItems()), Is.True); + Assert.That(IC.SetEq(list.ItemMultiplicities()), Is.True); + }); + list.AddAll([7, 9, 7]); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(list.UniqueItems(), 7, 9), Is.True); + Assert.That(IC.SetEq(list.ItemMultiplicities(), 7, 2, 9, 1), Is.True); + }); } } @@ -1035,7 +1089,7 @@ public void Init() [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } private string aeq(int[] a, params int[] b) @@ -1059,10 +1113,10 @@ private string aeq(int[] a, params int[] b) [Test] public void ToArray() { - Assert.AreEqual("Alles klar", aeq(list.ToArray())); + Assert.That(aeq(list.ToArray()), Is.EqualTo("Alles klar")); list.Add(7); list.Add(7); - Assert.AreEqual("Alles klar", aeq(list.ToArray(), 7, 7)); + Assert.That(aeq(list.ToArray(), 7, 7), Is.EqualTo("Alles klar")); } @@ -1070,19 +1124,19 @@ public void ToArray() public void CopyTo() { list.CopyTo(a, 1); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009), Is.EqualTo("Alles klar")); list.Add(6); list.CopyTo(a, 2); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009), Is.EqualTo("Alles klar")); list.Add(4); list.Add(4); list.Add(9); list.CopyTo(a, 4); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 4, 4, 9, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 6, 4, 4, 9, 1008, 1009), Is.EqualTo("Alles klar")); list.Clear(); list.Add(7); list.CopyTo(a, 9); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 4, 4, 9, 1008, 7)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 6, 4, 4, 9, 1008, 7), Is.EqualTo("Alles klar")); } @@ -1112,24 +1166,12 @@ public void CopyToTooFar() [TestFixture] public class Sync { - private ArrayList list; - - - [SetUp] - public void Init() - { - list = new ArrayList(); - } - - - [TearDown] - public void Dispose() { list = null; } - - [Test] - public void Get() + public void ArrayList_has_SyncRoot() { - Assert.IsNotNull(((System.Collections.IList)list).SyncRoot); + var list = new ArrayList(); + + Assert.That(((System.Collections.IList)list).SyncRoot, Is.Not.Null); } } } @@ -1160,39 +1202,54 @@ public void NullEqualityComparerinConstructor2() [Test] public void Contains() { - Assert.IsFalse(list.Contains(5)); + Assert.That(list.Contains(5), Is.False); list.Add(5); - Assert.IsTrue(list.Contains(5)); - Assert.IsFalse(list.Contains(7)); + Assert.Multiple(() => + { + Assert.That(list.Contains(5), Is.True); + Assert.That(list.Contains(7), Is.False); + }); list.Add(8); list.Add(10); - Assert.IsTrue(list.Contains(5)); - Assert.IsFalse(list.Contains(7)); - Assert.IsTrue(list.Contains(8)); - Assert.IsTrue(list.Contains(10)); + Assert.Multiple(() => + { + Assert.That(list.Contains(5), Is.True); + Assert.That(list.Contains(7), Is.False); + Assert.That(list.Contains(8), Is.True); + Assert.That(list.Contains(10), Is.True); + }); list.Remove(8); - Assert.IsTrue(list.Contains(5)); - Assert.IsFalse(list.Contains(7)); - Assert.IsFalse(list.Contains(8)); - Assert.IsTrue(list.Contains(10)); + Assert.Multiple(() => + { + Assert.That(list.Contains(5), Is.True); + Assert.That(list.Contains(7), Is.False); + Assert.That(list.Contains(8), Is.False); + Assert.That(list.Contains(10), Is.True); + }); } [Test] public void ContainsCount() { - Assert.AreEqual(0, list.ContainsCount(5)); + Assert.That(list.ContainsCount(5), Is.EqualTo(0)); list.Add(5); - Assert.AreEqual(1, list.ContainsCount(5)); - Assert.AreEqual(0, list.ContainsCount(7)); + Assert.Multiple(() => + { + Assert.That(list.ContainsCount(5), Is.EqualTo(1)); + Assert.That(list.ContainsCount(7), Is.EqualTo(0)); + }); list.Add(8); - Assert.AreEqual(1, list.ContainsCount(5)); - Assert.AreEqual(0, list.ContainsCount(7)); - Assert.AreEqual(1, list.ContainsCount(8)); + Assert.Multiple(() => + { + Assert.That(list.ContainsCount(5), Is.EqualTo(1)); + Assert.That(list.ContainsCount(7), Is.EqualTo(0)); + Assert.That(list.ContainsCount(8), Is.EqualTo(1)); + }); list.Add(5); - Assert.AreEqual(2, list.ContainsCount(5)); - Assert.AreEqual(0, list.ContainsCount(7)); - Assert.AreEqual(1, list.ContainsCount(8)); + Assert.That(list.ContainsCount(5), Is.EqualTo(2)); + Assert.That(list.ContainsCount(7), Is.EqualTo(0)); + Assert.That(list.ContainsCount(8), Is.EqualTo(1)); } @@ -1200,14 +1257,17 @@ public void ContainsCount() public void RemoveAllCopies() { list.Add(5); list.Add(7); list.Add(5); - Assert.AreEqual(2, list.ContainsCount(5)); - Assert.AreEqual(1, list.ContainsCount(7)); + Assert.Multiple(() => + { + Assert.That(list.ContainsCount(5), Is.EqualTo(2)); + Assert.That(list.ContainsCount(7), Is.EqualTo(1)); + }); list.RemoveAllCopies(5); - Assert.AreEqual(0, list.ContainsCount(5)); - Assert.AreEqual(1, list.ContainsCount(7)); + Assert.That(list.ContainsCount(5), Is.EqualTo(0)); + Assert.That(list.ContainsCount(7), Is.EqualTo(1)); list.Add(5); list.Add(8); list.Add(5); list.RemoveAllCopies(8); - Assert.IsTrue(IC.Eq(list, 7, 5, 5)); + Assert.That(IC.Eq(list, 7, 5, 5), Is.True); } @@ -1216,113 +1276,137 @@ public void FindAll() { bool f(int i) { return i % 2 == 0; } - Assert.IsTrue(list.FindAll(f).IsEmpty); + Assert.That(list.FindAll(f).IsEmpty, Is.True); list.Add(5); list.Add(8); list.Add(5); list.Add(10); list.Add(8); - Assert.IsTrue(((ArrayList)list.FindAll(f)).Check()); - Assert.IsTrue(IC.Eq(list.FindAll(f), 8, 10, 8)); + Assert.Multiple(() => + { + Assert.That(((ArrayList)list.FindAll(f)).Check(), Is.True); + Assert.That(IC.Eq(list.FindAll(f), 8, 10, 8), Is.True); + }); } [Test] public void ContainsAll() { - ArrayList list2 = new ArrayList(); + ArrayList list2 = new(); - Assert.IsTrue(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.True); list2.Add(4); - Assert.IsFalse(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.False); list.Add(4); - Assert.IsTrue(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.True); list.Add(5); - Assert.IsTrue(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.True); list2.Add(4); - Assert.IsFalse(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.False); list.Add(4); - Assert.IsTrue(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.True); } [Test] public void RetainAll() { - ArrayList list2 = new ArrayList(); + ArrayList list2 = new(); list.Add(4); list.Add(4); list.Add(5); list.Add(4); list.Add(6); list2.Add(5); list2.Add(4); list2.Add(7); list2.Add(7); list2.Add(4); list.RetainAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 4, 5)); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 4, 5), Is.True); + }); list.Add(5); list.Add(4); list.Add(6); list2.Clear(); list2.Add(5); list2.Add(5); list2.Add(6); list.RetainAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 5, 5, 6)); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 5, 5, 6), Is.True); + }); list2.Clear(); list2.Add(7); list2.Add(8); list2.Add(9); list.RetainAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list), Is.True); } [Test] public void RemoveAll() { - ArrayList list2 = new ArrayList(); + ArrayList list2 = new(); list.Add(4); list.Add(4); list.Add(5); list.Add(4); list.Add(6); list2.Add(5); list2.Add(4); list2.Add(7); list2.Add(7); list2.Add(4); list.RemoveAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 6)); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 6), Is.True); + }); list.Add(5); list.Add(4); list.Add(6); list2.Clear(); list2.Add(6); list2.Add(5); list2.Add(5); list2.Add(6); list.RemoveAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 4)); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 4), Is.True); + }); list2.Clear(); list2.Add(7); list2.Add(8); list2.Add(9); list.RemoveAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 4)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 4), Is.True); } [Test] public void Remove() { - Assert.IsFalse(list.FIFO); + Assert.That(list.FIFO, Is.False); list.Add(4); list.Add(4); list.Add(5); list.Add(4); list.Add(6); - Assert.IsFalse(list.Remove(2)); - Assert.IsTrue(list.Check()); - Assert.IsTrue(list.Remove(4)); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 4, 5, 6)); - Assert.AreEqual(6, list.RemoveLast()); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 4, 5)); + Assert.Multiple(() => + { + Assert.That(list.Remove(2), Is.False); + Assert.That(list.Check(), Is.True); + Assert.That(list.Remove(4), Is.True); + }); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 4, 5, 6), Is.True); + Assert.That(list.RemoveLast(), Is.EqualTo(6)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 4, 5), Is.True); list.Add(7); - Assert.AreEqual(4, list.RemoveFirst()); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 5, 7)); + Assert.Multiple(() => + { + Assert.That(list.RemoveFirst(), Is.EqualTo(4)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 5, 7), Is.True); + }); list.FIFO = true; list.Clear(); list.Add(4); list.Add(4); list.Add(5); list.Add(4); list.Add(6); - Assert.IsFalse(list.Remove(2)); - Assert.IsTrue(list.Check()); - Assert.IsTrue(list.Remove(4)); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 5, 4, 6)); - Assert.AreEqual(6, list.RemoveLast()); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 5, 4)); + Assert.That(list.Remove(2), Is.False); + Assert.That(list.Check(), Is.True); + Assert.That(list.Remove(4), Is.True); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 5, 4, 6), Is.True); + Assert.That(list.RemoveLast(), Is.EqualTo(6)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 5, 4), Is.True); list.Add(7); - Assert.AreEqual(4, list.RemoveFirst()); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 5, 4, 7)); + Assert.Multiple(() => + { + Assert.That(list.RemoveFirst(), Is.EqualTo(4)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 5, 4, 7), Is.True); + }); } @@ -1331,12 +1415,12 @@ public void Clear() { list.Add(7); list.Add(7); list.Clear(); - Assert.IsTrue(list.IsEmpty); + Assert.That(list.IsEmpty, Is.True); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } } @@ -1348,7 +1432,7 @@ namespace Indexed [TestFixture] public class Searching { - private IIndexed dit; + private ArrayList dit; [SetUp] @@ -1361,30 +1445,36 @@ public void Init() [Test] public void IndexOf() { - Assert.AreEqual(~0, dit.IndexOf(6)); + Assert.That(dit.IndexOf(6), Is.EqualTo(~0)); dit.Add(7); - Assert.AreEqual(~1, dit.IndexOf(6)); - Assert.AreEqual(~1, dit.LastIndexOf(6)); - Assert.AreEqual(0, dit.IndexOf(7)); + Assert.Multiple(() => + { + Assert.That(dit.IndexOf(6), Is.EqualTo(~1)); + Assert.That(dit.LastIndexOf(6), Is.EqualTo(~1)); + Assert.That(dit.IndexOf(7), Is.EqualTo(0)); + }); dit.Add(5); dit.Add(7); dit.Add(8); dit.Add(7); - Assert.AreEqual(~5, dit.IndexOf(6)); - Assert.AreEqual(0, dit.IndexOf(7)); - Assert.AreEqual(4, dit.LastIndexOf(7)); - Assert.AreEqual(3, dit.IndexOf(8)); - Assert.AreEqual(1, dit.LastIndexOf(5)); + Assert.Multiple(() => + { + Assert.That(dit.IndexOf(6), Is.EqualTo(~5)); + Assert.That(dit.IndexOf(7), Is.EqualTo(0)); + Assert.That(dit.LastIndexOf(7), Is.EqualTo(4)); + Assert.That(dit.IndexOf(8), Is.EqualTo(3)); + Assert.That(dit.LastIndexOf(5), Is.EqualTo(1)); + }); } [TearDown] public void Dispose() { - dit = null; + dit.Dispose(); } } [TestFixture] public class Removing { - private IIndexed dit; + private ArrayList dit; [SetUp] @@ -1398,15 +1488,18 @@ public void Init() public void RemoveAt() { dit.Add(5); dit.Add(7); dit.Add(9); dit.Add(1); dit.Add(2); - Assert.AreEqual(7, dit.RemoveAt(1)); - Assert.IsTrue(((ArrayList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 5, 9, 1, 2)); - Assert.AreEqual(5, dit.RemoveAt(0)); - Assert.IsTrue(((ArrayList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 9, 1, 2)); - Assert.AreEqual(2, dit.RemoveAt(2)); - Assert.IsTrue(((ArrayList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 9, 1)); + Assert.Multiple(() => + { + Assert.That(dit.RemoveAt(1), Is.EqualTo(7)); + Assert.That(((ArrayList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 5, 9, 1, 2), Is.True); + Assert.That(dit.RemoveAt(0), Is.EqualTo(5)); + }); + Assert.That(((ArrayList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 9, 1, 2), Is.True); + Assert.That(dit.RemoveAt(2), Is.EqualTo(2)); + Assert.That(((ArrayList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 9, 1), Is.True); } @@ -1437,31 +1530,49 @@ public void RemoveInterval() dit.RemoveInterval(0, 0); dit.Add(10); dit.Add(20); dit.Add(30); dit.Add(40); dit.Add(50); dit.Add(60); dit.RemoveInterval(3, 0); - Assert.IsTrue(((ArrayList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 10, 20, 30, 40, 50, 60)); + Assert.Multiple(() => + { + Assert.That(((ArrayList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 10, 20, 30, 40, 50, 60), Is.True); + }); dit.RemoveInterval(3, 1); - Assert.IsTrue(((ArrayList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 10, 20, 30, 50, 60)); + Assert.Multiple(() => + { + Assert.That(((ArrayList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 10, 20, 30, 50, 60), Is.True); + }); dit.RemoveInterval(1, 3); - Assert.IsTrue(((ArrayList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 10, 60)); + Assert.Multiple(() => + { + Assert.That(((ArrayList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 10, 60), Is.True); + }); dit.RemoveInterval(0, 2); - Assert.IsTrue(((ArrayList)dit).Check()); - Assert.IsTrue(IC.Eq(dit)); + Assert.Multiple(() => + { + Assert.That(((ArrayList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit), Is.True); + }); dit.Add(10); dit.Add(20); dit.Add(30); dit.Add(40); dit.Add(50); dit.Add(60); dit.RemoveInterval(0, 2); - Assert.IsTrue(((ArrayList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 30, 40, 50, 60)); + Assert.Multiple(() => + { + Assert.That(((ArrayList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 30, 40, 50, 60), Is.True); + }); dit.RemoveInterval(2, 2); - Assert.IsTrue(((ArrayList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 30, 40)); + Assert.Multiple(() => + { + Assert.That(((ArrayList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 30, 40), Is.True); + }); } [TearDown] public void Dispose() { - dit = null; + dit.Dispose(); } } } @@ -1479,7 +1590,7 @@ public class Searching [TearDown] - public void Dispose() { lst = null; } + public void Dispose() { lst.Dispose(); } [Test] @@ -1504,11 +1615,17 @@ public void LastBad() public void FirstLast() { lst.Add(19); - Assert.AreEqual(19, lst.First); - Assert.AreEqual(19, lst.Last); + Assert.Multiple(() => + { + Assert.That(lst.First, Is.EqualTo(19)); + Assert.That(lst.Last, Is.EqualTo(19)); + }); lst.Add(34); lst.InsertFirst(12); - Assert.AreEqual(12, lst.First); - Assert.AreEqual(34, lst.Last); + Assert.Multiple(() => + { + Assert.That(lst.First, Is.EqualTo(12)); + Assert.That(lst.Last, Is.EqualTo(34)); + }); } @@ -1516,12 +1633,12 @@ public void FirstLast() public void This() { lst.Add(34); - Assert.AreEqual(34, lst[0]); + Assert.That(lst[0], Is.EqualTo(34)); lst[0] = 56; - Assert.AreEqual(56, lst.First); + Assert.That(lst.First, Is.EqualTo(56)); lst.Add(7); lst.Add(7); lst.Add(7); lst.Add(7); lst[0] = 45; lst[2] = 78; lst[4] = 101; - Assert.IsTrue(IC.Eq(lst, 45, 7, 78, 7, 101)); + Assert.That(IC.Eq(lst, 45, 7, 78, 7, 101), Is.True); } @@ -1594,61 +1711,64 @@ public class Inserting { private IList lst; - [SetUp] public void Init() { lst = new ArrayList(); } - [TearDown] - public void Dispose() { lst = null; } - + public void Dispose() { lst.Dispose(); } [Test] public void Insert() { lst.Insert(0, 5); - Assert.IsTrue(IC.Eq(lst, 5)); + Assert.That(IC.Eq(lst, 5), Is.True); lst.Insert(0, 7); - Assert.IsTrue(IC.Eq(lst, 7, 5)); + Assert.That(IC.Eq(lst, 7, 5), Is.True); lst.Insert(1, 4); - Assert.IsTrue(IC.Eq(lst, 7, 4, 5)); + Assert.That(IC.Eq(lst, 7, 4, 5), Is.True); lst.Insert(3, 2); - Assert.IsTrue(IC.Eq(lst, 7, 4, 5, 2)); + Assert.That(IC.Eq(lst, 7, 4, 5, 2), Is.True); } [Test] public void InsertDuplicate() { lst.Insert(0, 5); - Assert.IsTrue(IC.Eq(lst, 5)); + Assert.That(IC.Eq(lst, 5), Is.True); lst.Insert(0, 7); - Assert.IsTrue(IC.Eq(lst, 7, 5)); + Assert.That(IC.Eq(lst, 7, 5), Is.True); lst.Insert(1, 5); - Assert.IsTrue(IC.Eq(lst, 7, 5, 5)); + Assert.That(IC.Eq(lst, 7, 5, 5), Is.True); } [Test] public void InsertAllDuplicate1() { lst.Insert(0, 3); - Assert.IsTrue(IC.Eq(lst, 3)); + Assert.That(IC.Eq(lst, 3), Is.True); lst.Insert(0, 7); - Assert.IsTrue(IC.Eq(lst, 7, 3)); - lst.InsertAll(1, new int[] { 1, 2, 3, 4 }); - Assert.IsTrue(IC.Eq(lst, 7, 1, 2, 3, 4, 3)); - Assert.IsTrue(lst.Check()); + Assert.That(IC.Eq(lst, 7, 3), Is.True); + lst.InsertAll(1, [1, 2, 3, 4]); + Assert.Multiple(() => + { + Assert.That(IC.Eq(lst, 7, 1, 2, 3, 4, 3), Is.True); + Assert.That(lst.Check(), Is.True); + }); } [Test] public void InsertAllDuplicate2() { lst.Insert(0, 3); - Assert.IsTrue(IC.Eq(lst, 3)); + Assert.That(IC.Eq(lst, 3), Is.True); lst.Insert(0, 7); - Assert.IsTrue(IC.Eq(lst, 7, 3)); - lst.InsertAll(1, new int[] { 5, 6, 5, 8 }); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 5, 6, 5, 8, 3)); + Assert.That(IC.Eq(lst, 7, 3), Is.True); + lst.InsertAll(1, [5, 6, 5, 8]); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 5, 6, 5, 8, 3), Is.True); + }); } @@ -1676,15 +1796,19 @@ public void FIFO() { lst.Add(2 * i); } - Assert.IsFalse(lst.FIFO); - Assert.AreEqual(12, lst.Remove()); - Assert.AreEqual(10, lst.Remove()); + + Assert.Multiple(() => + { + Assert.That(lst.FIFO, Is.False); + Assert.That(lst.Remove(), Is.EqualTo(12)); + }); + Assert.That(lst.Remove(), Is.EqualTo(10)); lst.FIFO = true; - Assert.AreEqual(0, lst.Remove()); - Assert.AreEqual(2, lst.Remove()); + Assert.That(lst.Remove(), Is.EqualTo(0)); + Assert.That(lst.Remove(), Is.EqualTo(2)); lst.FIFO = false; - Assert.AreEqual(8, lst.Remove()); - Assert.AreEqual(6, lst.Remove()); + Assert.That(lst.Remove(), Is.EqualTo(8)); + Assert.That(lst.Remove(), Is.EqualTo(6)); } [Test] @@ -1698,7 +1822,7 @@ public void InsertFirstLast() lst.InsertLast(25); lst.InsertFirst(34); lst.InsertLast(55); - Assert.IsTrue(IC.Eq(lst, 34, 24, 14, 4, 5, 15, 25, 55)); + Assert.That(IC.Eq(lst, 34, 24, 14, 4, 5, 15, 25, 55), Is.True); } @@ -1710,14 +1834,23 @@ public void InsertFirst() lst.Add(2); lst.Add(5); lst.ViewOf(2).InsertFirst(7); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 2, 3, 2, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 2, 3, 2, 5), Is.True); + }); lst.ViewOf(3).InsertFirst(8); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 2, 8, 3, 2, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 2, 8, 3, 2, 5), Is.True); + }); lst.ViewOf(5).InsertFirst(9); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 2, 8, 3, 2, 9, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 2, 8, 3, 2, 9, 5), Is.True); + }); } [Test] @@ -1729,14 +1862,23 @@ public void InsertAfter() lst.Add(2); lst.Add(5); lst.LastViewOf(2).InsertLast(7); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 1, 2, 3, 2, 7, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 1, 2, 3, 2, 7, 5), Is.True); + }); lst.LastViewOf(1).InsertLast(8); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 1, 8, 2, 3, 2, 7, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 1, 8, 2, 3, 2, 7, 5), Is.True); + }); lst.LastViewOf(5).InsertLast(9); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 1, 8, 2, 3, 2, 7, 5, 9)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 1, 8, 2, 3, 2, 7, 5, 9), Is.True); + }); } [Test] @@ -1750,14 +1892,23 @@ public void InsertAll() IList lst2 = new ArrayList() { 7, 8, 9 }; lst.InsertAll(0, lst2); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 1, 2, 3, 4)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 1, 2, 3, 4), Is.True); + }); lst.InsertAll(7, lst2); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 1, 2, 3, 4, 7, 8, 9)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 1, 2, 3, 4, 7, 8, 9), Is.True); + }); lst.InsertAll(5, lst2); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 1, 2, 7, 8, 9, 3, 4, 7, 8, 9)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 1, 2, 7, 8, 9, 3, 4, 7, 8, 9), Is.True); + }); } @@ -1767,18 +1918,24 @@ public void Map() string m(int i) { return "<<" + i + ">>"; } IList r = lst.Map(m); - Assert.IsTrue(r.Check()); - Assert.IsTrue(r.IsEmpty); + Assert.Multiple(() => + { + Assert.That(r.Check(), Is.True); + Assert.That(r.IsEmpty, Is.True); + }); lst.Add(1); lst.Add(2); lst.Add(3); lst.Add(4); r = lst.Map(m); - Assert.IsTrue(r.Check()); - Assert.AreEqual(4, r.Count); + Assert.Multiple(() => + { + Assert.That(r.Check(), Is.True); + Assert.That(r, Has.Count.EqualTo(4)); + }); for (int i = 0; i < 4; i++) { - Assert.AreEqual("<<" + (i + 1) + ">>", r[i]); + Assert.That(r[i], Is.EqualTo("<<" + (i + 1) + ">>")); } } @@ -1853,11 +2010,14 @@ public void RemoveFirstLast() lst.Add(2); lst.Add(3); lst.Add(4); - Assert.AreEqual(1, lst.RemoveFirst()); - Assert.AreEqual(4, lst.RemoveLast()); - Assert.AreEqual(2, lst.RemoveFirst()); - Assert.AreEqual(3, lst.RemoveLast()); - Assert.IsTrue(lst.IsEmpty); + Assert.Multiple(() => + { + Assert.That(lst.RemoveFirst(), Is.EqualTo(1)); + Assert.That(lst.RemoveLast(), Is.EqualTo(4)); + }); + Assert.That(lst.RemoveFirst(), Is.EqualTo(2)); + Assert.That(lst.RemoveLast(), Is.EqualTo(3)); + Assert.That(lst.IsEmpty, Is.True); } [Test] @@ -1869,20 +2029,35 @@ public void Reverse() } lst.Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0), Is.True); + }); lst.View(0, 3).Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0), Is.True); + }); lst.View(7, 0).Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0), Is.True); + }); lst.View(7, 3).Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2), Is.True); + }); lst.View(5, 1).Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2), Is.True); + }); } @@ -1901,102 +2076,126 @@ public void BadReverse() [TestFixture] public class Combined { - private IList> lst; + private IList> lst; [SetUp] public void Init() { - lst = new ArrayList>(new KeyValuePairEqualityComparer()); + lst = new ArrayList>(new KeyValuePairEqualityComparer()); for (int i = 0; i < 10; i++) { - lst.Add(new System.Collections.Generic.KeyValuePair(i, i + 30)); + lst.Add(new SCG.KeyValuePair(i, i + 30)); } } [TearDown] - public void Dispose() { lst = null; } + public void Dispose() { lst.Dispose(); } [Test] public void Find() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); - Assert.IsTrue(lst.Find(ref p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); + System.Collections.Generic.KeyValuePair p = new(3, 78); + Assert.Multiple(() => + { + Assert.That(lst.Find(ref p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Find(ref p)); + Assert.That(lst.Find(ref p), Is.False); } [Test] public void FindOrAdd() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + System.Collections.Generic.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.FindOrAdd(ref p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); + Assert.Multiple(() => + { + Assert.That(lst.FindOrAdd(ref p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); p = new System.Collections.Generic.KeyValuePair(13, 79); - Assert.IsFalse(lst.FindOrAdd(ref p)); - Assert.AreEqual(13, lst[10].Key); - Assert.AreEqual(79, lst[10].Value); + Assert.Multiple(() => + { + Assert.That(lst.FindOrAdd(ref p), Is.False); + Assert.That(lst[10].Key, Is.EqualTo(13)); + Assert.That(lst[10].Value, Is.EqualTo(79)); + }); } [Test] public void Update() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + System.Collections.Generic.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Update(p)); - Assert.AreEqual(3, lst[3].Key); - Assert.AreEqual(78, lst[3].Value); + Assert.Multiple(() => + { + Assert.That(lst.Update(p), Is.True); + Assert.That(lst[3].Key, Is.EqualTo(3)); + Assert.That(lst[3].Value, Is.EqualTo(78)); + }); p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Update(p)); + Assert.That(lst.Update(p), Is.False); } [Test] public void UpdateOrAdd1() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + System.Collections.Generic.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.UpdateOrAdd(p)); - Assert.AreEqual(3, lst[3].Key); - Assert.AreEqual(78, lst[3].Value); + Assert.Multiple(() => + { + Assert.That(lst.UpdateOrAdd(p), Is.True); + Assert.That(lst[3].Key, Is.EqualTo(3)); + Assert.That(lst[3].Value, Is.EqualTo(78)); + }); p = new System.Collections.Generic.KeyValuePair(13, 79); - Assert.IsFalse(lst.UpdateOrAdd(p)); - Assert.AreEqual(13, lst[10].Key); - Assert.AreEqual(79, lst[10].Value); + Assert.Multiple(() => + { + Assert.That(lst.UpdateOrAdd(p), Is.False); + Assert.That(lst[10].Key, Is.EqualTo(13)); + Assert.That(lst[10].Value, Is.EqualTo(79)); + }); } [Test] public void UpdateOrAdd2() { - ICollection coll = new ArrayList(); + ICollection coll = new ArrayList(); // s1 and s2 are distinct objects but contain the same text: - String s1 = "abc", s2 = ("def" + s1).Substring(3); - Assert.IsFalse(coll.UpdateOrAdd(s1, out string old)); - Assert.AreEqual(null, old); - Assert.IsTrue(coll.UpdateOrAdd(s2, out old)); - Assert.IsTrue(Object.ReferenceEquals(s1, old)); - Assert.IsFalse(Object.ReferenceEquals(s2, old)); + string s1 = "abc", s2 = ("def" + s1).Substring(3); + Assert.Multiple(() => + { + Assert.That(coll.UpdateOrAdd(s1, out string old), Is.False); + Assert.That(old, Is.EqualTo(null)); + Assert.That(coll.UpdateOrAdd(s2, out old), Is.True); + Assert.That(ReferenceEquals(s1, old), Is.True); + Assert.That(ReferenceEquals(s2, old), Is.False); + }); } [Test] public void RemoveWithReturn() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + System.Collections.Generic.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Remove(p, out p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); - Assert.AreEqual(4, lst[3].Key); - Assert.AreEqual(34, lst[3].Value); + Assert.Multiple(() => + { + Assert.That(lst.Remove(p, out p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + Assert.That(lst[3].Key, Is.EqualTo(4)); + Assert.That(lst[3].Value, Is.EqualTo(34)); + }); p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Remove(p, out _)); + Assert.That(lst.Remove(p, out _), Is.False); } } @@ -2012,18 +2211,21 @@ public class SortingTests [TearDown] - public void Dispose() { lst = null; } + public void Dispose() { lst.Dispose(); } [Test] public void Sort() { lst.Add(5); lst.Add(6); lst.Add(5); lst.Add(7); lst.Add(3); - Assert.IsFalse(lst.IsSorted(new IC())); + Assert.That(lst.IsSorted(new IC()), Is.False); lst.Sort(new IC()); - Assert.IsTrue(lst.IsSorted()); - Assert.IsTrue(lst.IsSorted(new IC())); - Assert.IsTrue(IC.Eq(lst, 3, 5, 5, 6, 7)); + Assert.Multiple(() => + { + Assert.That(lst.IsSorted(), Is.True); + Assert.That(lst.IsSorted(new IC()), Is.True); + Assert.That(IC.Eq(lst, 3, 5, 5, 6, 7), Is.True); + }); } @@ -2040,33 +2242,54 @@ public void Stability() lst2.Add(new System.Collections.Generic.KeyValuePair(3, "e")); lst2.Add(new System.Collections.Generic.KeyValuePair(4, "f")); lst2.Add(new System.Collections.Generic.KeyValuePair(5, "handle")); - Assert.IsFalse(lst2.IsSorted(c)); + Assert.That(lst2.IsSorted(c), Is.False); lst2.Sort(c); - Assert.IsTrue(lst2.IsSorted(c)); + Assert.That(lst2.IsSorted(c), Is.True); System.Collections.Generic.KeyValuePair p = lst2.RemoveFirst(); - Assert.AreEqual(3, p.Key); - Assert.AreEqual("e", p.Value); + Assert.Multiple(() => + { + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo("e")); + }); p = lst2.RemoveFirst(); - Assert.AreEqual(4, p.Key); - Assert.AreEqual("d", p.Value); + Assert.Multiple(() => + { + Assert.That(p.Key, Is.EqualTo(4)); + Assert.That(p.Value, Is.EqualTo("d")); + }); p = lst2.RemoveFirst(); - Assert.AreEqual(4, p.Key); - Assert.AreEqual("f", p.Value); + Assert.Multiple(() => + { + Assert.That(p.Key, Is.EqualTo(4)); + Assert.That(p.Value, Is.EqualTo("f")); + }); p = lst2.RemoveFirst(); - Assert.AreEqual(5, p.Key); - Assert.AreEqual("a", p.Value); + Assert.Multiple(() => + { + Assert.That(p.Key, Is.EqualTo(5)); + Assert.That(p.Value, Is.EqualTo("a")); + }); p = lst2.RemoveFirst(); - Assert.AreEqual(5, p.Key); - Assert.AreEqual("b", p.Value); + Assert.Multiple(() => + { + Assert.That(p.Key, Is.EqualTo(5)); + Assert.That(p.Value, Is.EqualTo("b")); + }); p = lst2.RemoveFirst(); - Assert.AreEqual(5, p.Key); - Assert.AreEqual("handle", p.Value); + Assert.Multiple(() => + { + Assert.That(p.Key, Is.EqualTo(5)); + Assert.That(p.Value, Is.EqualTo("handle")); + }); p = lst2.RemoveFirst(); - Assert.AreEqual(6, p.Key); - Assert.AreEqual("c", p.Value); - Assert.IsTrue(lst2.IsEmpty); + Assert.Multiple(() => + { + Assert.That(p.Key, Is.EqualTo(6)); + Assert.That(p.Value, Is.EqualTo("c")); + Assert.That(lst2.IsEmpty, Is.True); + }); } } @@ -2081,7 +2304,7 @@ public class ShuffleTests [TearDown] - public void Dispose() { lst = null; } + public void Dispose() { lst.Dispose(); } [Test] @@ -2091,10 +2314,10 @@ public void Shuffle() for (int i = 0; i < 100; i++) { lst.Shuffle(new C5Random(i + 1)); - Assert.IsTrue(lst.Check(), "Check " + i); + Assert.That(lst.Check(), Is.True, "Check " + i); int[] lst2 = lst.ToArray(); Sorting.IntroSort(lst2); - Assert.IsTrue(IC.Eq(lst2, 3, 5, 5, 6, 7), "Contents " + i); + Assert.That(IC.Eq(lst2, 3, 5, 5, 6, 7), Is.True, "Contents " + i); } } } @@ -2107,7 +2330,7 @@ namespace IStackQueue [TestFixture] public class Stack { - private IStack list; + private ArrayList list; [SetUp] @@ -2122,11 +2345,11 @@ public void Normal() list.Push(7); list.Push(8); list.Push(9); - Assert.AreEqual(9, list.Pop()); - Assert.AreEqual(8, list.Pop()); - Assert.AreEqual(7, list.Pop()); - Assert.AreEqual(5, list.Pop()); - Assert.AreEqual(7, list.Pop()); + Assert.That(list.Pop(), Is.EqualTo(9)); + Assert.That(list.Pop(), Is.EqualTo(8)); + Assert.That(list.Pop(), Is.EqualTo(7)); + Assert.That(list.Pop(), Is.EqualTo(5)); + Assert.That(list.Pop(), Is.EqualTo(7)); } @@ -2134,7 +2357,7 @@ public void Normal() public void PopEmpty() { list.Push(5); - Assert.AreEqual(5, list.Pop()); + Assert.That(list.Pop(), Is.EqualTo(5)); Assert.Throws(() => list.Pop()); } @@ -2142,14 +2365,14 @@ public void PopEmpty() [TearDown] public void Dispose() { - list = null; + list.Dispose(); } } [TestFixture] public class Queue { - private IQueue list; + private ArrayList list; [SetUp] public void Init() { list = new ArrayList(); } @@ -2162,11 +2385,11 @@ public void Normal() list.Enqueue(7); list.Enqueue(8); list.Enqueue(9); - Assert.AreEqual(7, list.Dequeue()); - Assert.AreEqual(5, list.Dequeue()); - Assert.AreEqual(7, list.Dequeue()); - Assert.AreEqual(8, list.Dequeue()); - Assert.AreEqual(9, list.Dequeue()); + Assert.That(list.Dequeue(), Is.EqualTo(7)); + Assert.That(list.Dequeue(), Is.EqualTo(5)); + Assert.That(list.Dequeue(), Is.EqualTo(7)); + Assert.That(list.Dequeue(), Is.EqualTo(8)); + Assert.That(list.Dequeue(), Is.EqualTo(9)); } @@ -2174,14 +2397,14 @@ public void Normal() public void DeQueueEmpty() { list.Enqueue(5); - Assert.AreEqual(5, list.Dequeue()); + Assert.That(list.Dequeue(), Is.EqualTo(5)); Assert.Throws(() => list.Dequeue()); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } } @@ -2199,7 +2422,7 @@ public class Range [TearDown] - public void Dispose() { lst = null; } + public void Dispose() { lst.Dispose(); } [Test] @@ -2211,9 +2434,12 @@ public void GetRange() lst.Add(i); } - Assert.IsTrue(IC.Eq(lst[0, 3], 0, 1, 2)); - Assert.IsTrue(IC.Eq(lst[3, 4], 3, 4, 5, 6)); - Assert.IsTrue(IC.Eq(lst[6, 4], 6, 7, 8, 9)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(lst[0, 3], 0, 1, 2), Is.True); + Assert.That(IC.Eq(lst[3, 4], 3, 4, 5, 6), Is.True); + Assert.That(IC.Eq(lst[6, 4], 6, 7, 8, 9), Is.True); + }); } @@ -2234,10 +2460,13 @@ public void Backwards() lst.Add(i); } - Assert.IsTrue(IC.Eq(lst.Backwards(), 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); - Assert.IsTrue(IC.Eq(lst[0, 4].Backwards(), 3, 2, 1, 0)); - Assert.IsTrue(IC.Eq(lst[3, 4].Backwards(), 6, 5, 4, 3)); - Assert.IsTrue(IC.Eq(lst[6, 4].Backwards(), 9, 8, 7, 6)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(lst.Backwards(), 9, 8, 7, 6, 5, 4, 3, 2, 1, 0), Is.True); + Assert.That(IC.Eq(lst[0, 4].Backwards(), 3, 2, 1, 0), Is.True); + Assert.That(IC.Eq(lst[3, 4].Backwards(), 6, 5, 4, 3), Is.True); + Assert.That(IC.Eq(lst[6, 4].Backwards(), 9, 8, 7, 6), Is.True); + }); } @@ -2249,13 +2478,19 @@ public void DirectionAndCount() lst.Add(i); } - Assert.AreEqual(Direction.Forwards, lst.Direction); - Assert.AreEqual(Direction.Forwards, lst[3, 4].Direction); - Assert.AreEqual(Direction.Backwards, lst[3, 4].Backwards().Direction); - Assert.AreEqual(Direction.Backwards, lst.Backwards().Direction); - Assert.AreEqual(4, lst[3, 4].Count); - Assert.AreEqual(4, lst[3, 4].Backwards().Count); - Assert.AreEqual(10, lst.Backwards().Count); + Assert.Multiple(() => + { + Assert.That(lst.Direction, Is.EqualTo(Direction.Forwards)); + Assert.That(lst[3, 4].Direction, Is.EqualTo(Direction.Forwards)); + Assert.That(lst[3, 4].Backwards().Direction, Is.EqualTo(Direction.Backwards)); + Assert.That(lst.Backwards().Direction, Is.EqualTo(Direction.Backwards)); + Assert.That(lst[3, 4], Has.Count.EqualTo(4)); + }); + Assert.Multiple(() => + { + Assert.That(lst[3, 4].Backwards(), Has.Count.EqualTo(4)); + Assert.That(lst.Backwards(), Has.Count.EqualTo(10)); + }); } @@ -2296,13 +2531,17 @@ public void Init() [TearDown] public void Dispose() { - list = view = null; + list.Dispose(); + view.Dispose(); } private void check() { - Assert.IsTrue(list.Check()); - Assert.IsTrue(view.Check()); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(view.Check(), Is.True); + }); } //static void pint(IEnumerable l) { foreach (int cell in l) Console.WriteLine(cell); } @@ -2321,8 +2560,11 @@ public void InsertPointer() check(); view.Insert(list.ViewOf(0), 11); check(); - Assert.IsTrue(IC.Eq(list, 0, 11, 1, 9, 7, 2, 10, 3, 8)); - Assert.IsTrue(IC.Eq(view, 11, 1, 9, 7, 2, 10)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 11, 1, 9, 7, 2, 10, 3, 8), Is.True); + Assert.That(IC.Eq(view, 11, 1, 9, 7, 2, 10), Is.True); + }); } [Test] @@ -2353,15 +2595,21 @@ public void InsertPointerBad4() public void Span() { IList span = list.View(1, 0).Span(list.View(2, 0)); - Assert.IsTrue(span.Check()); - Assert.AreEqual(1, span.Offset); - Assert.AreEqual(1, span.Count); + Assert.Multiple(() => + { + Assert.That(span.Check(), Is.True); + Assert.That(span.Offset, Is.EqualTo(1)); + Assert.That(span, Has.Count.EqualTo(1)); + }); span = list.View(0, 2).Span(list.View(2, 2)); - Assert.IsTrue(span.Check()); - Assert.AreEqual(0, span.Offset); - Assert.AreEqual(4, span.Count); + Assert.Multiple(() => + { + Assert.That(span.Check(), Is.True); + Assert.That(span.Offset, Is.EqualTo(0)); + Assert.That(span, Has.Count.EqualTo(4)); + }); span = list.View(3, 1).Span(list.View(1, 1)); - Assert.IsNull(span); + Assert.That(span, Is.Null); } [Test] @@ -2373,119 +2621,170 @@ public void ViewOf() } IList v = view.ViewOf(2); - Assert.IsTrue(v.Check()); - Assert.IsTrue(IC.Eq(v, 2)); - Assert.AreEqual(2, v.Offset); + Assert.Multiple(() => + { + Assert.That(v.Check(), Is.True); + Assert.That(IC.Eq(v, 2), Is.True); + Assert.That(v.Offset, Is.EqualTo(2)); + }); v = list.ViewOf(2); - Assert.IsTrue(v.Check()); - Assert.IsTrue(IC.Eq(v, 2)); - Assert.AreEqual(2, v.Offset); + Assert.Multiple(() => + { + Assert.That(v.Check(), Is.True); + Assert.That(IC.Eq(v, 2), Is.True); + Assert.That(v.Offset, Is.EqualTo(2)); + }); v = list.LastViewOf(2); - Assert.IsTrue(v.Check()); - Assert.IsTrue(IC.Eq(v, 2)); - Assert.AreEqual(6, v.Offset); + Assert.Multiple(() => + { + Assert.That(v.Check(), Is.True); + Assert.That(IC.Eq(v, 2), Is.True); + Assert.That(v.Offset, Is.EqualTo(6)); + }); } [Test] public void ArrayStuff() { - Assert.IsTrue(IC.Eq(view.ToArray(), 1, 2)); + Assert.That(IC.Eq(view.ToArray(), 1, 2), Is.True); int[] extarray = new int[5]; view.CopyTo(extarray, 2); - Assert.IsTrue(IC.Eq(extarray, 0, 0, 1, 2, 0)); + Assert.That(IC.Eq(extarray, 0, 0, 1, 2, 0), Is.True); } [Test] public void BadViewOf() { - Assert.IsNull(view.ViewOf(5)); - Assert.IsNull(view.LastViewOf(5)); - Assert.IsNull(view.ViewOf(3)); - Assert.IsNull(view.LastViewOf(3)); - Assert.IsNull(view.ViewOf(0)); - Assert.IsNull(view.LastViewOf(0)); + Assert.Multiple(() => + { + Assert.That(view.ViewOf(5), Is.Null); + Assert.That(view.LastViewOf(5), Is.Null); + Assert.That(view.ViewOf(3), Is.Null); + Assert.That(view.LastViewOf(3), Is.Null); + Assert.That(view.ViewOf(0), Is.Null); + Assert.That(view.LastViewOf(0), Is.Null); + }); } [Test] public void Add() { check(); - Assert.IsTrue(IC.Eq(list, 0, 1, 2, 3)); - Assert.IsTrue(IC.Eq(view, 1, 2)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 1, 2, 3), Is.True); + Assert.That(IC.Eq(view, 1, 2), Is.True); + }); view.InsertFirst(10); check(); - Assert.IsTrue(IC.Eq(list, 0, 10, 1, 2, 3)); - Assert.IsTrue(IC.Eq(view, 10, 1, 2)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 10, 1, 2, 3), Is.True); + Assert.That(IC.Eq(view, 10, 1, 2), Is.True); + }); view.Clear(); - Assert.IsFalse(view.IsReadOnly); - Assert.IsTrue(view.AllowsDuplicates); - Assert.IsTrue(view.IsEmpty); + Assert.Multiple(() => + { + Assert.That(view.IsReadOnly, Is.False); + Assert.That(view.AllowsDuplicates, Is.True); + Assert.That(view.IsEmpty, Is.True); + }); check(); - Assert.IsTrue(IC.Eq(list, 0, 3)); - Assert.IsTrue(IC.Eq(view)); + Assert.That(IC.Eq(list, 0, 3), Is.True); + Assert.That(IC.Eq(view), Is.True); view.Add(8); - Assert.IsFalse(view.IsEmpty); - Assert.IsTrue(view.AllowsDuplicates); - Assert.IsFalse(view.IsReadOnly); + Assert.That(view.IsEmpty, Is.False); + Assert.That(view.AllowsDuplicates, Is.True); + Assert.That(view.IsReadOnly, Is.False); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 3)); - Assert.IsTrue(IC.Eq(view, 8)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 3), Is.True); + Assert.That(IC.Eq(view, 8), Is.True); + }); view.Add(12); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 12, 3)); - Assert.IsTrue(IC.Eq(view, 8, 12)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 12, 3), Is.True); + Assert.That(IC.Eq(view, 8, 12), Is.True); + }); view./*ViewOf(12)*/InsertLast(15); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 12, 15, 3)); - Assert.IsTrue(IC.Eq(view, 8, 12, 15)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 12, 15, 3), Is.True); + Assert.That(IC.Eq(view, 8, 12, 15), Is.True); + }); view.ViewOf(12).InsertFirst(18); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 18, 12, 15, 3)); - Assert.IsTrue(IC.Eq(view, 8, 18, 12, 15)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 18, 12, 15, 3), Is.True); + Assert.That(IC.Eq(view, 8, 18, 12, 15), Is.True); + }); - ArrayList lst2 = new ArrayList { 90, 92 }; + ArrayList lst2 = new() { 90, 92 }; view.AddAll(lst2); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 18, 12, 15, 90, 92, 3)); - Assert.IsTrue(IC.Eq(view, 8, 18, 12, 15, 90, 92)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 18, 12, 15, 90, 92, 3), Is.True); + Assert.That(IC.Eq(view, 8, 18, 12, 15, 90, 92), Is.True); + }); view.InsertLast(66); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 18, 12, 15, 90, 92, 66, 3)); - Assert.IsTrue(IC.Eq(view, 8, 18, 12, 15, 90, 92, 66)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 18, 12, 15, 90, 92, 66, 3), Is.True); + Assert.That(IC.Eq(view, 8, 18, 12, 15, 90, 92, 66), Is.True); + }); } [Test] public void Bxxx() { - Assert.IsTrue(IC.Eq(view.Backwards(), 2, 1)); - Assert.AreSame(list, view.Underlying); - Assert.IsNull(list.Underlying); - Assert.AreEqual(Direction.Forwards, view.Direction); - Assert.AreEqual(Direction.Backwards, view.Backwards().Direction); - Assert.AreEqual(0, list.Offset); - Assert.AreEqual(1, view.Offset); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view.Backwards(), 2, 1), Is.True); + Assert.That(view.Underlying, Is.SameAs(list)); + Assert.That(list.Underlying, Is.Null); + Assert.That(view.Direction, Is.EqualTo(Direction.Forwards)); + Assert.That(view.Backwards().Direction, Is.EqualTo(Direction.Backwards)); + Assert.That(list.Offset, Is.EqualTo(0)); + Assert.That(view.Offset, Is.EqualTo(1)); + }); } [Test] public void Contains() { - Assert.IsTrue(view.Contains(1)); - Assert.IsFalse(view.Contains(0)); + Assert.Multiple(() => + { + Assert.That(view.Contains(1), Is.True); + Assert.That(view.Contains(0), Is.False); + }); - ArrayList lst2 = new ArrayList() { 2 }; + ArrayList lst2 = new() { 2 }; - Assert.IsTrue(view.ContainsAll(lst2)); + Assert.That(view.ContainsAll(lst2), Is.True); lst2.Add(3); - Assert.IsFalse(view.ContainsAll(lst2)); - Assert.AreEqual(Speed.Linear, view.ContainsSpeed); - Assert.AreEqual(2, view.Count); + Assert.Multiple(() => + { + Assert.That(view.ContainsAll(lst2), Is.False); + Assert.That(view.ContainsSpeed, Is.EqualTo(Speed.Linear)); + Assert.That(view, Has.Count.EqualTo(2)); + }); view.Add(1); - Assert.AreEqual(1, view.ContainsCount(2)); - Assert.AreEqual(2, view.ContainsCount(1)); - Assert.AreEqual(3, view.Count); + Assert.Multiple(() => + { + Assert.That(view.ContainsCount(2), Is.EqualTo(1)); + Assert.That(view.ContainsCount(1), Is.EqualTo(2)); + Assert.That(view, Has.Count.EqualTo(3)); + }); } @@ -2494,26 +2793,32 @@ public void CreateView() { ArrayList view2 = (ArrayList)view.View(1, 0); - Assert.AreSame(list, view2.Underlying); + Assert.That(view2.Underlying, Is.SameAs(list)); } [Test] public void FIFO() { - Assert.IsFalse(view.FIFO); + Assert.That(view.FIFO, Is.False); view.FIFO = true; view.Add(23); view.Add(24); view.Add(25); check(); - Assert.IsTrue(IC.Eq(view, 1, 2, 23, 24, 25)); - Assert.AreEqual(1, view.Remove()); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 1, 2, 23, 24, 25), Is.True); + Assert.That(view.Remove(), Is.EqualTo(1)); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 23, 24, 25)); + Assert.That(IC.Eq(view, 2, 23, 24, 25), Is.True); view.FIFO = false; - Assert.IsFalse(view.FIFO); - Assert.AreEqual(25, view.Remove()); + Assert.Multiple(() => + { + Assert.That(view.FIFO, Is.False); + Assert.That(view.Remove(), Is.EqualTo(25)); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 23, 24)); + Assert.That(IC.Eq(view, 2, 23, 24), Is.True); } @@ -2522,25 +2827,34 @@ public void MapEtc() { ArrayList dbl = (ArrayList)view.Map(new Func(delegate (int i) { return i / 10.0; })); - Assert.IsTrue(dbl.Check()); - Assert.AreEqual(0.1, dbl[0]); - Assert.AreEqual(0.2, dbl[1]); + Assert.Multiple(() => + { + Assert.That(dbl.Check(), Is.True); + Assert.That(dbl[0], Is.EqualTo(0.1)); + Assert.That(dbl[1], Is.EqualTo(0.2)); + }); for (int i = 0; i < 10; i++) { view.Add(i); } list = (ArrayList)view.FindAll(new Func(delegate (int i) { return i % 4 == 1; })); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 1, 1, 5, 9)); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 1, 1, 5, 9), Is.True); + }); } [Test] public void FL() { - Assert.AreEqual(1, view.First); - Assert.AreEqual(2, view.Last); + Assert.Multiple(() => + { + Assert.That(view.First, Is.EqualTo(1)); + Assert.That(view.Last, Is.EqualTo(2)); + }); } @@ -2556,17 +2870,17 @@ public void Indexing() view = (ArrayList)list.View(5, 7); for (int i = 0; i < 7; i++) { - Assert.AreEqual(i + 5, view[i]); + Assert.That(view[i], Is.EqualTo(i + 5)); } for (int i = 0; i < 7; i++) { - Assert.AreEqual(i, view.IndexOf(i + 5)); + Assert.That(view.IndexOf(i + 5), Is.EqualTo(i)); } for (int i = 0; i < 7; i++) { - Assert.AreEqual(i, view.LastIndexOf(i + 5)); + Assert.That(view.LastIndexOf(i + 5), Is.EqualTo(i)); } } @@ -2577,15 +2891,21 @@ public void Insert() view.Insert(0, 34); view.Insert(1, 35); view.Insert(4, 36); - Assert.IsTrue(view.Check()); - Assert.IsTrue(IC.Eq(view, 34, 35, 1, 2, 36)); + Assert.Multiple(() => + { + Assert.That(view.Check(), Is.True); + Assert.That(IC.Eq(view, 34, 35, 1, 2, 36), Is.True); + }); IList list2 = new ArrayList(); list2.AddAll(view); view.InsertAll(3, list2); - Assert.IsTrue(view.Check()); - Assert.IsTrue(IC.Eq(view, 34, 35, 1, 34, 35, 1, 2, 36, 2, 36)); + Assert.Multiple(() => + { + Assert.That(view.Check(), Is.True); + Assert.That(IC.Eq(view, 34, 35, 1, 34, 35, 1, 2, 36, 2, 36), Is.True); + }); } [Test] @@ -2611,11 +2931,14 @@ public void RangeCheck2() public void Sort() { view.Add(45); view.Add(47); view.Add(46); view.Add(48); - Assert.IsFalse(view.IsSorted(new IC())); + Assert.That(view.IsSorted(new IC()), Is.False); view.Sort(new IC()); check(); - Assert.IsTrue(IC.Eq(list, 0, 1, 2, 45, 46, 47, 48, 3)); - Assert.IsTrue(IC.Eq(view, 1, 2, 45, 46, 47, 48)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 1, 2, 45, 46, 47, 48, 3), Is.True); + Assert.That(IC.Eq(view, 1, 2, 45, 46, 47, 48), Is.True); + }); } @@ -2623,67 +2946,97 @@ public void Sort() public void Remove() { view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0); - Assert.IsTrue(IC.Eq(view, 1, 2, 1, 5, 3, 1, 3, 0)); - Assert.IsTrue(view.Remove(1)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 1, 2, 1, 5, 3, 1, 3, 0), Is.True); + Assert.That(view.Remove(1), Is.True); + }); check(); - Assert.IsTrue(IC.Eq(view, 1, 2, 1, 5, 3, 3, 0)); - Assert.IsTrue(view.Remove(1)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 1, 2, 1, 5, 3, 3, 0), Is.True); + Assert.That(view.Remove(1), Is.True); + }); check(); - Assert.IsTrue(IC.Eq(view, 1, 2, 5, 3, 3, 0)); - Assert.IsTrue(view.Remove(0)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 1, 2, 5, 3, 3, 0), Is.True); + Assert.That(view.Remove(0), Is.True); + }); check(); - Assert.IsTrue(IC.Eq(view, 1, 2, 5, 3, 3)); + Assert.That(IC.Eq(view, 1, 2, 5, 3, 3), Is.True); view.RemoveAllCopies(3); check(); - Assert.IsTrue(IC.Eq(view, 1, 2, 5)); - Assert.IsTrue(IC.Eq(list, 0, 1, 2, 5, 3)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 1, 2, 5), Is.True); + Assert.That(IC.Eq(list, 0, 1, 2, 5, 3), Is.True); + }); view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0); - Assert.IsTrue(IC.Eq(view, 1, 2, 5, 1, 5, 3, 1, 3, 0)); + Assert.That(IC.Eq(view, 1, 2, 5, 1, 5, 3, 1, 3, 0), Is.True); view.FIFO = true; view.Clear(); view.Add(1); view.Add(2); view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0); - Assert.IsTrue(IC.Eq(view, 1, 2, 1, 5, 3, 1, 3, 0)); - Assert.IsTrue(view.Remove(1)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 1, 2, 1, 5, 3, 1, 3, 0), Is.True); + Assert.That(view.Remove(1), Is.True); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 1, 5, 3, 1, 3, 0)); - Assert.IsTrue(view.Remove(1)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 2, 1, 5, 3, 1, 3, 0), Is.True); + Assert.That(view.Remove(1), Is.True); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 5, 3, 1, 3, 0)); - Assert.IsTrue(view.Remove(0)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 2, 5, 3, 1, 3, 0), Is.True); + Assert.That(view.Remove(0), Is.True); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 5, 3, 1, 3)); + Assert.That(IC.Eq(view, 2, 5, 3, 1, 3), Is.True); view.RemoveAllCopies(3); check(); - Assert.IsTrue(IC.Eq(view, 2, 5, 1)); - Assert.IsTrue(IC.Eq(list, 0, 2, 5, 1, 3)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 2, 5, 1), Is.True); + Assert.That(IC.Eq(list, 0, 2, 5, 1, 3), Is.True); + }); view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0); - Assert.IsTrue(IC.Eq(view, 2, 5, 1, 1, 5, 3, 1, 3, 0)); + Assert.That(IC.Eq(view, 2, 5, 1, 1, 5, 3, 1, 3, 0), Is.True); view.FIFO = false; - ArrayList l2 = new ArrayList() { 1, 2, 2, 3, 1 }; + ArrayList l2 = new() { 1, 2, 2, 3, 1 }; view.RemoveAll(l2); check(); - Assert.IsTrue(IC.Eq(view, 5, 5, 1, 3, 0)); + Assert.That(IC.Eq(view, 5, 5, 1, 3, 0), Is.True); view.RetainAll(l2); check(); - Assert.IsTrue(IC.Eq(view, 1, 3)); + Assert.That(IC.Eq(view, 1, 3), Is.True); view.Add(2); view.Add(4); view.Add(5); - Assert.AreEqual(1, view.RemoveAt(0)); - Assert.AreEqual(5, view.RemoveAt(3)); - Assert.AreEqual(2, view.RemoveAt(1)); + Assert.Multiple(() => + { + Assert.That(view.RemoveAt(0), Is.EqualTo(1)); + Assert.That(view.RemoveAt(3), Is.EqualTo(5)); + Assert.That(view.RemoveAt(1), Is.EqualTo(2)); + }); check(); - Assert.IsTrue(IC.Eq(view, 3, 4)); + Assert.That(IC.Eq(view, 3, 4), Is.True); view.Add(8); - Assert.AreEqual(3, view.RemoveFirst()); - Assert.AreEqual(8, view.RemoveLast()); + Assert.Multiple(() => + { + Assert.That(view.RemoveFirst(), Is.EqualTo(3)); + Assert.That(view.RemoveLast(), Is.EqualTo(8)); + }); view.Add(2); view.Add(5); view.Add(3); view.Add(1); view.RemoveInterval(1, 2); check(); - Assert.IsTrue(IC.Eq(view, 4, 3, 1)); + Assert.That(IC.Eq(view, 4, 3, 1), Is.True); } @@ -2698,10 +3051,13 @@ public void Reverse() view.View(3, 4).Reverse(); check(); - Assert.IsTrue(IC.Eq(view, 10, 11, 12, 16, 15, 14, 13, 17, 18, 19)); + Assert.That(IC.Eq(view, 10, 11, 12, 16, 15, 14, 13, 17, 18, 19), Is.True); view.Reverse(); - Assert.IsTrue(IC.Eq(view, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10)); - Assert.IsTrue(IC.Eq(list, 0, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10, 3)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10), Is.True); + Assert.That(IC.Eq(list, 0, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10, 3), Is.True); + }); } @@ -2710,21 +3066,24 @@ public void Slide() { view.Slide(1); check(); - Assert.IsTrue(IC.Eq(view, 2, 3)); + Assert.That(IC.Eq(view, 2, 3), Is.True); view.Slide(-2); check(); - Assert.IsTrue(IC.Eq(view, 0, 1)); + Assert.That(IC.Eq(view, 0, 1), Is.True); view.Slide(0, 3); check(); - Assert.IsTrue(IC.Eq(view, 0, 1, 2)); + Assert.That(IC.Eq(view, 0, 1, 2), Is.True); view.Slide(2, 1); check(); - Assert.IsTrue(IC.Eq(view, 2)); - Assert.AreEqual(view, view.Slide(-1, 0)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 2), Is.True); + Assert.That(view.Slide(-1, 0), Is.EqualTo(view)); + }); check(); - Assert.IsTrue(IC.Eq(view)); + Assert.That(IC.Eq(view), Is.True); view.Add(28); - Assert.IsTrue(IC.Eq(list, 0, 28, 1, 2, 3)); + Assert.That(IC.Eq(list, 0, 28, 1, 2, 3), Is.True); } [Test] public void Iterate() @@ -2754,21 +3113,25 @@ public void Iterate() view.Slide(-1, 2); } } - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 2, 4, 8, 666, 13, 6, 1, 666, 2, 666, 7)); + + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 2, 4, 8, 666, 13, 6, 1, 666, 2, 666, 7), Is.True); + }); } [Test] public void SyncRoot() { - Assert.AreSame(((System.Collections.IList)view).SyncRoot, ((System.Collections.IList)list).SyncRoot); + Assert.That(((System.Collections.IList)list).SyncRoot, Is.SameAs(((System.Collections.IList)view).SyncRoot)); } } [TestFixture] public class MulipleViews { - private IList list; + private ArrayList list; private IList[][] views; [SetUp] public void Init() @@ -2792,36 +3155,42 @@ public void Init() [TearDown] public void Dispose() { - list = null; + list.Dispose(); views = null; } [Test] public void Insert() { - Assert.IsTrue(list.Check(), "list check before insert"); + Assert.That(list.Check(), Is.True, "list check before insert"); list.Insert(3, 777); - Assert.IsTrue(list.Check(), "list check after insert"); + Assert.That(list.Check(), Is.True, "list check after insert"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i < 3 && i + j > 3 ? j + 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i < 3 || (i == 3 && j == 0) ? i : i + 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i < 3 && i + j > 3 ? j + 1 : j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void RemoveAt() { - Assert.IsTrue(list.Check(), "list check before remove"); + Assert.That(list.Check(), Is.True, "list check before remove"); list.RemoveAt(3); - Assert.IsTrue(list.Check(), "list check after remove"); + Assert.That(list.Check(), Is.True, "list check after remove"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i <= 3 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i <= 3 && i + j > 3 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i <= 3 ? i : i - 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i <= 3 && i + j > 3 ? j - 1 : j), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2829,15 +3198,18 @@ public void RemoveAt() [Test] public void RemoveInterval() { - Assert.IsTrue(list.Check(), "list check before remove"); + Assert.That(list.Check(), Is.True, "list check before remove"); list.RemoveInterval(3, 2); - Assert.IsTrue(list.Check(), "list check after remove"); + Assert.That(list.Check(), Is.True, "list check after remove"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i <= 3 ? i : i <= 5 ? 3 : i - 2, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(j == 0 ? 0 : i <= 3 && i + j > 4 ? j - 2 : i > 4 || i + j <= 3 ? j : j - 1, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i <= 3 ? i : i <= 5 ? 3 : i - 2), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(j == 0 ? 0 : i <= 3 && i + j > 4 ? j - 2 : i > 4 || i + j <= 3 ? j : j - 1), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2846,75 +3218,90 @@ public void RemoveInterval() [Test] public void InsertAtEnd() { - Assert.IsTrue(list.Check(), "list check before insert"); + Assert.That(list.Check(), Is.True, "list check before insert"); list.InsertLast(777); - Assert.IsTrue(list.Check(), "list check after insert"); + Assert.That(list.Check(), Is.True, "list check after insert"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void RemoveAtEnd() { - Assert.IsTrue(list.Check(), "list check before remove"); + Assert.That(list.Check(), Is.True, "list check before remove"); list.RemoveAt(5); - Assert.IsTrue(list.Check(), "list check after remove"); + Assert.That(list.Check(), Is.True, "list check after remove"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i <= 5 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i <= 5 && i + j > 5 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i <= 5 ? i : i - 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i <= 5 && i + j > 5 ? j - 1 : j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void InsertAtStart() { - Assert.IsTrue(list.Check(), "list check before insert"); + Assert.That(list.Check(), Is.True, "list check before insert"); list.Insert(0, 777); - Assert.IsTrue(list.Check(), "list check after insert"); + Assert.That(list.Check(), Is.True, "list check after insert"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i == 0 && j == 0 ? 0 : i + 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i == 0 && j == 0 ? 0 : i + 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void RemoveAtStart() { - Assert.IsTrue(list.Check(), "list check before remove"); + Assert.That(list.Check(), Is.True, "list check before remove"); list.RemoveAt(0); - Assert.IsTrue(list.Check(), "list check after remove"); + Assert.That(list.Check(), Is.True, "list check after remove"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i == 0 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i == 0 && j > 0 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i == 0 ? i : i - 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i == 0 && j > 0 ? j - 1 : j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void Clear() { - Assert.IsTrue(list.Check(), "list check before clear"); + Assert.That(list.Check(), Is.True, "list check before clear"); views[2][3].Clear(); - Assert.IsTrue(list.Check(), "list check after clear"); + Assert.That(list.Check(), Is.True, "list check after clear"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i < 2 ? i : i < 6 ? 2 : i - 3, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(s(i, j), views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i < 2 ? i : i < 6 ? 2 : i - 3), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(s(i, j)), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2947,17 +3334,20 @@ private int s(int i, int j) [Test] public void InsertAll() { - ArrayList list2 = new ArrayList(); + ArrayList list2 = new(); for (int i = 0; i < 5; i++) { list2.Add(100 + i); } - Assert.IsTrue(list.Check(), "list check before insertAll"); + Assert.That(list.Check(), Is.True, "list check before insertAll"); list.InsertAll(3, list2); - Assert.IsTrue(list.Check(), "list check after insertAll"); + Assert.That(list.Check(), Is.True, "list check after insertAll"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 5, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i < 3 && i + j > 3 ? j + 5 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i < 3 || (i == 3 && j == 0) ? i : i + 5), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i < 3 && i + j > 3 ? j + 5 : j), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2965,17 +3355,20 @@ public void InsertAll() [Test] public void AddAll() { - ArrayList list2 = new ArrayList(); + ArrayList list2 = new(); for (int i = 0; i < 5; i++) { list2.Add(100 + i); } - Assert.IsTrue(list.Check(), "list check before AddAll"); + Assert.That(list.Check(), Is.True, "list check before AddAll"); list.View(1, 2).AddAll(list2); - Assert.IsTrue(list.Check(), "list check after AddAll"); + Assert.That(list.Check(), Is.True, "list check after AddAll"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 5, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i < 3 && i + j > 3 ? j + 5 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i < 3 || (i == 3 && j == 0) ? i : i + 5), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i < 3 && i + j > 3 ? j + 5 : j), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2983,7 +3376,7 @@ public void AddAll() [Test] public void RemoveAll1() { - ArrayList list2 = new ArrayList() { 1, 3, 4 }; + ArrayList list2 = new() { 1, 3, 4 }; for (int i = 0; i < 7; i++) { @@ -2997,150 +3390,156 @@ public void RemoveAll1() _ = (ArrayList)list.View(i, j); list.RemoveAll(list2); - Assert.IsTrue(list.Check(), "list check after RemoveAll, i=" + i + ", j=" + j); + Assert.That(list.Check(), Is.True, "list check after RemoveAll, i=" + i + ", j=" + j); } } } [Test] public void RemoveAll2() { - ArrayList list2 = new ArrayList() { 1, 3, 4 }; - Assert.IsTrue(list.Check(), "list check before RemoveAll"); + ArrayList list2 = new() { 1, 3, 4 }; + Assert.That(list.Check(), Is.True, "list check before RemoveAll"); list.RemoveAll(list2); - Assert.AreEqual(0, views[0][0].Offset, "view [0][0] offset"); - Assert.AreEqual(0, views[0][1].Offset, "view [0][1] offset"); - Assert.AreEqual(0, views[0][2].Offset, "view [0][2] offset"); - Assert.AreEqual(0, views[0][3].Offset, "view [0][3] offset"); - Assert.AreEqual(0, views[0][4].Offset, "view [0][4] offset"); - Assert.AreEqual(0, views[0][5].Offset, "view [0][5] offset"); - Assert.AreEqual(0, views[0][6].Offset, "view [0][6] offset"); - Assert.AreEqual(1, views[1][0].Offset, "view [1][0] offset"); - Assert.AreEqual(1, views[1][1].Offset, "view [1][1] offset"); - Assert.AreEqual(1, views[1][2].Offset, "view [1][2] offset"); - Assert.AreEqual(1, views[1][3].Offset, "view [1][3] offset"); - Assert.AreEqual(1, views[1][4].Offset, "view [1][4] offset"); - Assert.AreEqual(1, views[1][5].Offset, "view [1][5] offset"); - Assert.AreEqual(1, views[2][0].Offset, "view [2][0] offset"); - Assert.AreEqual(1, views[2][1].Offset, "view [2][1] offset"); - Assert.AreEqual(1, views[2][2].Offset, "view [2][2] offset"); - Assert.AreEqual(1, views[2][3].Offset, "view [2][3] offset"); - Assert.AreEqual(1, views[2][4].Offset, "view [2][4] offset"); - Assert.AreEqual(2, views[3][0].Offset, "view [3][0] offset"); - Assert.AreEqual(2, views[3][1].Offset, "view [3][1] offset"); - Assert.AreEqual(2, views[3][2].Offset, "view [3][2] offset"); - Assert.AreEqual(2, views[3][3].Offset, "view [3][3] offset"); - Assert.AreEqual(2, views[4][0].Offset, "view [4][0] offset"); - Assert.AreEqual(2, views[4][1].Offset, "view [4][1] offset"); - Assert.AreEqual(2, views[4][2].Offset, "view [4][2] offset"); - Assert.AreEqual(2, views[5][0].Offset, "view [5][0] offset"); - Assert.AreEqual(2, views[5][1].Offset, "view [5][1] offset"); - Assert.AreEqual(3, views[6][0].Offset, "view [6][0] offset"); - - Assert.AreEqual(0, views[0][0].Count, "view [0][0] count"); - Assert.AreEqual(1, views[0][1].Count, "view [0][1] count"); - Assert.AreEqual(1, views[0][2].Count, "view [0][2] count"); - Assert.AreEqual(2, views[0][3].Count, "view [0][3] count"); - Assert.AreEqual(2, views[0][4].Count, "view [0][4] count"); - Assert.AreEqual(2, views[0][5].Count, "view [0][5] count"); - Assert.AreEqual(3, views[0][6].Count, "view [0][6] count"); - Assert.AreEqual(0, views[1][0].Count, "view [1][0] count"); - Assert.AreEqual(0, views[1][1].Count, "view [1][1] count"); - Assert.AreEqual(1, views[1][2].Count, "view [1][2] count"); - Assert.AreEqual(1, views[1][3].Count, "view [1][3] count"); - Assert.AreEqual(1, views[1][4].Count, "view [1][4] count"); - Assert.AreEqual(2, views[1][5].Count, "view [1][5] count"); - Assert.AreEqual(0, views[2][0].Count, "view [2][0] count"); - Assert.AreEqual(1, views[2][1].Count, "view [2][1] count"); - Assert.AreEqual(1, views[2][2].Count, "view [2][2] count"); - Assert.AreEqual(1, views[2][3].Count, "view [2][3] count"); - Assert.AreEqual(2, views[2][4].Count, "view [2][4] count"); - Assert.AreEqual(0, views[3][0].Count, "view [3][0] count"); - Assert.AreEqual(0, views[3][1].Count, "view [3][1] count"); - Assert.AreEqual(0, views[3][2].Count, "view [3][2] count"); - Assert.AreEqual(1, views[3][3].Count, "view [3][3] count"); - Assert.AreEqual(0, views[4][0].Count, "view [4][0] count"); - Assert.AreEqual(0, views[4][1].Count, "view [4][1] count"); - Assert.AreEqual(1, views[4][2].Count, "view [4][2] count"); - Assert.AreEqual(0, views[5][0].Count, "view [5][0] count"); - Assert.AreEqual(1, views[5][1].Count, "view [5][1] count"); - Assert.AreEqual(0, views[6][0].Count, "view [6][0] count"); - - Assert.IsTrue(list.Check(), "list check after RemoveAll"); + Assert.Multiple(() => + { + Assert.That(views[0][0].Offset, Is.EqualTo(0), "view [0][0] offset"); + Assert.That(views[0][1].Offset, Is.EqualTo(0), "view [0][1] offset"); + Assert.That(views[0][2].Offset, Is.EqualTo(0), "view [0][2] offset"); + Assert.That(views[0][3].Offset, Is.EqualTo(0), "view [0][3] offset"); + Assert.That(views[0][4].Offset, Is.EqualTo(0), "view [0][4] offset"); + Assert.That(views[0][5].Offset, Is.EqualTo(0), "view [0][5] offset"); + Assert.That(views[0][6].Offset, Is.EqualTo(0), "view [0][6] offset"); + Assert.That(views[1][0].Offset, Is.EqualTo(1), "view [1][0] offset"); + Assert.That(views[1][1].Offset, Is.EqualTo(1), "view [1][1] offset"); + Assert.That(views[1][2].Offset, Is.EqualTo(1), "view [1][2] offset"); + Assert.That(views[1][3].Offset, Is.EqualTo(1), "view [1][3] offset"); + Assert.That(views[1][4].Offset, Is.EqualTo(1), "view [1][4] offset"); + Assert.That(views[1][5].Offset, Is.EqualTo(1), "view [1][5] offset"); + Assert.That(views[2][0].Offset, Is.EqualTo(1), "view [2][0] offset"); + Assert.That(views[2][1].Offset, Is.EqualTo(1), "view [2][1] offset"); + Assert.That(views[2][2].Offset, Is.EqualTo(1), "view [2][2] offset"); + Assert.That(views[2][3].Offset, Is.EqualTo(1), "view [2][3] offset"); + Assert.That(views[2][4].Offset, Is.EqualTo(1), "view [2][4] offset"); + Assert.That(views[3][0].Offset, Is.EqualTo(2), "view [3][0] offset"); + Assert.That(views[3][1].Offset, Is.EqualTo(2), "view [3][1] offset"); + Assert.That(views[3][2].Offset, Is.EqualTo(2), "view [3][2] offset"); + Assert.That(views[3][3].Offset, Is.EqualTo(2), "view [3][3] offset"); + Assert.That(views[4][0].Offset, Is.EqualTo(2), "view [4][0] offset"); + Assert.That(views[4][1].Offset, Is.EqualTo(2), "view [4][1] offset"); + Assert.That(views[4][2].Offset, Is.EqualTo(2), "view [4][2] offset"); + Assert.That(views[5][0].Offset, Is.EqualTo(2), "view [5][0] offset"); + Assert.That(views[5][1].Offset, Is.EqualTo(2), "view [5][1] offset"); + Assert.That(views[6][0].Offset, Is.EqualTo(3), "view [6][0] offset"); + + Assert.That(views[0][0], Is.Empty, "view [0][0] count"); + Assert.That(views[0][1], Has.Count.EqualTo(1), "view [0][1] count"); + Assert.That(views[0][2], Has.Count.EqualTo(1), "view [0][2] count"); + Assert.That(views[0][3], Has.Count.EqualTo(2), "view [0][3] count"); + Assert.That(views[0][4], Has.Count.EqualTo(2), "view [0][4] count"); + Assert.That(views[0][5], Has.Count.EqualTo(2), "view [0][5] count"); + Assert.That(views[0][6], Has.Count.EqualTo(3), "view [0][6] count"); + Assert.That(views[1][0], Is.Empty, "view [1][0] count"); + Assert.That(views[1][1], Is.Empty, "view [1][1] count"); + Assert.That(views[1][2], Has.Count.EqualTo(1), "view [1][2] count"); + Assert.That(views[1][3], Has.Count.EqualTo(1), "view [1][3] count"); + Assert.That(views[1][4], Has.Count.EqualTo(1), "view [1][4] count"); + Assert.That(views[1][5], Has.Count.EqualTo(2), "view [1][5] count"); + Assert.That(views[2][0], Is.Empty, "view [2][0] count"); + Assert.That(views[2][1], Has.Count.EqualTo(1), "view [2][1] count"); + Assert.That(views[2][2], Has.Count.EqualTo(1), "view [2][2] count"); + Assert.That(views[2][3], Has.Count.EqualTo(1), "view [2][3] count"); + Assert.That(views[2][4], Has.Count.EqualTo(2), "view [2][4] count"); + Assert.That(views[3][0], Is.Empty, "view [3][0] count"); + Assert.That(views[3][1], Is.Empty, "view [3][1] count"); + Assert.That(views[3][2], Is.Empty, "view [3][2] count"); + Assert.That(views[3][3], Has.Count.EqualTo(1), "view [3][3] count"); + Assert.That(views[4][0], Is.Empty, "view [4][0] count"); + Assert.That(views[4][1], Is.Empty, "view [4][1] count"); + Assert.That(views[4][2], Has.Count.EqualTo(1), "view [4][2] count"); + Assert.That(views[5][0], Is.Empty, "view [5][0] count"); + Assert.That(views[5][1], Has.Count.EqualTo(1), "view [5][1] count"); + Assert.That(views[6][0], Is.Empty, "view [6][0] count"); + + Assert.That(list.Check(), Is.True, "list check after RemoveAll"); + }); } [Test] public void RetainAll() { - ArrayList list2 = new ArrayList() { 2, 4, 5 }; - Assert.IsTrue(list.Check(), "list check before RetainAll"); + ArrayList list2 = new() { 2, 4, 5 }; + Assert.That(list.Check(), Is.True, "list check before RetainAll"); list.RetainAll(list2); - Assert.AreEqual(0, views[0][0].Offset, "view [0][0] offset"); - Assert.AreEqual(0, views[0][1].Offset, "view [0][1] offset"); - Assert.AreEqual(0, views[0][2].Offset, "view [0][2] offset"); - Assert.AreEqual(0, views[0][3].Offset, "view [0][3] offset"); - Assert.AreEqual(0, views[0][4].Offset, "view [0][4] offset"); - Assert.AreEqual(0, views[0][5].Offset, "view [0][5] offset"); - Assert.AreEqual(0, views[0][6].Offset, "view [0][6] offset"); - Assert.AreEqual(0, views[1][0].Offset, "view [1][0] offset"); - Assert.AreEqual(0, views[1][1].Offset, "view [1][1] offset"); - Assert.AreEqual(0, views[1][2].Offset, "view [1][2] offset"); - Assert.AreEqual(0, views[1][3].Offset, "view [1][3] offset"); - Assert.AreEqual(0, views[1][4].Offset, "view [1][4] offset"); - Assert.AreEqual(0, views[1][5].Offset, "view [1][5] offset"); - Assert.AreEqual(0, views[2][0].Offset, "view [2][0] offset"); - Assert.AreEqual(0, views[2][1].Offset, "view [2][1] offset"); - Assert.AreEqual(0, views[2][2].Offset, "view [2][2] offset"); - Assert.AreEqual(0, views[2][3].Offset, "view [2][3] offset"); - Assert.AreEqual(0, views[2][4].Offset, "view [2][4] offset"); - Assert.AreEqual(1, views[3][0].Offset, "view [3][0] offset"); - Assert.AreEqual(1, views[3][1].Offset, "view [3][1] offset"); - Assert.AreEqual(1, views[3][2].Offset, "view [3][2] offset"); - Assert.AreEqual(1, views[3][3].Offset, "view [3][3] offset"); - Assert.AreEqual(1, views[4][0].Offset, "view [4][0] offset"); - Assert.AreEqual(1, views[4][1].Offset, "view [4][1] offset"); - Assert.AreEqual(1, views[4][2].Offset, "view [4][2] offset"); - Assert.AreEqual(2, views[5][0].Offset, "view [5][0] offset"); - Assert.AreEqual(2, views[5][1].Offset, "view [5][1] offset"); - Assert.AreEqual(3, views[6][0].Offset, "view [6][0] offset"); - - Assert.AreEqual(0, views[0][0].Count, "view [0][0] count"); - Assert.AreEqual(0, views[0][1].Count, "view [0][1] count"); - Assert.AreEqual(0, views[0][2].Count, "view [0][2] count"); - Assert.AreEqual(1, views[0][3].Count, "view [0][3] count"); - Assert.AreEqual(1, views[0][4].Count, "view [0][4] count"); - Assert.AreEqual(2, views[0][5].Count, "view [0][5] count"); - Assert.AreEqual(3, views[0][6].Count, "view [0][6] count"); - Assert.AreEqual(0, views[1][0].Count, "view [1][0] count"); - Assert.AreEqual(0, views[1][1].Count, "view [1][1] count"); - Assert.AreEqual(1, views[1][2].Count, "view [1][2] count"); - Assert.AreEqual(1, views[1][3].Count, "view [1][3] count"); - Assert.AreEqual(2, views[1][4].Count, "view [1][4] count"); - Assert.AreEqual(3, views[1][5].Count, "view [1][5] count"); - Assert.AreEqual(0, views[2][0].Count, "view [2][0] count"); - Assert.AreEqual(1, views[2][1].Count, "view [2][1] count"); - Assert.AreEqual(1, views[2][2].Count, "view [2][2] count"); - Assert.AreEqual(2, views[2][3].Count, "view [2][3] count"); - Assert.AreEqual(3, views[2][4].Count, "view [2][4] count"); - Assert.AreEqual(0, views[3][0].Count, "view [3][0] count"); - Assert.AreEqual(0, views[3][1].Count, "view [3][1] count"); - Assert.AreEqual(1, views[3][2].Count, "view [3][2] count"); - Assert.AreEqual(2, views[3][3].Count, "view [3][3] count"); - Assert.AreEqual(0, views[4][0].Count, "view [4][0] count"); - Assert.AreEqual(1, views[4][1].Count, "view [4][1] count"); - Assert.AreEqual(2, views[4][2].Count, "view [4][2] count"); - Assert.AreEqual(0, views[5][0].Count, "view [5][0] count"); - Assert.AreEqual(1, views[5][1].Count, "view [5][1] count"); - Assert.AreEqual(0, views[6][0].Count, "view [6][0] count"); - - Assert.IsTrue(list.Check(), "list check after RetainAll"); + Assert.Multiple(() => + { + Assert.That(views[0][0].Offset, Is.EqualTo(0), "view [0][0] offset"); + Assert.That(views[0][1].Offset, Is.EqualTo(0), "view [0][1] offset"); + Assert.That(views[0][2].Offset, Is.EqualTo(0), "view [0][2] offset"); + Assert.That(views[0][3].Offset, Is.EqualTo(0), "view [0][3] offset"); + Assert.That(views[0][4].Offset, Is.EqualTo(0), "view [0][4] offset"); + Assert.That(views[0][5].Offset, Is.EqualTo(0), "view [0][5] offset"); + Assert.That(views[0][6].Offset, Is.EqualTo(0), "view [0][6] offset"); + Assert.That(views[1][0].Offset, Is.EqualTo(0), "view [1][0] offset"); + Assert.That(views[1][1].Offset, Is.EqualTo(0), "view [1][1] offset"); + Assert.That(views[1][2].Offset, Is.EqualTo(0), "view [1][2] offset"); + Assert.That(views[1][3].Offset, Is.EqualTo(0), "view [1][3] offset"); + Assert.That(views[1][4].Offset, Is.EqualTo(0), "view [1][4] offset"); + Assert.That(views[1][5].Offset, Is.EqualTo(0), "view [1][5] offset"); + Assert.That(views[2][0].Offset, Is.EqualTo(0), "view [2][0] offset"); + Assert.That(views[2][1].Offset, Is.EqualTo(0), "view [2][1] offset"); + Assert.That(views[2][2].Offset, Is.EqualTo(0), "view [2][2] offset"); + Assert.That(views[2][3].Offset, Is.EqualTo(0), "view [2][3] offset"); + Assert.That(views[2][4].Offset, Is.EqualTo(0), "view [2][4] offset"); + Assert.That(views[3][0].Offset, Is.EqualTo(1), "view [3][0] offset"); + Assert.That(views[3][1].Offset, Is.EqualTo(1), "view [3][1] offset"); + Assert.That(views[3][2].Offset, Is.EqualTo(1), "view [3][2] offset"); + Assert.That(views[3][3].Offset, Is.EqualTo(1), "view [3][3] offset"); + Assert.That(views[4][0].Offset, Is.EqualTo(1), "view [4][0] offset"); + Assert.That(views[4][1].Offset, Is.EqualTo(1), "view [4][1] offset"); + Assert.That(views[4][2].Offset, Is.EqualTo(1), "view [4][2] offset"); + Assert.That(views[5][0].Offset, Is.EqualTo(2), "view [5][0] offset"); + Assert.That(views[5][1].Offset, Is.EqualTo(2), "view [5][1] offset"); + Assert.That(views[6][0].Offset, Is.EqualTo(3), "view [6][0] offset"); + + Assert.That(views[0][0], Is.Empty, "view [0][0] count"); + Assert.That(views[0][1], Is.Empty, "view [0][1] count"); + Assert.That(views[0][2], Is.Empty, "view [0][2] count"); + Assert.That(views[0][3], Has.Count.EqualTo(1), "view [0][3] count"); + Assert.That(views[0][4], Has.Count.EqualTo(1), "view [0][4] count"); + Assert.That(views[0][5], Has.Count.EqualTo(2), "view [0][5] count"); + Assert.That(views[0][6], Has.Count.EqualTo(3), "view [0][6] count"); + Assert.That(views[1][0], Is.Empty, "view [1][0] count"); + Assert.That(views[1][1], Is.Empty, "view [1][1] count"); + Assert.That(views[1][2], Has.Count.EqualTo(1), "view [1][2] count"); + Assert.That(views[1][3], Has.Count.EqualTo(1), "view [1][3] count"); + Assert.That(views[1][4], Has.Count.EqualTo(2), "view [1][4] count"); + Assert.That(views[1][5], Has.Count.EqualTo(3), "view [1][5] count"); + Assert.That(views[2][0], Is.Empty, "view [2][0] count"); + Assert.That(views[2][1], Has.Count.EqualTo(1), "view [2][1] count"); + Assert.That(views[2][2], Has.Count.EqualTo(1), "view [2][2] count"); + Assert.That(views[2][3], Has.Count.EqualTo(2), "view [2][3] count"); + Assert.That(views[2][4], Has.Count.EqualTo(3), "view [2][4] count"); + Assert.That(views[3][0], Is.Empty, "view [3][0] count"); + Assert.That(views[3][1], Is.Empty, "view [3][1] count"); + Assert.That(views[3][2], Has.Count.EqualTo(1), "view [3][2] count"); + Assert.That(views[3][3], Has.Count.EqualTo(2), "view [3][3] count"); + Assert.That(views[4][0], Is.Empty, "view [4][0] count"); + Assert.That(views[4][1], Has.Count.EqualTo(1), "view [4][1] count"); + Assert.That(views[4][2], Has.Count.EqualTo(2), "view [4][2] count"); + Assert.That(views[5][0], Is.Empty, "view [5][0] count"); + Assert.That(views[5][1], Has.Count.EqualTo(1), "view [5][1] count"); + Assert.That(views[6][0], Is.Empty, "view [6][0] count"); + + Assert.That(list.Check(), Is.True, "list check after RetainAll"); + }); } [Test] public void RemoveAllCopies() { - ArrayList list2 = new ArrayList { 0, 2, 2, 2, 5, 2, 1 }; + ArrayList list2 = new() { 0, 2, 2, 2, 5, 2, 1 }; for (int i = 0; i < 7; i++) { @@ -3150,9 +3549,12 @@ public void RemoveAllCopies() list.AddAll(list2); ArrayList v = (ArrayList)list.View(i, j); list.RemoveAllCopies(2); - Assert.AreEqual((i == 0 && j > 0 ? 1 : 0) + (i <= 4 && i + j > 4 ? 1 : 0) + (i <= 6 && i + j > 6 ? 1 : 0), v.Count, "v.Count, i=" + i + ", j=" + j); - Assert.AreEqual(i == 0 ? 0 : i <= 4 ? 1 : i <= 6 ? 2 : 3, v.Offset, "v.Offset, i=" + i + ", j=" + j); - Assert.IsTrue(list.Check(), "list check after RemoveAllCopies, i=" + i + ", j=" + j); + Assert.That(v, Has.Count.EqualTo((i == 0 && j > 0 ? 1 : 0) + (i <= 4 && i + j > 4 ? 1 : 0) + (i <= 6 && i + j > 6 ? 1 : 0)), "v.Count, i=" + i + ", j=" + j); + Assert.Multiple(() => + { + Assert.That(v.Offset, Is.EqualTo(i == 0 ? 0 : i <= 4 ? 1 : i <= 6 ? 2 : 3), "v.Offset, i=" + i + ", j=" + j); + Assert.That(list.Check(), Is.True, "list check after RemoveAllCopies, i=" + i + ", j=" + j); + }); } } } @@ -3174,14 +3576,14 @@ private void checkDisposed(bool reverse, int start, int count) { Assert.Fail("view[" + i + "][" + j + "] threw"); } - Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] size"); + Assert.That(views[i][j], Has.Count.EqualTo(j), "view[" + i + "][" + j + "] size"); if (reverse && ((j > 0 && start <= i && start + count >= i + j) || (j == 0 && start < i && start + count > i))) { - Assert.AreEqual(start + (start + count - i - j), views[i][j].Offset, "view[" + i + "][" + j + "] offset (mirrored)"); + Assert.That(views[i][j].Offset, Is.EqualTo(start + (start + count - i - j)), "view[" + i + "][" + j + "] offset (mirrored)"); } else { - Assert.AreEqual(i, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j].Offset, Is.EqualTo(i), "view[" + i + "][" + j + "] offset"); } } else @@ -3202,9 +3604,9 @@ public void Reverse() { int start = 2, count = 3; IList list2 = list.View(start, count); - Assert.IsTrue(list.Check(), "list check before Reverse"); + Assert.That(list.Check(), Is.True, "list check before Reverse"); list2.Reverse(); - Assert.IsTrue(list.Check(), "list check after Reverse"); + Assert.That(list.Check(), Is.True, "list check after Reverse"); checkDisposed(true, start, count); } [Test] @@ -3212,9 +3614,9 @@ public void Sort() { int start = 2, count = 3; IList list2 = list.View(start, count); - Assert.IsTrue(list.Check(), "list check before Sort"); + Assert.That(list.Check(), Is.True, "list check before Sort"); list2.Sort(); - Assert.IsTrue(list.Check(), "list check after Sort"); + Assert.That(list.Check(), Is.True, "list check after Sort"); checkDisposed(false, start, count); } [Test] @@ -3222,9 +3624,9 @@ public void Shuffle() { int start = 2, count = 3; IList list2 = list.View(start, count); - Assert.IsTrue(list.Check(), "list check before Shuffle"); + Assert.That(list.Check(), Is.True, "list check before Shuffle"); list2.Shuffle(); - Assert.IsTrue(list.Check(), "list check after Shuffle"); + Assert.That(list.Check(), Is.True, "list check after Shuffle"); checkDisposed(false, start, count); } @@ -3240,9 +3642,13 @@ namespace ArrayListOfTreesORLists [TestFixture] public class MultiLevelUnorderedOfUnOrdered { - private ICollection dit, dat, dut; + private ArrayList dit; + private TreeSet dat; + private ArrayList dut; - private ICollection> Dit, Dat, Dut; + private ArrayList> Dit; + private ArrayList> Dat; + private ArrayList> Dut; [SetUp] @@ -3263,8 +3669,11 @@ public void Init() [Test] public void Check() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dit.UnsequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dit.UnsequencedEquals(dut), Is.False); + }); } @@ -3273,27 +3682,36 @@ public void Multi() { Dit.Add(dit); Dit.Add(dut); Dit.Add(dit); Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); - Assert.IsTrue(Dit.UnsequencedEquals(Dat)); - Assert.IsFalse(Dit.UnsequencedEquals(Dut)); + Assert.Multiple(() => + { + Assert.That(Dit.UnsequencedEquals(Dat), Is.True); + Assert.That(Dit.UnsequencedEquals(Dut), Is.False); + }); } [TearDown] public void Dispose() { - dit = dat = dut = null; - Dit = Dat = Dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); } } - - [TestFixture] public class MultiLevelOrderedOfUnOrdered { - private ICollection dit, dat, dut; + private ArrayList dit; + private TreeSet dat; + private ArrayList dut; - private ISequenced> Dit, Dat, Dut; + private ArrayList> Dit; + private ArrayList> Dat; + private ArrayList> Dut; [SetUp] @@ -3314,8 +3732,11 @@ public void Init() [Test] public void Check() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dit.UnsequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dit.UnsequencedEquals(dut), Is.False); + }); } @@ -3325,16 +3746,23 @@ public void Multi() Dit.Add(dit); Dit.Add(dut); Dit.Add(dit); Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); Dut.Add(dit); Dut.Add(dut); Dut.Add(dat); - Assert.IsFalse(Dit.SequencedEquals(Dat)); - Assert.IsTrue(Dit.SequencedEquals(Dut)); + Assert.Multiple(() => + { + Assert.That(Dit.SequencedEquals(Dat), Is.False); + Assert.That(Dit.SequencedEquals(Dut), Is.True); + }); } [TearDown] public void Dispose() { - dit = dat = dut = null; - Dit = Dat = Dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); } } @@ -3343,9 +3771,15 @@ public void Dispose() [TestFixture] public class MultiLevelUnOrderedOfOrdered { - private ISequenced dit, dat, dut, dot; + private TreeSet dit; + private ArrayList dat; + private ArrayList dut; + private ArrayList dot; - private ICollection> Dit, Dat, Dut, Dot; + private ArrayList> Dit; + private ArrayList> Dat; + private ArrayList> Dut; + private ArrayList> Dot; [SetUp] @@ -3365,16 +3799,17 @@ public void Init() Dot = new ArrayList>(); } - [Test] public void Check() { - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsTrue(dit.SequencedEquals(dot)); - Assert.IsFalse(dit.SequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dit.SequencedEquals(dot), Is.True); + Assert.That(dit.SequencedEquals(dut), Is.False); + }); } - [Test] public void Multi() { @@ -3382,28 +3817,40 @@ public void Multi() Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); Dut.Add(dot); Dut.Add(dut); Dut.Add(dit); Dot.Add(dit); Dot.Add(dit); Dot.Add(dut); - Assert.IsTrue(Dit.UnsequencedEquals(Dut)); - Assert.IsFalse(Dit.UnsequencedEquals(Dat)); - Assert.IsTrue(Dit.UnsequencedEquals(Dot)); + Assert.Multiple(() => + { + Assert.That(Dit.UnsequencedEquals(Dut), Is.True); + Assert.That(Dit.UnsequencedEquals(Dat), Is.False); + Assert.That(Dit.UnsequencedEquals(Dot), Is.True); + }); } - [TearDown] public void Dispose() { - dit = dat = dut = dot = null; - Dit = Dat = Dut = Dot = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + dot.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); + Dot.Dispose(); } } - - [TestFixture] public class MultiLevelOrderedOfOrdered { - private ISequenced dit, dat, dut, dot; + private TreeSet dit; + private ArrayList dat; + private ArrayList dut; + private ArrayList dot; - private ISequenced> Dit, Dat, Dut, Dot; + private ArrayList> Dit; + private ArrayList> Dat; + private ArrayList> Dut; + private ArrayList> Dot; [SetUp] @@ -3427,9 +3874,12 @@ public void Init() [Test] public void Check() { - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsTrue(dit.SequencedEquals(dot)); - Assert.IsFalse(dit.SequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dit.SequencedEquals(dot), Is.True); + Assert.That(dit.SequencedEquals(dut), Is.False); + }); } @@ -3440,31 +3890,37 @@ public void Multi() Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); Dut.Add(dot); Dut.Add(dut); Dut.Add(dit); Dot.Add(dit); Dot.Add(dit); Dot.Add(dut); - Assert.IsTrue(Dit.SequencedEquals(Dut)); - Assert.IsFalse(Dit.SequencedEquals(Dat)); - Assert.IsFalse(Dit.SequencedEquals(Dot)); + Assert.Multiple(() => + { + Assert.That(Dit.SequencedEquals(Dut), Is.True); + Assert.That(Dit.SequencedEquals(Dat), Is.False); + Assert.That(Dit.SequencedEquals(Dot), Is.False); + }); } [TearDown] public void Dispose() { - dit = dat = dut = dot = null; - Dit = Dat = Dut = Dot = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + dot.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); + Dot.Dispose(); } } } - - namespace HashingAndEquals { [TestFixture] public class ISequenced { - private ISequenced dit, dat, dut; - + private ArrayList dit, dat, dut; [SetUp] public void Init() @@ -3474,35 +3930,39 @@ public void Init() dut = new ArrayList(); } - [Test] public void EmptyEmpty() { - Assert.IsTrue(dit.SequencedEquals(dat)); + Assert.That(dit.SequencedEquals(dat), Is.True); } - [Test] public void EmptyNonEmpty() { dit.Add(3); - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsFalse(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dat.SequencedEquals(dit), Is.False); + }); } [Test] public void HashVal() { - Assert.AreEqual(CHC.SequencedHashCode(), dit.GetSequencedHashCode()); + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode())); dit.Add(3); - Assert.AreEqual(CHC.SequencedHashCode(3), dit.GetSequencedHashCode()); + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(3))); dit.Add(7); - Assert.AreEqual(CHC.SequencedHashCode(3, 7), dit.GetSequencedHashCode()); - Assert.AreEqual(CHC.SequencedHashCode(), dut.GetSequencedHashCode()); + Assert.Multiple(() => + { + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(3, 7))); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode())); + }); dut.Add(7); - Assert.AreEqual(CHC.SequencedHashCode(7), dut.GetSequencedHashCode()); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(7))); dut.Add(3); - Assert.AreEqual(CHC.SequencedHashCode(7, 3), dut.GetSequencedHashCode()); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(7, 3))); } @@ -3511,8 +3971,11 @@ public void EqualHashButDifferent() { dit.Add(0); dit.Add(31); dat.Add(1); dat.Add(0); - Assert.AreEqual(dit.GetSequencedHashCode(), dat.GetSequencedHashCode()); - Assert.IsFalse(dit.SequencedEquals(dat)); + Assert.Multiple(() => + { + Assert.That(dat.GetSequencedHashCode(), Is.EqualTo(dit.GetSequencedHashCode())); + Assert.That(dit.SequencedEquals(dat), Is.False); + }); } @@ -3522,11 +3985,17 @@ public void Normal() dit.Add(3); dit.Add(7); dat.Add(3); - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsFalse(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dat.SequencedEquals(dit), Is.False); + }); dat.Add(7); - Assert.IsTrue(dit.SequencedEquals(dat)); - Assert.IsTrue(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.True); + Assert.That(dat.SequencedEquals(dit), Is.True); + }); } @@ -3535,41 +4004,45 @@ public void WrongOrder() { dit.Add(3); dut.Add(3); - Assert.IsTrue(dit.SequencedEquals(dut)); - Assert.IsTrue(dut.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dut), Is.True); + Assert.That(dut.SequencedEquals(dit), Is.True); + }); dit.Add(7); ((ArrayList)dut).InsertFirst(7); - Assert.IsFalse(dit.SequencedEquals(dut)); - Assert.IsFalse(dut.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dut), Is.False); + Assert.That(dut.SequencedEquals(dit), Is.False); + }); } [Test] public void Reflexive() { - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); dit.Add(3); - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); dit.Add(7); - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); } [TearDown] public void Dispose() { - dit = null; - dat = null; - dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); } } - - [TestFixture] public class IEditableCollection { - private ICollection dit, dat, dut; + private ArrayList dit, dat, dut; [SetUp] @@ -3580,11 +4053,10 @@ public void Init() dut = new ArrayList(); } - [Test] public void EmptyEmpty() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); + Assert.That(dit.UnsequencedEquals(dat), Is.True); } @@ -3592,24 +4064,30 @@ public void EmptyEmpty() public void EmptyNonEmpty() { dit.Add(3); - Assert.IsFalse(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.False); + Assert.That(dat.UnsequencedEquals(dit), Is.False); + }); } [Test] public void HashVal() { - Assert.AreEqual(CHC.UnsequencedHashCode(), dit.GetUnsequencedHashCode()); + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode())); dit.Add(3); - Assert.AreEqual(CHC.UnsequencedHashCode(3), dit.GetUnsequencedHashCode()); + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3))); dit.Add(7); - Assert.AreEqual(CHC.UnsequencedHashCode(3, 7), dit.GetUnsequencedHashCode()); - Assert.AreEqual(CHC.UnsequencedHashCode(), dut.GetUnsequencedHashCode()); + Assert.Multiple(() => + { + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3, 7))); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode())); + }); dut.Add(3); - Assert.AreEqual(CHC.UnsequencedHashCode(3), dut.GetUnsequencedHashCode()); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3))); dut.Add(7); - Assert.AreEqual(CHC.UnsequencedHashCode(7, 3), dut.GetUnsequencedHashCode()); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(7, 3))); } @@ -3618,67 +4096,76 @@ public void EqualHashButDifferent() { dit.Add(-1657792980); dit.Add(-1570288808); dat.Add(1862883298); dat.Add(-272461342); - Assert.AreEqual(dit.GetUnsequencedHashCode(), dat.GetUnsequencedHashCode()); - Assert.IsFalse(dit.UnsequencedEquals(dat)); + Assert.Multiple(() => + { + Assert.That(dat.GetUnsequencedHashCode(), Is.EqualTo(dit.GetUnsequencedHashCode())); + Assert.That(dit.UnsequencedEquals(dat), Is.False); + }); } - [Test] public void Normal() { dit.Add(3); dit.Add(7); dat.Add(3); - Assert.IsFalse(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.False); + Assert.That(dat.UnsequencedEquals(dit), Is.False); + }); dat.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsTrue(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dat.UnsequencedEquals(dit), Is.True); + }); } - [Test] public void WrongOrder() { dit.Add(3); dut.Add(3); - Assert.IsTrue(dit.UnsequencedEquals(dut)); - Assert.IsTrue(dut.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dut), Is.True); + Assert.That(dut.UnsequencedEquals(dit), Is.True); + }); dit.Add(7); dut.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dut)); - Assert.IsTrue(dut.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dut), Is.True); + Assert.That(dut.UnsequencedEquals(dit), Is.True); + }); } - [Test] public void Reflexive() { - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); dit.Add(3); - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); dit.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); } - [TearDown] public void Dispose() { - dit = null; - dat = null; - dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); } } - - [TestFixture] public class MultiLevelUnorderedOfUnOrdered { - private ICollection dit, dat, dut; + private ArrayList dit, dat, dut; - private ICollection> Dit, Dat, Dut; + private ArrayList> Dit, Dat, Dut; [SetUp] @@ -3699,8 +4186,11 @@ public void Init() [Test] public void Check() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dit.UnsequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dit.UnsequencedEquals(dut), Is.False); + }); } @@ -3709,27 +4199,32 @@ public void Multi() { Dit.Add(dit); Dit.Add(dut); Dit.Add(dit); Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); - Assert.IsTrue(Dit.UnsequencedEquals(Dat)); - Assert.IsFalse(Dit.UnsequencedEquals(Dut)); + Assert.Multiple(() => + { + Assert.That(Dit.UnsequencedEquals(Dat), Is.True); + Assert.That(Dit.UnsequencedEquals(Dut), Is.False); + }); } [TearDown] public void Dispose() { - dit = dat = dut = null; - Dit = Dat = Dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); } } - - [TestFixture] public class MultiLevelOrderedOfUnOrdered { - private ICollection dit, dat, dut; + private ArrayList dit, dat, dut; - private ISequenced> Dit, Dat, Dut; + private ArrayList> Dit, Dat, Dut; [SetUp] @@ -3750,8 +4245,11 @@ public void Init() [Test] public void Check() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dit.UnsequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dit.UnsequencedEquals(dut), Is.False); + }); } @@ -3761,27 +4259,32 @@ public void Multi() Dit.Add(dit); Dit.Add(dut); Dit.Add(dit); Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); Dut.Add(dit); Dut.Add(dut); Dut.Add(dat); - Assert.IsFalse(Dit.SequencedEquals(Dat)); - Assert.IsTrue(Dit.SequencedEquals(Dut)); + Assert.Multiple(() => + { + Assert.That(Dit.SequencedEquals(Dat), Is.False); + Assert.That(Dit.SequencedEquals(Dut), Is.True); + }); } [TearDown] public void Dispose() { - dit = dat = dut = null; - Dit = Dat = Dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); } } - - [TestFixture] public class MultiLevelUnOrderedOfOrdered { - private ISequenced dit, dat, dut, dot; + private ArrayList dit, dat, dut, dot; - private ICollection> Dit, Dat, Dut, Dot; + private ArrayList> Dit, Dat, Dut, Dot; [SetUp] @@ -3805,9 +4308,12 @@ public void Init() [Test] public void Check() { - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsTrue(dit.SequencedEquals(dot)); - Assert.IsFalse(dit.SequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dit.SequencedEquals(dot), Is.True); + Assert.That(dit.SequencedEquals(dut), Is.False); + }); } @@ -3818,17 +4324,26 @@ public void Multi() Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); Dut.Add(dot); Dut.Add(dut); Dut.Add(dit); Dot.Add(dit); Dot.Add(dit); Dot.Add(dut); - Assert.IsTrue(Dit.UnsequencedEquals(Dut)); - Assert.IsFalse(Dit.UnsequencedEquals(Dat)); - Assert.IsTrue(Dit.UnsequencedEquals(Dot)); + Assert.Multiple(() => + { + Assert.That(Dit.UnsequencedEquals(Dut), Is.True); + Assert.That(Dit.UnsequencedEquals(Dat), Is.False); + Assert.That(Dit.UnsequencedEquals(Dot), Is.True); + }); } [TearDown] public void Dispose() { - dit = dat = dut = dot = null; - Dit = Dat = Dut = Dot = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + dot.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); + Dot.Dispose(); } } @@ -3837,9 +4352,9 @@ public void Dispose() [TestFixture] public class MultiLevelOrderedOfOrdered { - private ISequenced dit, dat, dut, dot; + private ArrayList dit, dat, dut, dot; - private ISequenced> Dit, Dat, Dut, Dot; + private ArrayList> Dit, Dat, Dut, Dot; [SetUp] @@ -3863,9 +4378,12 @@ public void Init() [Test] public void Check() { - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsTrue(dit.SequencedEquals(dot)); - Assert.IsFalse(dit.SequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dit.SequencedEquals(dot), Is.True); + Assert.That(dit.SequencedEquals(dut), Is.False); + }); } @@ -3876,17 +4394,26 @@ public void Multi() Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); Dut.Add(dot); Dut.Add(dut); Dut.Add(dit); Dot.Add(dit); Dot.Add(dit); Dot.Add(dut); - Assert.IsTrue(Dit.SequencedEquals(Dut)); - Assert.IsFalse(Dit.SequencedEquals(Dat)); - Assert.IsFalse(Dit.SequencedEquals(Dot)); + Assert.Multiple(() => + { + Assert.That(Dit.SequencedEquals(Dut), Is.True); + Assert.That(Dit.SequencedEquals(Dat), Is.False); + Assert.That(Dit.SequencedEquals(Dot), Is.False); + }); } [TearDown] public void Dispose() { - dit = dat = dut = dot = null; - Dit = Dat = Dut = Dot = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + dot.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); + Dot.Dispose(); } } } diff --git a/C5.Tests/Arrays/CircularQueueTest.cs b/C5.Tests/Arrays/CircularQueueTest.cs index 557da5a1..e8e66fde 100644 --- a/C5.Tests/Arrays/CircularQueueTest.cs +++ b/C5.Tests/Arrays/CircularQueueTest.cs @@ -5,25 +5,23 @@ using System; namespace C5.Tests.arrays.circularqueue { - using CollectionOfInt = CircularQueue; - [TestFixture] public class GenericTesters { [Test] public void TestEvents() { - CollectionOfInt factory() { return new CollectionOfInt(); } - new C5.Tests.Templates.Events.QueueTester().Test(factory); - new C5.Tests.Templates.Events.StackTester().Test(factory); + CircularQueue factory() { return new CircularQueue(); } + new C5.Tests.Templates.Events.QueueTester>().Test(factory); + new C5.Tests.Templates.Events.StackTester>().Test(factory); } //[Test] //public void Extensible() //{ // TODO: Test Circular Queue for Clone(?) and Serializable - // C5.Tests.Templates.Extensible.Clone.Tester(); - // C5.Tests.Templates.Extensible.Serialization.Tester(); + // C5.Tests.Templates.Extensible.Clone.Tester>(); + // C5.Tests.Templates.Extensible.Serialization.Tester>(); //} } @@ -58,16 +56,19 @@ public class Formatting [Test] public void Format() { - Assert.AreEqual("{ }", coll.ToString()); + Assert.That(coll.ToString(), Is.EqualTo("{ }")); foreach (int i in new int[] { -4, 28, 129, 65530 }) { coll.Enqueue(i); } - Assert.AreEqual("{ -4, 28, 129, 65530 }", coll.ToString()); - Assert.AreEqual("{ -4, 1C, 81, FFFA }", coll.ToString(null, rad16)); - Assert.AreEqual("{ -4, 28, 129... }", coll.ToString("L14", null)); - Assert.AreEqual("{ -4, 1C, 81... }", coll.ToString("L14", rad16)); + Assert.Multiple(() => + { + Assert.That(coll.ToString(), Is.EqualTo("{ -4, 28, 129, 65530 }")); + Assert.That(coll.ToString(null, rad16), Is.EqualTo("{ -4, 1C, 81, FFFA }")); + Assert.That(coll.ToString("L14", null), Is.EqualTo("{ -4, 28, 129... }")); + Assert.That(coll.ToString("L14", rad16), Is.EqualTo("{ -4, 1C, 81... }")); + }); } } @@ -108,11 +109,11 @@ private void loadup3() for (int i = 0; i < 18; i++) { queue.Enqueue(i); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); } for (int i = 0; i < 14; i++) { - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); queue.Dequeue(); } } @@ -120,36 +121,42 @@ private void loadup3() [Test] public void Expand() { - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); loadup3(); - Assert.IsTrue(IC.Eq(queue, 14, 15, 16, 17)); + Assert.That(IC.Eq(queue, 14, 15, 16, 17), Is.True); } [Test] public void Simple() { loadup1(); - Assert.IsTrue(queue.Check()); - Assert.AreEqual(5, queue.Count); - Assert.IsTrue(IC.Eq(queue, 12, 13, 103, 14, 15)); - Assert.AreEqual(12, queue.Choose()); + Assert.Multiple(() => + { + Assert.That(queue.Check(), Is.True); + Assert.That(queue, Has.Count.EqualTo(5)); + Assert.That(IC.Eq(queue, 12, 13, 103, 14, 15), Is.True); + }); + Assert.That(queue.Choose(), Is.EqualTo(12)); } [Test] public void Stack() { queue.Push(1); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); queue.Push(2); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); queue.Push(3); - Assert.IsTrue(queue.Check()); - Assert.AreEqual(3, queue.Pop()); - Assert.IsTrue(queue.Check()); - Assert.AreEqual(2, queue.Pop()); - Assert.IsTrue(queue.Check()); - Assert.AreEqual(1, queue.Pop()); - Assert.IsTrue(queue.Check()); + Assert.Multiple(() => + { + Assert.That(queue.Check(), Is.True); + Assert.That(queue.Pop(), Is.EqualTo(3)); + }); + Assert.That(queue.Check(), Is.True); + Assert.That(queue.Pop(), Is.EqualTo(2)); + Assert.That(queue.Check(), Is.True); + Assert.That(queue.Pop(), Is.EqualTo(1)); + Assert.That(queue.Check(), Is.True); } [Test] @@ -168,29 +175,35 @@ public void BadDequeue() public void Simple2() { loadup2(); - Assert.IsTrue(queue.Check()); - Assert.AreEqual(5, queue.Count); - Assert.IsTrue(IC.Eq(queue, 15, 1000, 1001, 1002, 1003)); - Assert.AreEqual(15, queue.Choose()); + Assert.Multiple(() => + { + Assert.That(queue.Check(), Is.True); + Assert.That(queue, Has.Count.EqualTo(5)); + Assert.That(IC.Eq(queue, 15, 1000, 1001, 1002, 1003), Is.True); + }); + Assert.That(queue.Choose(), Is.EqualTo(15)); } [Test] public void Counting() { - Assert.IsTrue(queue.IsEmpty); - Assert.AreEqual(0, queue.Count); - Assert.AreEqual(Speed.Constant, queue.CountSpeed); + Assert.Multiple(() => + { + Assert.That(queue.IsEmpty, Is.True); + Assert.That(queue, Is.Empty); + }); + Assert.That(queue.CountSpeed, Is.EqualTo(Speed.Constant)); queue.Enqueue(11); - Assert.IsFalse(queue.IsEmpty); + Assert.That(queue.IsEmpty, Is.False); queue.Enqueue(12); - Assert.AreEqual(2, queue.Count); + Assert.That(queue, Has.Count.EqualTo(2)); } //This test by Steve Wallace uncovered a bug in the indexing. [Test] public void SW200602() { - C5.CircularQueue list = new C5.CircularQueue(8); + C5.CircularQueue list = new(8); for (int count = 0; count <= 7; count++) { list.Enqueue(count); @@ -198,7 +211,7 @@ public void SW200602() int end = list.Count; for (int index = 0; index < end; index++) { - Assert.AreEqual(index, list[0]); + Assert.That(list[0], Is.EqualTo(index)); list.Dequeue(); } } diff --git a/C5.Tests/Arrays/HashedArrayListTest.cs b/C5.Tests/Arrays/HashedArrayListTest.cs index a8205be2..99e0fa03 100644 --- a/C5.Tests/Arrays/HashedArrayListTest.cs +++ b/C5.Tests/Arrays/HashedArrayListTest.cs @@ -7,32 +7,21 @@ namespace C5.Tests.arrays.hashed { - using CollectionOfInt = HashedArrayList; - [TestFixture] public class GenericTesters { [Test] public void TestEvents() { - CollectionOfInt factory() { return new CollectionOfInt(TenEqualityComparer.Default); } - new C5.Tests.Templates.Events.ListTester().Test(factory); + HashedArrayList factory() { return new HashedArrayList(TenEqualityComparer.Default); } + new C5.Tests.Templates.Events.ListTester>().Test(factory); } - //[Test] - //public void Extensible() - //{ - // C5.Tests.Templates.Extensible.Clone.Tester(); - // C5.Tests.Templates.Extensible.Clone.ViewTester(); - // C5.Tests.Templates.Extensible.Serialization.Tester(); - // C5.Tests.Templates.Extensible.Serialization.ViewTester(); - //} - [Test] public void List() { - C5.Tests.Templates.List.Dispose.Tester(); - C5.Tests.Templates.List.SCG_IList.Tester(); + Templates.List.Dispose.Tester>(); + Templates.List.SCG_IList.Tester>(); } } @@ -46,7 +35,7 @@ namespace Events internal class TenEqualityComparer : SCG.IEqualityComparer { private TenEqualityComparer() { } - public static TenEqualityComparer Default => new TenEqualityComparer(); + public static TenEqualityComparer Default => new(); public int GetHashCode(int item) { return (item / 10).GetHashCode(); } public bool Equals(int item1, int item2) { return item1 / 10 == item2 / 10; } } @@ -61,7 +50,7 @@ public class IList_ public void Init() { list = new HashedArrayList(TenEqualityComparer.Default); - seen = new CollectionEventList(System.Collections.Generic.EqualityComparer.Default); + seen = new CollectionEventList(SCG.EqualityComparer.Default); } private void listen() { seen.Listen(list, EventType.All); } @@ -72,13 +61,13 @@ public void SetThis() list.Add(4); list.Add(56); list.Add(8); listen(); list[1] = 45; - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), list), new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(56,1), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(45, 1), list), new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(45,1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); } [Test] @@ -87,11 +76,11 @@ public void Insert() list.Add(4); list.Add(56); list.Add(8); listen(); list.Insert(1, 45); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(45,1), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(45, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); } [Test] @@ -99,9 +88,9 @@ public void InsertAll() { list.Add(4); list.Add(56); list.Add(8); listen(); - list.InsertAll(1, new int[] { 666, 777, 888 }); + list.InsertAll(1, [666, 777, 888]); //seen.Print(Console.Error); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(666,1), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(666, 1), list), new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(777,2), list), @@ -109,9 +98,9 @@ public void InsertAll() new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(888,3), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(888, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); - list.InsertAll(1, new int[] { }); - seen.Check(new CollectionEvent[] { }); + ]); + list.InsertAll(1, []); + seen.Check([]); } [Test] @@ -120,17 +109,17 @@ public void InsertFirstLast() list.Add(4); list.Add(56); list.Add(18); listen(); list.InsertFirst(45); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(45,0), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(45, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.InsertLast(88); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(88,4), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(88, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); } [Test] @@ -139,9 +128,9 @@ public void Remove() list.Add(4); list.Add(56); list.Add(8); listen(); list.Remove(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); } [Test] @@ -150,10 +139,10 @@ public void RemoveFirst() list.Add(4); list.Add(56); list.Add(8); listen(); list.RemoveFirst(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(4,0), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(4, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); } [Test] @@ -162,10 +151,10 @@ public void RemoveLast() list.Add(4); list.Add(56); list.Add(8); listen(); list.RemoveLast(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(56,1), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); } [Test] @@ -174,11 +163,11 @@ public void Reverse() list.Add(4); list.Add(56); list.Add(8); listen(); list.Reverse(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.View(1, 0).Reverse(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } @@ -188,11 +177,11 @@ public void Sort() list.Add(4); list.Add(56); list.Add(8); listen(); list.Sort(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.View(1, 0).Sort(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } [Test] @@ -201,11 +190,11 @@ public void Shuffle() list.Add(4); list.Add(56); list.Add(8); listen(); list.Shuffle(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.View(1, 0).Shuffle(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } [Test] @@ -214,10 +203,10 @@ public void RemoveAt() list.Add(4); list.Add(56); list.Add(8); listen(); list.RemoveAt(1); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(56,1), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); } [Test] @@ -226,12 +215,12 @@ public void RemoveInterval() list.Add(4); list.Add(56); list.Add(18); listen(); list.RemoveInterval(1, 2); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Cleared, new ClearedRangeEventArgs(false,2,1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.RemoveInterval(1, 0); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } [Test] @@ -240,13 +229,13 @@ public void Update() list.Add(4); list.Add(56); list.Add(8); listen(); list.Update(53); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(53, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.Update(67); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } [Test] @@ -256,13 +245,13 @@ public void FindOrAdd() listen(); int val = 53; list.FindOrAdd(ref val); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); val = 67; list.FindOrAdd(ref val); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(67, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); } [Test] @@ -272,29 +261,29 @@ public void UpdateOrAdd() listen(); int val = 53; list.UpdateOrAdd(val); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(53, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); val = 67; list.UpdateOrAdd(val); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(67, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.UpdateOrAdd(51, out _); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(53, 1), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(51, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); // val = 67; list.UpdateOrAdd(81, out _); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(81, 1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); } [Test] @@ -303,13 +292,13 @@ public void RemoveItem() list.Add(4); list.Add(56); list.Add(18); listen(); list.Remove(53); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); list.Remove(11); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(18, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); } [Test] @@ -320,14 +309,14 @@ public void RemoveAll() list.Add(10 * i + 5); } listen(); - list.RemoveAll(new int[] { 32, 187, 45 }); + list.RemoveAll([32, 187, 45]); //TODO: the order depends on internals of the HashSet - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(35, 1), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(45, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); - list.RemoveAll(new int[] { 200, 300 }); - seen.Check(new CollectionEvent[] { }); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); + list.RemoveAll([200, 300]); + seen.Check([]); } [Test] @@ -336,17 +325,17 @@ public void Clear() list.Add(4); list.Add(56); list.Add(18); listen(); list.View(1, 1).Clear(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Cleared, new ClearedRangeEventArgs(false,1,1), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.Clear(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Cleared, new ClearedRangeEventArgs(true,2,0), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.Clear(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } [Test] @@ -355,14 +344,14 @@ public void ListDispose() list.Add(4); list.Add(56); list.Add(18); listen(); list.View(1, 1).Dispose(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); list.Dispose(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Cleared, new ClearedRangeEventArgs(true,3,0), list), new CollectionEvent(EventType.Changed, new EventArgs(), list) - }); + ]); list.Dispose(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } @@ -374,15 +363,15 @@ public void RetainAll() list.Add(10 * i + 5); } listen(); - list.RetainAll(new int[] { 32, 187, 45, 62, 82, 95, 2 }); - seen.Check(new CollectionEvent[] { + list.RetainAll([32, 187, 45, 62, 82, 95, 2]); + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(15, 1), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(25, 1), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(55, 1), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(75, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); - list.RetainAll(new int[] { 32, 187, 45, 62, 82, 95, 2 }); - seen.Check(new CollectionEvent[] { }); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); + list.RetainAll([32, 187, 45, 62, 82, 95, 2]); + seen.Check([]); } [Test] @@ -394,22 +383,22 @@ public void RemoveAllCopies() } listen(); list.RemoveAllCopies(14); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(11, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); list.RemoveAllCopies(14); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } [Test] public void Add() { listen(); - seen.Check(new CollectionEvent[0]); + seen.Check([]); list.Add(23); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(23, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); } [Test] @@ -420,17 +409,17 @@ public void AddAll() list.Add(10 * i + 5); } listen(); - list.AddAll(new int[] { 145, 56, 167 }); - seen.Check(new CollectionEvent[] { + list.AddAll([145, 56, 167]); + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(145, 1), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(167, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); - list.AddAll(new int[] { }); - seen.Check(new CollectionEvent[] { }); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); + list.AddAll([]); + seen.Check([]); } [TearDown] - public void Dispose() { list = null; seen = null; } + public void Dispose() { list.Dispose(); seen = null; } } [TestFixture] @@ -444,7 +433,7 @@ public class StackQueue public void Init() { list = new ArrayList(TenEqualityComparer.Default); - seen = new CollectionEventList(System.Collections.Generic.EqualityComparer.Default); + seen = new CollectionEventList(SCG.EqualityComparer.Default); } private void listen() { seen.Listen(list, EventType.All); } @@ -454,56 +443,56 @@ public void EnqueueDequeue() { listen(); list.Enqueue(67); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(67,0), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(67, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); list.Enqueue(2); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(2,1), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(2, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); list.Dequeue(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(67,0), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(67, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); list.Dequeue(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(2,0), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(2, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); } [Test] public void PushPop() { listen(); - seen.Check(new CollectionEvent[0]); + seen.Check([]); list.Push(23); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(23,0), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(23, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); list.Push(-12); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(-12,1), list), new CollectionEvent(EventType.Added, new ItemCountEventArgs(-12, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); list.Pop(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(-12,1), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(-12, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); list.Pop(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(23,0), list), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(23, 1), list), - new CollectionEvent(EventType.Changed, new EventArgs(), list)}); + new CollectionEvent(EventType.Changed, new EventArgs(), list)]); } [TearDown] - public void Dispose() { list = null; seen = null; } + public void Dispose() { list.Dispose(); seen = null; } } @@ -535,8 +524,12 @@ public void InsertAll() Assert.Fail("Should not get here"); } catch (BadEnumerableException) { } - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 91, 81, 71, 56, 18)); + + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 91, 81, 71, 56, 18), Is.True); + }); } [Test] @@ -549,8 +542,12 @@ public void AddAll() Assert.Fail("Should not get here"); } catch (BadEnumerableException) { } - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 91, 81, 71, 56, 18)); + + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 91, 81, 71, 56, 18), Is.True); + }); } [Test] @@ -563,8 +560,12 @@ public void RemoveAll() Assert.Fail("Should not get here"); } catch (BadEnumerableException) { } - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 56, 18)); + + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 56, 18), Is.True); + }); } [Test] @@ -577,8 +578,12 @@ public void RetainAll() Assert.Fail("Should not get here"); } catch (BadEnumerableException) { } - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 56, 18)); + + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 56, 18), Is.True); + }); } @@ -592,13 +597,17 @@ public void ContainsAll() Assert.Fail("Should not get here"); } catch (BadEnumerableException) { } - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 56, 18)); + + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 56, 18), Is.True); + }); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } /// @@ -645,34 +654,52 @@ public void Init() [Test] public void All() { - Assert.IsTrue(list.All(always)); - Assert.IsTrue(list.All(never)); - Assert.IsTrue(list.All(even)); + Assert.Multiple(() => + { + Assert.That(list.All(always), Is.True); + Assert.That(list.All(never), Is.True); + Assert.That(list.All(even), Is.True); + }); list.Add(8); - Assert.IsTrue(list.All(always)); - Assert.IsFalse(list.All(never)); - Assert.IsTrue(list.All(even)); + Assert.Multiple(() => + { + Assert.That(list.All(always), Is.True); + Assert.That(list.All(never), Is.False); + Assert.That(list.All(even), Is.True); + }); list.Add(5); - Assert.IsTrue(list.All(always)); - Assert.IsFalse(list.All(never)); - Assert.IsFalse(list.All(even)); + Assert.Multiple(() => + { + Assert.That(list.All(always), Is.True); + Assert.That(list.All(never), Is.False); + Assert.That(list.All(even), Is.False); + }); } [Test] public void Exists() { - Assert.IsFalse(list.Exists(always)); - Assert.IsFalse(list.Exists(never)); - Assert.IsFalse(list.Exists(even)); + Assert.Multiple(() => + { + Assert.That(list.Exists(always), Is.False); + Assert.That(list.Exists(never), Is.False); + Assert.That(list.Exists(even), Is.False); + }); list.Add(5); - Assert.IsTrue(list.Exists(always)); - Assert.IsFalse(list.Exists(never)); - Assert.IsFalse(list.Exists(even)); + Assert.Multiple(() => + { + Assert.That(list.Exists(always), Is.True); + Assert.That(list.Exists(never), Is.False); + Assert.That(list.Exists(even), Is.False); + }); list.Add(8); - Assert.IsTrue(list.Exists(always)); - Assert.IsFalse(list.Exists(never)); - Assert.IsTrue(list.Exists(even)); + Assert.Multiple(() => + { + Assert.That(list.Exists(always), Is.True); + Assert.That(list.Exists(never), Is.False); + Assert.That(list.Exists(even), Is.True); + }); } @@ -683,16 +710,16 @@ public void Apply() void a(int i) { sum = i + 10 * sum; } list.Apply(a); - Assert.AreEqual(0, sum); + Assert.That(sum, Is.EqualTo(0)); sum = 0; list.Add(5); list.Add(8); list.Add(7); list.Add(5); list.Apply(a); - Assert.AreEqual(587, sum); + Assert.That(sum, Is.EqualTo(587)); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } @@ -712,7 +739,7 @@ public void Empty() { SCG.IEnumerator e = list.GetEnumerator(); - Assert.IsFalse(e.MoveNext()); + Assert.That(e.MoveNext(), Is.False); } @@ -728,15 +755,18 @@ public void Normal() SCG.IEnumerator e = list.GetEnumerator(); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(5, e.Current); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(8, e.Current); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(10, e.Current); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(1, e.Current); - Assert.IsFalse(e.MoveNext()); + Assert.Multiple(() => + { + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(5)); + }); + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(8)); + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(10)); + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(1)); + Assert.That(e.MoveNext(), Is.False); } @@ -771,7 +801,7 @@ public void MoveNextAfterUpdate() } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } } @@ -789,12 +819,15 @@ public class Formatting [Test] public void Format() { - Assert.AreEqual("[ ]", coll.ToString()); - coll.AddAll(new int[] { -4, 28, 129, 65530 }); - Assert.AreEqual("[ 0:-4, 1:28, 2:129, 3:65530 ]", coll.ToString()); - Assert.AreEqual("[ 0:-4, 1:1C, 2:81, 3:FFFA ]", coll.ToString(null, rad16)); - Assert.AreEqual("[ 0:-4, 1:28... ]", coll.ToString("L14", null)); - Assert.AreEqual("[ 0:-4, 1:1C... ]", coll.ToString("L14", rad16)); + Assert.That(coll.ToString(), Is.EqualTo("[ ]")); + coll.AddAll([-4, 28, 129, 65530]); + Assert.Multiple(() => + { + Assert.That(coll.ToString(), Is.EqualTo("[ 0:-4, 1:28, 2:129, 3:65530 ]")); + Assert.That(coll.ToString(null, rad16), Is.EqualTo("[ 0:-4, 1:1C, 2:81, 3:FFFA ]")); + Assert.That(coll.ToString("L14", null), Is.EqualTo("[ 0:-4, 1:28... ]")); + Assert.That(coll.ToString("L14", rad16), Is.EqualTo("[ 0:-4, 1:1C... ]")); + }); } } @@ -811,7 +844,7 @@ public class CollectionOrSink public void Choose() { list.Add(7); - Assert.AreEqual(7, list.Choose()); + Assert.That(list.Choose(), Is.EqualTo(7)); } [Test] @@ -823,17 +856,26 @@ public void BadChoose() [Test] public void CountEtAl() { - Assert.AreEqual(0, list.Count); - Assert.IsTrue(list.IsEmpty); - Assert.IsFalse(list.AllowsDuplicates); - Assert.IsTrue(list.Add(5)); - Assert.AreEqual(1, list.Count); - Assert.IsFalse(list.IsEmpty); - Assert.IsFalse(list.Add(5)); - Assert.AreEqual(1, list.Count); - Assert.IsFalse(list.IsEmpty); - Assert.IsTrue(list.Add(8)); - Assert.AreEqual(2, list.Count); + Assert.That(list, Is.Empty); + Assert.Multiple(() => + { + Assert.That(list.IsEmpty, Is.True); + Assert.That(list.AllowsDuplicates, Is.False); + Assert.That(list.Add(5), Is.True); + Assert.That(list, Has.Count.EqualTo(1)); + }); + Assert.Multiple(() => + { + Assert.That(list.IsEmpty, Is.False); + Assert.That(list.Add(5), Is.False); + Assert.That(list, Has.Count.EqualTo(1)); + }); + Assert.Multiple(() => + { + Assert.That(list.IsEmpty, Is.False); + Assert.That(list.Add(8), Is.True); + Assert.That(list, Has.Count.EqualTo(2)); + }); } @@ -842,18 +884,21 @@ public void AddAll() { list.Add(3); list.Add(4); list.Add(5); - HashedArrayList list2 = new HashedArrayList(); + HashedArrayList list2 = new(); list2.AddAll(list); - Assert.IsTrue(IC.Eq(list2, 3, 4, 5)); + Assert.That(IC.Eq(list2, 3, 4, 5), Is.True); list.AddAll(list2); - Assert.IsTrue(IC.Eq(list2, 3, 4, 5)); - Assert.IsTrue(IC.Eq(list, 3, 4, 5)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list2, 3, 4, 5), Is.True); + Assert.That(IC.Eq(list, 3, 4, 5), Is.True); + }); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } [TestFixture] @@ -870,48 +915,54 @@ public void Init() } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } [Test] public void Find() { - Assert.IsFalse(list.Find(pred, out int i)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(list.Find(pred, out i)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.IsTrue(list.Find(pred, out i)); - Assert.AreEqual(45, i); + Assert.That(list.Find(pred, out int i), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(list.Find(pred, out i), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.Multiple(() => + { + Assert.That(list.Find(pred, out i), Is.True); + Assert.That(i, Is.EqualTo(45)); + }); } [Test] public void FindLast() { - Assert.IsFalse(list.FindLast(pred, out int i)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(list.FindLast(pred, out i)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.IsTrue(list.FindLast(pred, out i)); - Assert.AreEqual(675, i); + Assert.That(list.FindLast(pred, out int i), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(list.FindLast(pred, out i), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.Multiple(() => + { + Assert.That(list.FindLast(pred, out i), Is.True); + Assert.That(i, Is.EqualTo(675)); + }); } [Test] public void FindIndex() { - Assert.IsFalse(0 <= list.FindIndex(pred)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(0 <= list.FindIndex(pred)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.AreEqual(4, list.FindIndex(pred)); + Assert.That(0 <= list.FindIndex(pred), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(0 <= list.FindIndex(pred), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.That(list.FindIndex(pred), Is.EqualTo(4)); } [Test] public void FindLastIndex() { - Assert.IsFalse(0 <= list.FindLastIndex(pred)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(0 <= list.FindLastIndex(pred)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.AreEqual(6, list.FindLastIndex(pred)); + Assert.That(0 <= list.FindLastIndex(pred), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(0 <= list.FindLastIndex(pred), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.That(list.FindLastIndex(pred), Is.EqualTo(6)); } } @@ -924,16 +975,22 @@ public class UniqueItems public void Init() { list = new HashedArrayList(); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } [Test] public void Test() { - Assert.IsTrue(IC.SetEq(list.UniqueItems())); - Assert.IsTrue(IC.SetEq(list.ItemMultiplicities())); - list.AddAll(new int[] { 7, 9, 7 }); - Assert.IsTrue(IC.SetEq(list.UniqueItems(), 7, 9)); - Assert.IsTrue(IC.SetEq(list.ItemMultiplicities(), 7, 1, 9, 1)); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(list.UniqueItems()), Is.True); + Assert.That(IC.SetEq(list.ItemMultiplicities()), Is.True); + }); + list.AddAll([7, 9, 7]); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(list.UniqueItems(), 7, 9), Is.True); + Assert.That(IC.SetEq(list.ItemMultiplicities(), 7, 1, 9, 1), Is.True); + }); } } @@ -957,7 +1014,7 @@ public void Init() [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } private string aeq(int[] a, params int[] b) @@ -982,10 +1039,10 @@ private string aeq(int[] a, params int[] b) [Test] public void ToArray() { - Assert.AreEqual("Alles klar", aeq(list.ToArray())); + Assert.That(aeq(list.ToArray()), Is.EqualTo("Alles klar")); list.Add(7); list.Add(8); - Assert.AreEqual("Alles klar", aeq(list.ToArray(), 7, 8)); + Assert.That(aeq(list.ToArray(), 7, 8), Is.EqualTo("Alles klar")); } @@ -993,19 +1050,19 @@ public void ToArray() public void CopyTo() { list.CopyTo(a, 1); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009), Is.EqualTo("Alles klar")); list.Add(6); list.CopyTo(a, 2); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009), Is.EqualTo("Alles klar")); list.Add(4); list.Add(5); list.Add(9); list.CopyTo(a, 4); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 4, 5, 9, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 6, 4, 5, 9, 1008, 1009), Is.EqualTo("Alles klar")); list.Clear(); list.Add(7); list.CopyTo(a, 9); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 4, 5, 9, 1008, 7)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 6, 4, 5, 9, 1008, 7), Is.EqualTo("Alles klar")); } @@ -1035,24 +1092,11 @@ public void CopyToTooFar() [TestFixture] public class Sync { - private HashedArrayList list; - - - [SetUp] - public void Init() - { - list = new HashedArrayList(); - } - - - [TearDown] - public void Dispose() { list = null; } - - [Test] - public void Get() + public void HashedArrayList_has_SyncRoot() { - Assert.IsNotNull(((System.Collections.IList)list).SyncRoot); + var list = new HashedArrayList(); + Assert.That(((System.Collections.IList)list).SyncRoot, Is.Not.Null); } } } @@ -1084,43 +1128,61 @@ public void NullEqualityComparerinConstructor2() [Test] public void Contains() { - Assert.IsFalse(list.Contains(5)); + Assert.That(list.Contains(5), Is.False); list.Add(5); - Assert.IsTrue(list.Contains(5)); - Assert.IsFalse(list.Contains(7)); + Assert.Multiple(() => + { + Assert.That(list.Contains(5), Is.True); + Assert.That(list.Contains(7), Is.False); + }); list.Add(8); list.Add(10); - Assert.IsTrue(list.Contains(5)); - Assert.IsFalse(list.Contains(7)); - Assert.IsTrue(list.Contains(8)); - Assert.IsTrue(list.Contains(10)); + Assert.Multiple(() => + { + Assert.That(list.Contains(5), Is.True); + Assert.That(list.Contains(7), Is.False); + Assert.That(list.Contains(8), Is.True); + Assert.That(list.Contains(10), Is.True); + }); list.Remove(8); - Assert.IsTrue(list.Contains(5)); - Assert.IsFalse(list.Contains(7)); - Assert.IsFalse(list.Contains(8)); - Assert.IsTrue(list.Contains(10)); + Assert.Multiple(() => + { + Assert.That(list.Contains(5), Is.True); + Assert.That(list.Contains(7), Is.False); + Assert.That(list.Contains(8), Is.False); + Assert.That(list.Contains(10), Is.True); + }); } [Test] public void BadAdd() { - Assert.IsTrue(list.Add(5)); - Assert.IsTrue(list.Add(8)); - Assert.IsFalse(list.Add(5)); + Assert.Multiple(() => + { + Assert.That(list.Add(5), Is.True); + Assert.That(list.Add(8), Is.True); + }); + Assert.That(list.Add(5), Is.False); } [Test] public void ContainsCount() { - Assert.AreEqual(0, list.ContainsCount(5)); + Assert.That(list.ContainsCount(5), Is.EqualTo(0)); list.Add(5); - Assert.AreEqual(1, list.ContainsCount(5)); - Assert.AreEqual(0, list.ContainsCount(7)); + Assert.Multiple(() => + { + Assert.That(list.ContainsCount(5), Is.EqualTo(1)); + Assert.That(list.ContainsCount(7), Is.EqualTo(0)); + }); list.Add(8); - Assert.AreEqual(1, list.ContainsCount(5)); - Assert.AreEqual(0, list.ContainsCount(7)); - Assert.AreEqual(1, list.ContainsCount(8)); + Assert.Multiple(() => + { + Assert.That(list.ContainsCount(5), Is.EqualTo(1)); + Assert.That(list.ContainsCount(7), Is.EqualTo(0)); + Assert.That(list.ContainsCount(8), Is.EqualTo(1)); + }); } @@ -1128,14 +1190,20 @@ public void ContainsCount() public void RemoveAllCopies() { list.Add(5); list.Add(7); - Assert.AreEqual(1, list.ContainsCount(5)); - Assert.AreEqual(1, list.ContainsCount(7)); + Assert.Multiple(() => + { + Assert.That(list.ContainsCount(5), Is.EqualTo(1)); + Assert.That(list.ContainsCount(7), Is.EqualTo(1)); + }); list.RemoveAllCopies(5); - Assert.AreEqual(0, list.ContainsCount(5)); - Assert.AreEqual(1, list.ContainsCount(7)); + Assert.Multiple(() => + { + Assert.That(list.ContainsCount(5), Is.EqualTo(0)); + Assert.That(list.ContainsCount(7), Is.EqualTo(1)); + }); list.Add(5); list.Add(8); list.RemoveAllCopies(8); - Assert.IsTrue(IC.Eq(list, 7, 5)); + Assert.That(IC.Eq(list, 7, 5), Is.True); } @@ -1144,73 +1212,88 @@ public void FindAll() { bool f(int i) { return i % 2 == 0; } - Assert.IsTrue(list.FindAll(f).IsEmpty); + Assert.That(list.FindAll(f).IsEmpty, Is.True); list.Add(5); list.Add(8); list.Add(10); - Assert.IsTrue(((HashedArrayList)list.FindAll(f)).Check()); - Assert.IsTrue(IC.Eq(list.FindAll(f), 8, 10)); + Assert.Multiple(() => + { + Assert.That(((HashedArrayList)list.FindAll(f)).Check(), Is.True); + Assert.That(IC.Eq(list.FindAll(f), 8, 10), Is.True); + }); } [Test] public void ContainsAll() { - HashedArrayList list2 = new HashedArrayList(); + HashedArrayList list2 = new(); - Assert.IsTrue(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.True); list2.Add(4); - Assert.IsFalse(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.False); list.Add(4); - Assert.IsTrue(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.True); list.Add(5); - Assert.IsTrue(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.True); } [Test] public void RetainAll() { - HashedArrayList list2 = new HashedArrayList(); + HashedArrayList list2 = new(); list.Add(4); list.Add(5); list.Add(6); list2.Add(5); list2.Add(4); list2.Add(7); list.RetainAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 5)); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 5), Is.True); + }); list.Add(5); list.Add(4); list.Add(6); list2.Clear(); list2.Add(5); list2.Add(5); list2.Add(6); list.RetainAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 5, 6)); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 5, 6), Is.True); + }); list2.Clear(); list2.Add(7); list2.Add(8); list2.Add(9); list.RetainAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list), Is.True); } [Test] public void RemoveAll() { - HashedArrayList list2 = new HashedArrayList(); + HashedArrayList list2 = new(); list.Add(4); list.Add(5); list.Add(6); list2.Add(5); list2.Add(4); list2.Add(7); list.RemoveAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 6)); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 6), Is.True); + }); list.Add(5); list.Add(4); list.Add(6); list2.Clear(); list2.Add(6); list2.Add(5); list.RemoveAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4)); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4), Is.True); + }); list2.Clear(); list2.Add(7); list2.Add(8); list2.Add(9); list.RemoveAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4), Is.True); } @@ -1218,18 +1301,24 @@ public void RemoveAll() public void Remove() { list.Add(4); list.Add(5); list.Add(6); - Assert.IsFalse(list.Remove(2)); - Assert.IsTrue(list.Check()); - Assert.IsTrue(list.Remove(4)); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 5, 6)); - Assert.AreEqual(6, list.RemoveLast()); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 5)); + Assert.Multiple(() => + { + Assert.That(list.Remove(2), Is.False); + Assert.That(list.Check(), Is.True); + Assert.That(list.Remove(4), Is.True); + }); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 5, 6), Is.True); + Assert.That(list.RemoveLast(), Is.EqualTo(6)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 5), Is.True); list.Add(7); - Assert.AreEqual(5, list.RemoveFirst()); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 7)); + Assert.Multiple(() => + { + Assert.That(list.RemoveFirst(), Is.EqualTo(5)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 7), Is.True); + }); } @@ -1238,12 +1327,12 @@ public void Clear() { list.Add(7); list.Add(6); list.Clear(); - Assert.IsTrue(list.IsEmpty); + Assert.That(list.IsEmpty, Is.True); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } } @@ -1255,7 +1344,7 @@ namespace IIndexed [TestFixture] public class Searching { - private IIndexed dit; + private HashedArrayList dit; [SetUp] @@ -1268,30 +1357,36 @@ public void Init() [Test] public void IndexOf() { - Assert.AreEqual(~0, dit.IndexOf(6)); + Assert.That(dit.IndexOf(6), Is.EqualTo(~0)); dit.Add(7); - Assert.AreEqual(~1, dit.IndexOf(6)); - Assert.AreEqual(~1, dit.LastIndexOf(6)); - Assert.AreEqual(0, dit.IndexOf(7)); + Assert.Multiple(() => + { + Assert.That(dit.IndexOf(6), Is.EqualTo(~1)); + Assert.That(dit.LastIndexOf(6), Is.EqualTo(~1)); + Assert.That(dit.IndexOf(7), Is.EqualTo(0)); + }); dit.Add(5); dit.Add(7); dit.Add(8); dit.Add(7); - Assert.AreEqual(~3, dit.IndexOf(6)); - Assert.AreEqual(0, dit.IndexOf(7)); - Assert.AreEqual(0, dit.LastIndexOf(7)); - Assert.AreEqual(2, dit.IndexOf(8)); - Assert.AreEqual(1, dit.LastIndexOf(5)); + Assert.Multiple(() => + { + Assert.That(dit.IndexOf(6), Is.EqualTo(~3)); + Assert.That(dit.IndexOf(7), Is.EqualTo(0)); + Assert.That(dit.LastIndexOf(7), Is.EqualTo(0)); + Assert.That(dit.IndexOf(8), Is.EqualTo(2)); + Assert.That(dit.LastIndexOf(5), Is.EqualTo(1)); + }); } [TearDown] public void Dispose() { - dit = null; + dit.Dispose(); } } [TestFixture] public class Removing { - private IIndexed dit; + private HashedArrayList dit; [SetUp] public void Init() @@ -1303,15 +1398,18 @@ public void Init() public void RemoveAt() { dit.Add(5); dit.Add(7); dit.Add(9); dit.Add(1); dit.Add(2); - Assert.AreEqual(7, dit.RemoveAt(1)); - Assert.IsTrue(((HashedArrayList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 5, 9, 1, 2)); - Assert.AreEqual(5, dit.RemoveAt(0)); - Assert.IsTrue(((HashedArrayList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 9, 1, 2)); - Assert.AreEqual(2, dit.RemoveAt(2)); - Assert.IsTrue(((HashedArrayList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 9, 1)); + Assert.Multiple(() => + { + Assert.That(dit.RemoveAt(1), Is.EqualTo(7)); + Assert.That(((HashedArrayList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 5, 9, 1, 2), Is.True); + Assert.That(dit.RemoveAt(0), Is.EqualTo(5)); + }); + Assert.That(((HashedArrayList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 9, 1, 2), Is.True); + Assert.That(dit.RemoveAt(2), Is.EqualTo(2)); + Assert.That(((HashedArrayList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 9, 1), Is.True); } [Test] @@ -1339,30 +1437,48 @@ public void RemoveInterval() dit.RemoveInterval(0, 0); dit.Add(10); dit.Add(20); dit.Add(30); dit.Add(40); dit.Add(50); dit.Add(60); dit.RemoveInterval(3, 0); - Assert.IsTrue(((HashedArrayList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 10, 20, 30, 40, 50, 60)); + Assert.Multiple(() => + { + Assert.That(((HashedArrayList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 10, 20, 30, 40, 50, 60), Is.True); + }); dit.RemoveInterval(3, 1); - Assert.IsTrue(((HashedArrayList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 10, 20, 30, 50, 60)); + Assert.Multiple(() => + { + Assert.That(((HashedArrayList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 10, 20, 30, 50, 60), Is.True); + }); dit.RemoveInterval(1, 3); - Assert.IsTrue(((HashedArrayList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 10, 60)); + Assert.Multiple(() => + { + Assert.That(((HashedArrayList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 10, 60), Is.True); + }); dit.RemoveInterval(0, 2); - Assert.IsTrue(((HashedArrayList)dit).Check()); - Assert.IsTrue(IC.Eq(dit)); + Assert.Multiple(() => + { + Assert.That(((HashedArrayList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit), Is.True); + }); dit.Add(10); dit.Add(20); dit.Add(30); dit.Add(40); dit.Add(50); dit.Add(60); dit.RemoveInterval(0, 2); - Assert.IsTrue(((HashedArrayList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 30, 40, 50, 60)); + Assert.Multiple(() => + { + Assert.That(((HashedArrayList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 30, 40, 50, 60), Is.True); + }); dit.RemoveInterval(2, 2); - Assert.IsTrue(((HashedArrayList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 30, 40)); + Assert.Multiple(() => + { + Assert.That(((HashedArrayList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 30, 40), Is.True); + }); } [TearDown] public void Dispose() { - dit = null; + dit.Dispose(); } } } @@ -1379,7 +1495,7 @@ public class Searching [TearDown] - public void Dispose() { lst = null; } + public void Dispose() { lst.Dispose(); } [Test] public void FirstBad() @@ -1403,11 +1519,17 @@ public void LastBad() public void FirstLast() { lst.Add(19); - Assert.AreEqual(19, lst.First); - Assert.AreEqual(19, lst.Last); + Assert.Multiple(() => + { + Assert.That(lst.First, Is.EqualTo(19)); + Assert.That(lst.Last, Is.EqualTo(19)); + }); lst.Add(34); lst.InsertFirst(12); - Assert.AreEqual(12, lst.First); - Assert.AreEqual(34, lst.Last); + Assert.Multiple(() => + { + Assert.That(lst.First, Is.EqualTo(12)); + Assert.That(lst.Last, Is.EqualTo(34)); + }); } @@ -1415,48 +1537,57 @@ public void FirstLast() public void This() { lst.Add(34); - Assert.AreEqual(34, lst[0]); + Assert.That(lst[0], Is.EqualTo(34)); lst[0] = 56; - Assert.AreEqual(56, lst.First); + Assert.That(lst.First, Is.EqualTo(56)); lst.Add(7); lst.Add(77); lst.Add(777); lst.Add(7777); lst[0] = 45; lst[2] = 78; lst[4] = 101; - Assert.IsTrue(IC.Eq(lst, 45, 7, 78, 777, 101)); + Assert.That(IC.Eq(lst, 45, 7, 78, 777, 101), Is.True); } [Test] public void ThisWithUpdates() { - HashedArrayList> pairlist = new HashedArrayList>(new KeyValuePairEqualityComparer()) + HashedArrayList> pairlist = new(new KeyValuePairEqualityComparer()) { - new System.Collections.Generic.KeyValuePair(10, 50), - new System.Collections.Generic.KeyValuePair(11, 51), - new System.Collections.Generic.KeyValuePair(12, 52), - new System.Collections.Generic.KeyValuePair(13, 53) + new SCG.KeyValuePair(10, 50), + new SCG.KeyValuePair(11, 51), + new SCG.KeyValuePair(12, 52), + new SCG.KeyValuePair(13, 53) }; - pairlist[2] = new System.Collections.Generic.KeyValuePair(12, 102); - Assert.IsTrue(pairlist.Check()); - Assert.AreEqual(new System.Collections.Generic.KeyValuePair(12, 102), pairlist[2]); - pairlist[2] = new System.Collections.Generic.KeyValuePair(22, 202); - Assert.IsTrue(pairlist.Check()); - Assert.AreEqual(new System.Collections.Generic.KeyValuePair(22, 202), pairlist[2]); - pairlist[1] = new System.Collections.Generic.KeyValuePair(12, 303); - Assert.IsTrue(pairlist.Check()); - Assert.AreEqual(new System.Collections.Generic.KeyValuePair(12, 303), pairlist[1]); - Assert.AreEqual(new System.Collections.Generic.KeyValuePair(22, 202), pairlist[2]); + pairlist[2] = new SCG.KeyValuePair(12, 102); + Assert.Multiple(() => + { + Assert.That(pairlist.Check(), Is.True); + Assert.That(pairlist[2], Is.EqualTo(new SCG.KeyValuePair(12, 102))); + }); + pairlist[2] = new SCG.KeyValuePair(22, 202); + Assert.Multiple(() => + { + Assert.That(pairlist.Check(), Is.True); + Assert.That(pairlist[2], Is.EqualTo(new SCG.KeyValuePair(22, 202))); + }); + pairlist[1] = new SCG.KeyValuePair(12, 303); + Assert.Multiple(() => + { + Assert.That(pairlist.Check(), Is.True); + Assert.That(pairlist[1], Is.EqualTo(new SCG.KeyValuePair(12, 303))); + Assert.That(pairlist[2], Is.EqualTo(new SCG.KeyValuePair(22, 202))); + }); } [Test] public void ThisWithUpdatesBad() { - HashedArrayList> pairlist = new HashedArrayList>(new KeyValuePairEqualityComparer()) + HashedArrayList> pairlist = new(new KeyValuePairEqualityComparer()) { - new System.Collections.Generic.KeyValuePair(10, 50), - new System.Collections.Generic.KeyValuePair(11, 51), - new System.Collections.Generic.KeyValuePair(12, 52), - new System.Collections.Generic.KeyValuePair(13, 53) + new SCG.KeyValuePair(10, 50), + new SCG.KeyValuePair(11, 51), + new SCG.KeyValuePair(12, 52), + new SCG.KeyValuePair(13, 53) }; - Assert.Throws(() => pairlist[2] = new System.Collections.Generic.KeyValuePair(11, 102)); + Assert.Throws(() => pairlist[2] = new SCG.KeyValuePair(11, 102)); } [Test] @@ -1519,28 +1650,28 @@ public class Inserting public void Init() { lst = new HashedArrayList(); } [TearDown] - public void Dispose() { lst = null; } + public void Dispose() { lst.Dispose(); } [Test] public void Insert() { lst.Insert(0, 5); - Assert.IsTrue(IC.Eq(lst, 5)); + Assert.That(IC.Eq(lst, 5), Is.True); lst.Insert(0, 7); - Assert.IsTrue(IC.Eq(lst, 7, 5)); + Assert.That(IC.Eq(lst, 7, 5), Is.True); lst.Insert(1, 4); - Assert.IsTrue(IC.Eq(lst, 7, 4, 5)); + Assert.That(IC.Eq(lst, 7, 4, 5), Is.True); lst.Insert(3, 2); - Assert.IsTrue(IC.Eq(lst, 7, 4, 5, 2)); + Assert.That(IC.Eq(lst, 7, 4, 5, 2), Is.True); } [Test] public void InsertDuplicate() { lst.Insert(0, 5); - Assert.IsTrue(IC.Eq(lst, 5)); + Assert.That(IC.Eq(lst, 5), Is.True); lst.Insert(0, 7); - Assert.IsTrue(IC.Eq(lst, 7, 5)); + Assert.That(IC.Eq(lst, 7, 5), Is.True); Assert.Throws(() => lst.Insert(1, 5)); } @@ -1549,36 +1680,44 @@ public void InsertDuplicate() public void InsertAllDuplicate1() { lst.Insert(0, 3); - Assert.IsTrue(IC.Eq(lst, 3)); + Assert.That(IC.Eq(lst, 3), Is.True); lst.Insert(0, 7); - Assert.IsTrue(IC.Eq(lst, 7, 3)); + Assert.That(IC.Eq(lst, 7, 3), Is.True); try { - lst.InsertAll(1, new int[] { 1, 2, 3, 4 }); + lst.InsertAll(1, [1, 2, 3, 4]); } catch (DuplicateNotAllowedException) { } - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 1, 2, 3)); + + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 1, 2, 3), Is.True); + }); } [Test] public void InsertAllDuplicate2() { lst.Insert(0, 3); - Assert.IsTrue(IC.Eq(lst, 3)); + Assert.That(IC.Eq(lst, 3), Is.True); lst.Insert(0, 7); - Assert.IsTrue(IC.Eq(lst, 7, 3)); + Assert.That(IC.Eq(lst, 7, 3), Is.True); try { - lst.InsertAll(1, new int[] { 5, 6, 5, 8 }); + lst.InsertAll(1, [5, 6, 5, 8]); } catch (DuplicateNotAllowedException) { } - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 5, 6, 3)); + + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 5, 6, 3), Is.True); + }); } [Test] @@ -1603,15 +1742,19 @@ public void FIFO() { lst.Add(2 * i); } - Assert.IsFalse(lst.FIFO); - Assert.AreEqual(12, lst.Remove()); - Assert.AreEqual(10, lst.Remove()); + + Assert.Multiple(() => + { + Assert.That(lst.FIFO, Is.False); + Assert.That(lst.Remove(), Is.EqualTo(12)); + }); + Assert.That(lst.Remove(), Is.EqualTo(10)); lst.FIFO = true; - Assert.AreEqual(0, lst.Remove()); - Assert.AreEqual(2, lst.Remove()); + Assert.That(lst.Remove(), Is.EqualTo(0)); + Assert.That(lst.Remove(), Is.EqualTo(2)); lst.FIFO = false; - Assert.AreEqual(8, lst.Remove()); - Assert.AreEqual(6, lst.Remove()); + Assert.That(lst.Remove(), Is.EqualTo(8)); + Assert.That(lst.Remove(), Is.EqualTo(6)); } [Test] @@ -1625,7 +1768,7 @@ public void InsertFirstLast() lst.InsertLast(25); lst.InsertFirst(34); lst.InsertLast(55); - Assert.IsTrue(IC.Eq(lst, 34, 24, 14, 4, 5, 15, 25, 55)); + Assert.That(IC.Eq(lst, 34, 24, 14, 4, 5, 15, 25, 55), Is.True); } @@ -1637,14 +1780,23 @@ public void InsertFirst() lst.Add(4); lst.Add(5); lst.ViewOf(2).InsertFirst(7); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 2, 3, 4, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 2, 3, 4, 5), Is.True); + }); lst.ViewOf(3).InsertFirst(8); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 2, 8, 3, 4, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 2, 8, 3, 4, 5), Is.True); + }); lst.ViewOf(5).InsertFirst(9); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 2, 8, 3, 4, 9, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 2, 8, 3, 4, 9, 5), Is.True); + }); } [Test] @@ -1654,7 +1806,7 @@ public void BadFirst() lst.Add(3); lst.Add(2); lst.Add(5); - Assert.IsNull(lst.ViewOf(4)); + Assert.That(lst.ViewOf(4), Is.Null); } [Test] @@ -1666,14 +1818,23 @@ public void InsertAfter() lst.Add(4); lst.Add(5); lst.LastViewOf(2).InsertLast(7); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 1, 2, 7, 3, 4, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 1, 2, 7, 3, 4, 5), Is.True); + }); lst.LastViewOf(1).InsertLast(8); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 1, 8, 2, 7, 3, 4, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 1, 8, 2, 7, 3, 4, 5), Is.True); + }); lst.LastViewOf(5).InsertLast(9); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 1, 8, 2, 7, 3, 4, 5, 9)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 1, 8, 2, 7, 3, 4, 5, 9), Is.True); + }); } [Test] @@ -1683,7 +1844,7 @@ public void BadInsertAfter() lst.Add(3); lst.Add(6); lst.Add(5); - Assert.IsNull(lst.ViewOf(4)); + Assert.That(lst.ViewOf(4), Is.Null); } [Test] @@ -1701,16 +1862,25 @@ public void InsertAll() 9 }; lst.InsertAll(0, lst2); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 1, 2, 3, 4)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 1, 2, 3, 4), Is.True); + }); lst.RemoveAll(lst2); lst.InsertAll(4, lst2); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 1, 2, 3, 4, 7, 8, 9)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 1, 2, 3, 4, 7, 8, 9), Is.True); + }); lst.RemoveAll(lst2); lst.InsertAll(2, lst2); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 1, 2, 7, 8, 9, 3, 4)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 1, 2, 7, 8, 9, 3, 4), Is.True); + }); } [Test] @@ -1737,18 +1907,24 @@ public void Map() string m(int i) { return "<<" + i + ">>"; } IList r = lst.Map(m); - Assert.IsTrue(((HashedArrayList)r).Check()); - Assert.IsTrue(r.IsEmpty); + Assert.Multiple(() => + { + Assert.That(((HashedArrayList)r).Check(), Is.True); + Assert.That(r.IsEmpty, Is.True); + }); lst.Add(1); lst.Add(2); lst.Add(3); lst.Add(4); r = lst.Map(m); - Assert.IsTrue(((HashedArrayList)r).Check()); - Assert.AreEqual(4, r.Count); + Assert.Multiple(() => + { + Assert.That(((HashedArrayList)r).Check(), Is.True); + Assert.That(r, Has.Count.EqualTo(4)); + }); for (int i = 0; i < 4; i++) { - Assert.AreEqual("<<" + (i + 1) + ">>", r[i]); + Assert.That(r[i], Is.EqualTo("<<" + (i + 1) + ">>")); } } [Test] @@ -1823,11 +1999,14 @@ public void RemoveFirstLast() lst.Add(2); lst.Add(3); lst.Add(4); - Assert.AreEqual(1, lst.RemoveFirst()); - Assert.AreEqual(4, lst.RemoveLast()); - Assert.AreEqual(2, lst.RemoveFirst()); - Assert.AreEqual(3, lst.RemoveLast()); - Assert.IsTrue(lst.IsEmpty); + Assert.Multiple(() => + { + Assert.That(lst.RemoveFirst(), Is.EqualTo(1)); + Assert.That(lst.RemoveLast(), Is.EqualTo(4)); + }); + Assert.That(lst.RemoveFirst(), Is.EqualTo(2)); + Assert.That(lst.RemoveLast(), Is.EqualTo(3)); + Assert.That(lst.IsEmpty, Is.True); } @@ -1840,20 +2019,35 @@ public void Reverse() } lst.Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0), Is.True); + }); lst.View(0, 3).Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0), Is.True); + }); lst.View(7, 0).Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0), Is.True); + }); lst.View(7, 3).Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2), Is.True); + }); lst.View(5, 1).Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2), Is.True); + }); } @@ -1872,105 +2066,129 @@ public void BadReverse() [TestFixture] public class Combined { - private IList> lst; + private IList> lst; [SetUp] public void Init() { - lst = new HashedArrayList>(new KeyValuePairEqualityComparer()); + lst = new HashedArrayList>(new KeyValuePairEqualityComparer()); for (int i = 0; i < 10; i++) { - lst.Add(new System.Collections.Generic.KeyValuePair(i, i + 30)); + lst.Add(new SCG.KeyValuePair(i, i + 30)); } } [TearDown] public void Dispose() { - lst = null; + lst.Dispose(); } [Test] public void Find() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Find(ref p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); - p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Find(ref p)); + Assert.Multiple(() => + { + Assert.That(lst.Find(ref p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); + p = new SCG.KeyValuePair(13, 78); + Assert.That(lst.Find(ref p), Is.False); } [Test] public void FindOrAdd() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.FindOrAdd(ref p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); - p = new System.Collections.Generic.KeyValuePair(13, 79); - Assert.IsFalse(lst.FindOrAdd(ref p)); - Assert.AreEqual(13, lst[10].Key); - Assert.AreEqual(79, lst[10].Value); + Assert.Multiple(() => + { + Assert.That(lst.FindOrAdd(ref p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); + p = new SCG.KeyValuePair(13, 79); + Assert.Multiple(() => + { + Assert.That(lst.FindOrAdd(ref p), Is.False); + Assert.That(lst[10].Key, Is.EqualTo(13)); + Assert.That(lst[10].Value, Is.EqualTo(79)); + }); } [Test] public void Update() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Update(p)); - Assert.AreEqual(3, lst[3].Key); - Assert.AreEqual(78, lst[3].Value); - p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Update(p)); + Assert.Multiple(() => + { + Assert.That(lst.Update(p), Is.True); + Assert.That(lst[3].Key, Is.EqualTo(3)); + Assert.That(lst[3].Value, Is.EqualTo(78)); + }); + p = new SCG.KeyValuePair(13, 78); + Assert.That(lst.Update(p), Is.False); } [Test] public void UpdateOrAdd1() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.UpdateOrAdd(p)); - Assert.AreEqual(3, lst[3].Key); - Assert.AreEqual(78, lst[3].Value); - p = new System.Collections.Generic.KeyValuePair(13, 79); - Assert.IsFalse(lst.UpdateOrAdd(p)); - Assert.AreEqual(13, lst[10].Key); - Assert.AreEqual(79, lst[10].Value); + Assert.Multiple(() => + { + Assert.That(lst.UpdateOrAdd(p), Is.True); + Assert.That(lst[3].Key, Is.EqualTo(3)); + Assert.That(lst[3].Value, Is.EqualTo(78)); + }); + p = new SCG.KeyValuePair(13, 79); + Assert.Multiple(() => + { + Assert.That(lst.UpdateOrAdd(p), Is.False); + Assert.That(lst[10].Key, Is.EqualTo(13)); + Assert.That(lst[10].Value, Is.EqualTo(79)); + }); } [Test] public void UpdateOrAdd2() { - ICollection coll = new HashedArrayList(); + ICollection coll = new HashedArrayList(); // s1 and s2 are distinct objects but contain the same text: - String s1 = "abc", s2 = ("def" + s1).Substring(3); - Assert.IsFalse(coll.UpdateOrAdd(s1, out string old)); - Assert.AreEqual(null, old); - Assert.IsTrue(coll.UpdateOrAdd(s2, out old)); - Assert.IsTrue(Object.ReferenceEquals(s1, old)); - Assert.IsFalse(Object.ReferenceEquals(s2, old)); + string s1 = "abc", s2 = ("def" + s1).Substring(3); + Assert.Multiple(() => + { + Assert.That(coll.UpdateOrAdd(s1, out string old), Is.False); + Assert.That(old, Is.EqualTo(null)); + Assert.That(coll.UpdateOrAdd(s2, out old), Is.True); + Assert.That(ReferenceEquals(s1, old), Is.True); + Assert.That(ReferenceEquals(s2, old), Is.False); + }); } [Test] public void RemoveWithReturn() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Remove(p, out p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); - Assert.AreEqual(4, lst[3].Key); - Assert.AreEqual(34, lst[3].Value); - p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Remove(p, out _)); + Assert.Multiple(() => + { + Assert.That(lst.Remove(p, out p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + Assert.That(lst[3].Key, Is.EqualTo(4)); + Assert.That(lst[3].Value, Is.EqualTo(34)); + }); + p = new SCG.KeyValuePair(13, 78); + Assert.That(lst.Remove(p, out _), Is.False); } } @@ -1986,18 +2204,21 @@ public class Sorting [TearDown] - public void Dispose() { lst = null; } + public void Dispose() { lst.Dispose(); } [Test] public void Sort() { lst.Add(5); lst.Add(6); lst.Add(55); lst.Add(7); lst.Add(3); - Assert.IsFalse(lst.IsSorted(new IC())); + Assert.That(lst.IsSorted(new IC()), Is.False); lst.Sort(new IC()); - Assert.IsTrue(lst.IsSorted()); - Assert.IsTrue(lst.IsSorted(new IC())); - Assert.IsTrue(IC.Eq(lst, 3, 5, 6, 7, 55)); + Assert.Multiple(() => + { + Assert.That(lst.IsSorted(), Is.True); + Assert.That(lst.IsSorted(new IC()), Is.True); + Assert.That(IC.Eq(lst, 3, 5, 6, 7, 55), Is.True); + }); } } } @@ -2010,7 +2231,7 @@ namespace Range [TestFixture] public class Range { - private IList lst; + private HashedArrayList lst; [SetUp] @@ -2018,7 +2239,7 @@ public class Range [TearDown] - public void Dispose() { lst = null; } + public void Dispose() { lst.Dispose(); } [Test] @@ -2030,10 +2251,13 @@ public void GetRange() lst.Add(i); } - Assert.IsTrue(IC.Eq(lst[0, 3], 0, 1, 2)); - Assert.IsTrue(IC.Eq(lst[3, 3], 3, 4, 5)); - Assert.IsTrue(IC.Eq(lst[6, 3], 6, 7, 8)); - Assert.IsTrue(IC.Eq(lst[6, 4], 6, 7, 8, 9)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(lst[0, 3], 0, 1, 2), Is.True); + Assert.That(IC.Eq(lst[3, 3], 3, 4, 5), Is.True); + Assert.That(IC.Eq(lst[6, 3], 6, 7, 8), Is.True); + Assert.That(IC.Eq(lst[6, 4], 6, 7, 8, 9), Is.True); + }); } @@ -2045,10 +2269,13 @@ public void Backwards() lst.Add(i); } - Assert.IsTrue(IC.Eq(lst.Backwards(), 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); - Assert.IsTrue(IC.Eq(lst[0, 3].Backwards(), 2, 1, 0)); - Assert.IsTrue(IC.Eq(lst[3, 3].Backwards(), 5, 4, 3)); - Assert.IsTrue(IC.Eq(lst[6, 4].Backwards(), 9, 8, 7, 6)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(lst.Backwards(), 9, 8, 7, 6, 5, 4, 3, 2, 1, 0), Is.True); + Assert.That(IC.Eq(lst[0, 3].Backwards(), 2, 1, 0), Is.True); + Assert.That(IC.Eq(lst[3, 3].Backwards(), 5, 4, 3), Is.True); + Assert.That(IC.Eq(lst[6, 4].Backwards(), 9, 8, 7, 6), Is.True); + }); } @@ -2060,13 +2287,19 @@ public void DirectionAndCount() lst.Add(i); } - Assert.AreEqual(Direction.Forwards, lst.Direction); - Assert.AreEqual(Direction.Forwards, lst[3, 4].Direction); - Assert.AreEqual(Direction.Backwards, lst[3, 4].Backwards().Direction); - Assert.AreEqual(Direction.Backwards, lst.Backwards().Direction); - Assert.AreEqual(4, lst[3, 4].Count); - Assert.AreEqual(4, lst[3, 4].Backwards().Count); - Assert.AreEqual(10, lst.Backwards().Count); + Assert.Multiple(() => + { + Assert.That(lst.Direction, Is.EqualTo(Direction.Forwards)); + Assert.That(lst[3, 4].Direction, Is.EqualTo(Direction.Forwards)); + Assert.That(lst[3, 4].Backwards().Direction, Is.EqualTo(Direction.Backwards)); + Assert.That(lst.Backwards().Direction, Is.EqualTo(Direction.Backwards)); + Assert.That(lst[3, 4], Has.Count.EqualTo(4)); + }); + Assert.Multiple(() => + { + Assert.That(lst[3, 4].Backwards(), Has.Count.EqualTo(4)); + Assert.That(lst.Backwards(), Has.Count.EqualTo(10)); + }); } [Test] @@ -2114,14 +2347,17 @@ public void Init() [TearDown] public void Dispose() { - list = null; - view = null; + list.Dispose(); + view.Dispose(); } private void check() { - Assert.IsTrue(list.Check()); - Assert.IsTrue(view.Check()); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(view.Check(), Is.True); + }); } [Test] @@ -2138,8 +2374,11 @@ public void InsertPointer() check(); view.Insert(list.ViewOf(0), 11); check(); - Assert.IsTrue(IC.Eq(list, 0, 11, 1, 9, 7, 2, 10, 3, 8)); - Assert.IsTrue(IC.Eq(view, 11, 1, 9, 7, 2, 10)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 11, 1, 9, 7, 2, 10, 3, 8), Is.True); + Assert.That(IC.Eq(view, 11, 1, 9, 7, 2, 10), Is.True); + }); } [Test] @@ -2170,15 +2409,21 @@ public void InsertPointerBad4() public void Span() { IList span = list.View(1, 0).Span(list.View(2, 0)); - Assert.IsTrue(span.Check()); - Assert.AreEqual(1, span.Offset); - Assert.AreEqual(1, span.Count); + Assert.Multiple(() => + { + Assert.That(span.Check(), Is.True); + Assert.That(span.Offset, Is.EqualTo(1)); + Assert.That(span, Has.Count.EqualTo(1)); + }); span = list.View(0, 2).Span(list.View(2, 2)); - Assert.IsTrue(span.Check()); - Assert.AreEqual(0, span.Offset); - Assert.AreEqual(4, span.Count); + Assert.Multiple(() => + { + Assert.That(span.Check(), Is.True); + Assert.That(span.Offset, Is.EqualTo(0)); + Assert.That(span, Has.Count.EqualTo(4)); + }); span = list.View(3, 1).Span(list.View(1, 1)); - Assert.IsNull(span); + Assert.That(span, Is.Null); } [Test] @@ -2190,38 +2435,50 @@ public void ViewOf() } IList v = view.ViewOf(2); - Assert.IsTrue(v.Check()); - Assert.IsTrue(IC.Eq(v, 2)); - Assert.AreEqual(2, v.Offset); + Assert.Multiple(() => + { + Assert.That(v.Check(), Is.True); + Assert.That(IC.Eq(v, 2), Is.True); + Assert.That(v.Offset, Is.EqualTo(2)); + }); v = list.ViewOf(2); - Assert.IsTrue(v.Check()); - Assert.IsTrue(IC.Eq(v, 2)); - Assert.AreEqual(2, v.Offset); + Assert.Multiple(() => + { + Assert.That(v.Check(), Is.True); + Assert.That(IC.Eq(v, 2), Is.True); + Assert.That(v.Offset, Is.EqualTo(2)); + }); v = list.LastViewOf(2); - Assert.IsTrue(v.Check()); - Assert.IsTrue(IC.Eq(v, 2)); - Assert.AreEqual(2, v.Offset); + Assert.Multiple(() => + { + Assert.That(v.Check(), Is.True); + Assert.That(IC.Eq(v, 2), Is.True); + Assert.That(v.Offset, Is.EqualTo(2)); + }); } [Test] public void BadViewOf() { - Assert.IsNull(view.ViewOf(5)); - Assert.IsNull(view.LastViewOf(5)); - Assert.IsNull(view.ViewOf(3)); - Assert.IsNull(view.LastViewOf(3)); - Assert.IsNull(view.ViewOf(0)); - Assert.IsNull(view.LastViewOf(0)); + Assert.Multiple(() => + { + Assert.That(view.ViewOf(5), Is.Null); + Assert.That(view.LastViewOf(5), Is.Null); + Assert.That(view.ViewOf(3), Is.Null); + Assert.That(view.LastViewOf(3), Is.Null); + Assert.That(view.ViewOf(0), Is.Null); + Assert.That(view.LastViewOf(0), Is.Null); + }); } [Test] public void ArrayStuff() { - Assert.IsTrue(IC.Eq(view.ToArray(), 1, 2)); + Assert.That(IC.Eq(view.ToArray(), 1, 2), Is.True); int[] extarray = new int[5]; view.CopyTo(extarray, 2); - Assert.IsTrue(IC.Eq(extarray, 0, 0, 1, 2, 0)); + Assert.That(IC.Eq(extarray, 0, 0, 1, 2, 0), Is.True); } @@ -2229,87 +2486,126 @@ public void ArrayStuff() public void Add() { check(); - Assert.IsTrue(IC.Eq(list, 0, 1, 2, 3)); - Assert.IsTrue(IC.Eq(view, 1, 2)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 1, 2, 3), Is.True); + Assert.That(IC.Eq(view, 1, 2), Is.True); + }); view.InsertFirst(10); check(); - Assert.IsTrue(IC.Eq(list, 0, 10, 1, 2, 3)); - Assert.IsTrue(IC.Eq(view, 10, 1, 2)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 10, 1, 2, 3), Is.True); + Assert.That(IC.Eq(view, 10, 1, 2), Is.True); + }); view.Clear(); - Assert.IsFalse(view.IsReadOnly); - Assert.IsFalse(view.AllowsDuplicates); - Assert.IsTrue(view.IsEmpty); + Assert.Multiple(() => + { + Assert.That(view.IsReadOnly, Is.False); + Assert.That(view.AllowsDuplicates, Is.False); + Assert.That(view.IsEmpty, Is.True); + }); check(); - Assert.IsTrue(IC.Eq(list, 0, 3)); - Assert.IsTrue(IC.Eq(view)); + Assert.That(IC.Eq(list, 0, 3), Is.True); + Assert.That(IC.Eq(view), Is.True); view.Add(8); - Assert.IsFalse(view.IsEmpty); - Assert.IsFalse(view.AllowsDuplicates); - Assert.IsFalse(view.IsReadOnly); + Assert.That(view.IsEmpty, Is.False); + Assert.That(view.AllowsDuplicates, Is.False); + Assert.That(view.IsReadOnly, Is.False); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 3)); - Assert.IsTrue(IC.Eq(view, 8)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 3), Is.True); + Assert.That(IC.Eq(view, 8), Is.True); + }); view.Add(12); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 12, 3)); - Assert.IsTrue(IC.Eq(view, 8, 12)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 12, 3), Is.True); + Assert.That(IC.Eq(view, 8, 12), Is.True); + }); view./*ViewOf(12).*/InsertLast(15); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 12, 15, 3)); - Assert.IsTrue(IC.Eq(view, 8, 12, 15)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 12, 15, 3), Is.True); + Assert.That(IC.Eq(view, 8, 12, 15), Is.True); + }); view.ViewOf(12).InsertFirst(18); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 18, 12, 15, 3)); - Assert.IsTrue(IC.Eq(view, 8, 18, 12, 15)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 18, 12, 15, 3), Is.True); + Assert.That(IC.Eq(view, 8, 18, 12, 15), Is.True); + }); - HashedArrayList lst2 = new HashedArrayList + HashedArrayList lst2 = new() { 90, 92 }; view.AddAll(lst2); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 18, 12, 15, 90, 92, 3)); - Assert.IsTrue(IC.Eq(view, 8, 18, 12, 15, 90, 92)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 18, 12, 15, 90, 92, 3), Is.True); + Assert.That(IC.Eq(view, 8, 18, 12, 15, 90, 92), Is.True); + }); view.InsertLast(66); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 18, 12, 15, 90, 92, 66, 3)); - Assert.IsTrue(IC.Eq(view, 8, 18, 12, 15, 90, 92, 66)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 18, 12, 15, 90, 92, 66, 3), Is.True); + Assert.That(IC.Eq(view, 8, 18, 12, 15, 90, 92, 66), Is.True); + }); } [Test] public void Bxxx() { - Assert.IsTrue(IC.Eq(view.Backwards(), 2, 1)); - Assert.AreSame(list, view.Underlying); - Assert.IsNull(list.Underlying); - Assert.AreEqual(Direction.Forwards, view.Direction); - Assert.AreEqual(Direction.Backwards, view.Backwards().Direction); - Assert.AreEqual(0, list.Offset); - Assert.AreEqual(1, view.Offset); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view.Backwards(), 2, 1), Is.True); + Assert.That(view.Underlying, Is.SameAs(list)); + Assert.That(list.Underlying, Is.Null); + Assert.That(view.Direction, Is.EqualTo(Direction.Forwards)); + Assert.That(view.Backwards().Direction, Is.EqualTo(Direction.Backwards)); + Assert.That(list.Offset, Is.EqualTo(0)); + Assert.That(view.Offset, Is.EqualTo(1)); + }); } [Test] public void Contains() { - Assert.IsTrue(view.Contains(1)); - Assert.IsFalse(view.Contains(0)); + Assert.Multiple(() => + { + Assert.That(view.Contains(1), Is.True); + Assert.That(view.Contains(0), Is.False); + }); - HashedArrayList lst2 = new HashedArrayList + HashedArrayList lst2 = new() { 2 }; - Assert.IsTrue(view.ContainsAll(lst2)); + Assert.That(view.ContainsAll(lst2), Is.True); lst2.Add(3); - Assert.IsFalse(view.ContainsAll(lst2)); - Assert.AreEqual(Speed.Constant, view.ContainsSpeed); - Assert.AreEqual(2, view.Count); + Assert.Multiple(() => + { + Assert.That(view.ContainsAll(lst2), Is.False); + Assert.That(view.ContainsSpeed, Is.EqualTo(Speed.Constant)); + Assert.That(view, Has.Count.EqualTo(2)); + }); view.Add(1); - Assert.AreEqual(1, view.ContainsCount(2)); - Assert.AreEqual(1, view.ContainsCount(1)); - Assert.AreEqual(2, view.Count); + Assert.Multiple(() => + { + Assert.That(view.ContainsCount(2), Is.EqualTo(1)); + Assert.That(view.ContainsCount(1), Is.EqualTo(1)); + Assert.That(view, Has.Count.EqualTo(2)); + }); } @@ -2318,26 +2614,32 @@ public void CreateView() { HashedArrayList view2 = (HashedArrayList)view.View(1, 0); - Assert.AreSame(list, view2.Underlying); + Assert.That(view2.Underlying, Is.SameAs(list)); } [Test] public void FIFO() { - Assert.IsFalse(view.FIFO); + Assert.That(view.FIFO, Is.False); view.FIFO = true; view.Add(23); view.Add(24); view.Add(25); check(); - Assert.IsTrue(IC.Eq(view, 1, 2, 23, 24, 25)); - Assert.AreEqual(1, view.Remove()); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 1, 2, 23, 24, 25), Is.True); + Assert.That(view.Remove(), Is.EqualTo(1)); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 23, 24, 25)); + Assert.That(IC.Eq(view, 2, 23, 24, 25), Is.True); view.FIFO = false; - Assert.IsFalse(view.FIFO); - Assert.AreEqual(25, view.Remove()); + Assert.Multiple(() => + { + Assert.That(view.FIFO, Is.False); + Assert.That(view.Remove(), Is.EqualTo(25)); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 23, 24)); + Assert.That(IC.Eq(view, 2, 23, 24), Is.True); } @@ -2346,9 +2648,12 @@ public void MapEtc() { HashedArrayList dbl = (HashedArrayList)view.Map(new Func(delegate (int i) { return i / 10.0; })); - Assert.IsTrue(dbl.Check()); - Assert.AreEqual(0.1, dbl[0]); - Assert.AreEqual(0.2, dbl[1]); + Assert.Multiple(() => + { + Assert.That(dbl.Check(), Is.True); + Assert.That(dbl[0], Is.EqualTo(0.1)); + Assert.That(dbl[1], Is.EqualTo(0.2)); + }); for (int i = 0; i < 10; i++) { view.Add(i); @@ -2356,16 +2661,22 @@ public void MapEtc() HashedArrayList list2 = (HashedArrayList)view.FindAll(new Func(delegate (int i) { return i % 4 == 1; })); - Assert.IsTrue(list2.Check()); - Assert.IsTrue(IC.Eq(list2, 1, 5, 9)); + Assert.Multiple(() => + { + Assert.That(list2.Check(), Is.True); + Assert.That(IC.Eq(list2, 1, 5, 9), Is.True); + }); } [Test] public void FL() { - Assert.AreEqual(1, view.First); - Assert.AreEqual(2, view.Last); + Assert.Multiple(() => + { + Assert.That(view.First, Is.EqualTo(1)); + Assert.That(view.Last, Is.EqualTo(2)); + }); } @@ -2381,17 +2692,17 @@ public void Indexing() view = (HashedArrayList)list.View(5, 7); for (int i = 0; i < 7; i++) { - Assert.AreEqual(i + 5, view[i]); + Assert.That(view[i], Is.EqualTo(i + 5)); } for (int i = 0; i < 7; i++) { - Assert.AreEqual(i, view.IndexOf(i + 5)); + Assert.That(view.IndexOf(i + 5), Is.EqualTo(i)); } for (int i = 0; i < 7; i++) { - Assert.AreEqual(i, view.LastIndexOf(i + 5)); + Assert.That(view.LastIndexOf(i + 5), Is.EqualTo(i)); } } @@ -2402,8 +2713,11 @@ public void Insert() view.Insert(0, 34); view.Insert(1, 35); view.Insert(4, 36); - Assert.IsTrue(view.Check()); - Assert.IsTrue(IC.Eq(view, 34, 35, 1, 2, 36)); + Assert.Multiple(() => + { + Assert.That(view.Check(), Is.True); + Assert.That(IC.Eq(view, 34, 35, 1, 2, 36), Is.True); + }); IList list2 = new HashedArrayList { @@ -2411,8 +2725,11 @@ public void Insert() 41 }; view.InsertAll(3, list2); - Assert.IsTrue(view.Check()); - Assert.IsTrue(IC.Eq(view, 34, 35, 1, 40, 41, 2, 36)); + Assert.Multiple(() => + { + Assert.That(view.Check(), Is.True); + Assert.That(IC.Eq(view, 34, 35, 1, 40, 41, 2, 36), Is.True); + }); } @@ -2420,11 +2737,14 @@ public void Insert() public void Sort() { view.Add(45); view.Add(47); view.Add(46); view.Add(48); - Assert.IsFalse(view.IsSorted(new IC())); + Assert.That(view.IsSorted(new IC()), Is.False); view.Sort(new IC()); check(); - Assert.IsTrue(IC.Eq(list, 0, 1, 2, 45, 46, 47, 48, 3)); - Assert.IsTrue(IC.Eq(view, 1, 2, 45, 46, 47, 48)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 1, 2, 45, 46, 47, 48, 3), Is.True); + Assert.That(IC.Eq(view, 1, 2, 45, 46, 47, 48), Is.True); + }); } @@ -2432,24 +2752,36 @@ public void Sort() public void Remove() { view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0); - Assert.IsTrue(IC.Eq(view, 1, 2, 5)); - Assert.IsTrue(view.Remove(1)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 1, 2, 5), Is.True); + Assert.That(view.Remove(1), Is.True); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 5)); - Assert.IsFalse(view.Remove(1)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 2, 5), Is.True); + Assert.That(view.Remove(1), Is.False); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 5)); - Assert.IsFalse(view.Remove(0)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 2, 5), Is.True); + Assert.That(view.Remove(0), Is.False); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 5)); + Assert.That(IC.Eq(view, 2, 5), Is.True); view.RemoveAllCopies(3); check(); - Assert.IsTrue(IC.Eq(view, 2, 5)); - Assert.IsTrue(IC.Eq(list, 0, 2, 5, 3)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 2, 5), Is.True); + Assert.That(IC.Eq(list, 0, 2, 5, 3), Is.True); + }); view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0); - Assert.IsTrue(IC.Eq(view, 2, 5, 1)); + Assert.That(IC.Eq(view, 2, 5, 1), Is.True); - HashedArrayList l2 = new HashedArrayList + HashedArrayList l2 = new() { 1, 2, @@ -2459,23 +2791,29 @@ public void Remove() }; view.RemoveAll(l2); check(); - Assert.IsTrue(IC.Eq(view, 5)); + Assert.That(IC.Eq(view, 5), Is.True); view.RetainAll(l2); check(); - Assert.IsTrue(IC.Eq(view)); + Assert.That(IC.Eq(view), Is.True); view.Add(2); view.Add(4); view.Add(5); - Assert.AreEqual(2, view.RemoveAt(0)); - Assert.AreEqual(5, view.RemoveAt(1)); - Assert.AreEqual(4, view.RemoveAt(0)); + Assert.Multiple(() => + { + Assert.That(view.RemoveAt(0), Is.EqualTo(2)); + Assert.That(view.RemoveAt(1), Is.EqualTo(5)); + }); + Assert.That(view.RemoveAt(0), Is.EqualTo(4)); check(); - Assert.IsTrue(IC.Eq(view)); + Assert.That(IC.Eq(view), Is.True); view.Add(8); view.Add(6); view.Add(78); - Assert.AreEqual(8, view.RemoveFirst()); - Assert.AreEqual(78, view.RemoveLast()); + Assert.Multiple(() => + { + Assert.That(view.RemoveFirst(), Is.EqualTo(8)); + Assert.That(view.RemoveLast(), Is.EqualTo(78)); + }); view.Add(2); view.Add(5); view.Add(3); view.Add(1); view.RemoveInterval(1, 2); check(); - Assert.IsTrue(IC.Eq(view, 6, 1)); + Assert.That(IC.Eq(view, 6, 1), Is.True); } @@ -2490,10 +2828,13 @@ public void Reverse() view.View(3, 4).Reverse(); check(); - Assert.IsTrue(IC.Eq(view, 10, 11, 12, 16, 15, 14, 13, 17, 18, 19)); + Assert.That(IC.Eq(view, 10, 11, 12, 16, 15, 14, 13, 17, 18, 19), Is.True); view.Reverse(); - Assert.IsTrue(IC.Eq(view, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10)); - Assert.IsTrue(IC.Eq(list, 0, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10, 3)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10), Is.True); + Assert.That(IC.Eq(list, 0, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10, 3), Is.True); + }); } @@ -2502,21 +2843,21 @@ public void Slide() { view.Slide(1); check(); - Assert.IsTrue(IC.Eq(view, 2, 3)); + Assert.That(IC.Eq(view, 2, 3), Is.True); view.Slide(-2); check(); - Assert.IsTrue(IC.Eq(view, 0, 1)); + Assert.That(IC.Eq(view, 0, 1), Is.True); view.Slide(0, 3); check(); - Assert.IsTrue(IC.Eq(view, 0, 1, 2)); + Assert.That(IC.Eq(view, 0, 1, 2), Is.True); view.Slide(2, 1); check(); - Assert.IsTrue(IC.Eq(view, 2)); + Assert.That(IC.Eq(view, 2), Is.True); view.Slide(-1, 0); check(); - Assert.IsTrue(IC.Eq(view)); + Assert.That(IC.Eq(view), Is.True); view.Add(28); - Assert.IsTrue(IC.Eq(list, 0, 28, 1, 2, 3)); + Assert.That(IC.Eq(list, 0, 28, 1, 2, 3), Is.True); } [Test] public void Iterate() @@ -2550,14 +2891,14 @@ public void Iterate() } //foreach (int cell in list) Console.Write(" " + cell); //Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 2, 4, 8, 668, 13, 6, 1, 667, 10, 666, 11)); + Assert.That(IC.Eq(list, 2, 4, 8, 668, 13, 6, 1, 667, 10, 666, 11), Is.True); } [Test] public void SyncRoot() { - Assert.AreSame(((System.Collections.IList)view).SyncRoot, ((System.Collections.IList)list).SyncRoot); + Assert.That(((System.Collections.IList)list).SyncRoot, Is.SameAs(((System.Collections.IList)view).SyncRoot)); } } @@ -2588,36 +2929,42 @@ public void Init() [TearDown] public void Dispose() { - list = null; + list.Dispose(); views = null; } [Test] public void Insert() { - Assert.IsTrue(list.Check(), "list check before insert"); + Assert.That(list.Check(), Is.True, "list check before insert"); list.Insert(3, 777); - Assert.IsTrue(list.Check(), "list check after insert"); + Assert.That(list.Check(), Is.True, "list check after insert"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i < 3 && i + j > 3 ? j + 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i < 3 || (i == 3 && j == 0) ? i : i + 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i < 3 && i + j > 3 ? j + 1 : j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void RemoveAt() { - Assert.IsTrue(list.Check(), "list check before remove"); + Assert.That(list.Check(), Is.True, "list check before remove"); list.RemoveAt(3); - Assert.IsTrue(list.Check(), "list check after remove"); + Assert.That(list.Check(), Is.True, "list check after remove"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i <= 3 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i <= 3 && i + j > 3 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i <= 3 ? i : i - 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i <= 3 && i + j > 3 ? j - 1 : j), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2625,15 +2972,18 @@ public void RemoveAt() [Test] public void RemoveInterval() { - Assert.IsTrue(list.Check(), "list check before remove"); + Assert.That(list.Check(), Is.True, "list check before remove"); list.RemoveInterval(3, 2); - Assert.IsTrue(list.Check(), "list check after remove"); + Assert.That(list.Check(), Is.True, "list check after remove"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i <= 3 ? i : i <= 5 ? 3 : i - 2, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(j == 0 ? 0 : i <= 3 && i + j > 4 ? j - 2 : i > 4 || i + j <= 3 ? j : j - 1, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i <= 3 ? i : i <= 5 ? 3 : i - 2), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(j == 0 ? 0 : i <= 3 && i + j > 4 ? j - 2 : i > 4 || i + j <= 3 ? j : j - 1), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2641,78 +2991,93 @@ public void RemoveInterval() [Test] public void InsertAtEnd() { - Assert.IsTrue(list.Check(), "list check before insert"); + Assert.That(list.Check(), Is.True, "list check before insert"); list.InsertLast(777); - Assert.IsTrue(list.Check(), "list check after insert"); + Assert.That(list.Check(), Is.True, "list check after insert"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void RemoveAtEnd() { - Assert.IsTrue(list.Check(), "list check before remove"); + Assert.That(list.Check(), Is.True, "list check before remove"); list.RemoveAt(5); - Assert.IsTrue(list.Check(), "list check after remove"); + Assert.That(list.Check(), Is.True, "list check after remove"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i <= 5 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i <= 5 && i + j > 5 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i <= 5 ? i : i - 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i <= 5 && i + j > 5 ? j - 1 : j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void InsertAtStart() { - Assert.IsTrue(list.Check(), "list check before insert"); + Assert.That(list.Check(), Is.True, "list check before insert"); list.Insert(0, 777); - Assert.IsTrue(list.Check(), "list check after insert"); + Assert.That(list.Check(), Is.True, "list check after insert"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i == 0 && j == 0 ? 0 : i + 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i == 0 && j == 0 ? 0 : i + 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void RemoveAtStart() { - Assert.IsTrue(list.Check(), "list check before remove"); + Assert.That(list.Check(), Is.True, "list check before remove"); list.RemoveAt(0); - Assert.IsTrue(list.Check(), "list check after remove"); + Assert.That(list.Check(), Is.True, "list check after remove"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i == 0 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i == 0 && j > 0 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i == 0 ? i : i - 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i == 0 && j > 0 ? j - 1 : j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void Clear() { - Assert.IsTrue(list.Check(), "list check before clear"); + Assert.That(list.Check(), Is.True, "list check before clear"); //for (int i = 0; i < 7; i++) //for (int j = 0; j < 7 - i; j++) //Console.WriteLine("// view[{0}][{1}] : {2}", i, j, ((HashedArrayList) views[i][j]).GetHashCode()); views[2][3].Clear(); - Assert.IsTrue(list.Check(), "list check after clear"); + Assert.That(list.Check(), Is.True, "list check after clear"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i < 2 ? i : i < 6 ? 2 : i - 3, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(s(i, j), views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i < 2 ? i : i < 6 ? 2 : i - 3), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(s(i, j)), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2747,15 +3112,18 @@ public void InsertAll() { IList list2 = new HashedArrayList(); for (int i = 0; i < 5; i++) { list2.Add(100 + i); } - Assert.IsTrue(list.Check(), "list check before insertAll"); + Assert.That(list.Check(), Is.True, "list check before insertAll"); list.InsertAll(3, list2); - Assert.IsTrue(list.Check(), "list check after insertAll"); + Assert.That(list.Check(), Is.True, "list check after insertAll"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 5, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i < 3 && i + j > 3 ? j + 5 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i < 3 || (i == 3 && j == 0) ? i : i + 5), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i < 3 && i + j > 3 ? j + 5 : j), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2765,15 +3133,18 @@ public void AddAll() { IList list2 = new HashedArrayList(); for (int i = 0; i < 5; i++) { list2.Add(100 + i); } - Assert.IsTrue(list.Check(), "list check before AddAll"); + Assert.That(list.Check(), Is.True, "list check before AddAll"); list.View(1, 2).AddAll(list2); - Assert.IsTrue(list.Check(), "list check after AddAll"); + Assert.That(list.Check(), Is.True, "list check after AddAll"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 5, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i < 3 && i + j > 3 ? j + 5 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i < 3 || (i == 3 && j == 0) ? i : i + 5), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i < 3 && i + j > 3 ? j + 5 : j), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2793,7 +3164,7 @@ public void Remove() _ = (HashedArrayList)list.View(i, j); list.Remove(3); - Assert.IsTrue(list.Check(), "list check after Remove, i=" + i + ", j=" + j); + Assert.That(list.Check(), Is.True, "list check after Remove, i=" + i + ", j=" + j); } } } @@ -2819,7 +3190,7 @@ public void RemoveAll1() _ = (HashedArrayList)list.View(i, j); list.RemoveAll(list2); - Assert.IsTrue(list.Check(), "list check after RemoveAll, i=" + i + ", j=" + j); + Assert.That(list.Check(), Is.True, "list check after RemoveAll, i=" + i + ", j=" + j); } } } @@ -2832,68 +3203,71 @@ public void RemoveAll2() 3, 4 }; - Assert.IsTrue(list.Check(), "list check before RemoveAll"); + Assert.That(list.Check(), Is.True, "list check before RemoveAll"); list.RemoveAll(list2); - Assert.AreEqual(0, views[0][0].Offset, "view [0][0] offset"); - Assert.AreEqual(0, views[0][1].Offset, "view [0][1] offset"); - Assert.AreEqual(0, views[0][2].Offset, "view [0][2] offset"); - Assert.AreEqual(0, views[0][3].Offset, "view [0][3] offset"); - Assert.AreEqual(0, views[0][4].Offset, "view [0][4] offset"); - Assert.AreEqual(0, views[0][5].Offset, "view [0][5] offset"); - Assert.AreEqual(0, views[0][6].Offset, "view [0][6] offset"); - Assert.AreEqual(1, views[1][0].Offset, "view [1][0] offset"); - Assert.AreEqual(1, views[1][1].Offset, "view [1][1] offset"); - Assert.AreEqual(1, views[1][2].Offset, "view [1][2] offset"); - Assert.AreEqual(1, views[1][3].Offset, "view [1][3] offset"); - Assert.AreEqual(1, views[1][4].Offset, "view [1][4] offset"); - Assert.AreEqual(1, views[1][5].Offset, "view [1][5] offset"); - Assert.AreEqual(1, views[2][0].Offset, "view [2][0] offset"); - Assert.AreEqual(1, views[2][1].Offset, "view [2][1] offset"); - Assert.AreEqual(1, views[2][2].Offset, "view [2][2] offset"); - Assert.AreEqual(1, views[2][3].Offset, "view [2][3] offset"); - Assert.AreEqual(1, views[2][4].Offset, "view [2][4] offset"); - Assert.AreEqual(2, views[3][0].Offset, "view [3][0] offset"); - Assert.AreEqual(2, views[3][1].Offset, "view [3][1] offset"); - Assert.AreEqual(2, views[3][2].Offset, "view [3][2] offset"); - Assert.AreEqual(2, views[3][3].Offset, "view [3][3] offset"); - Assert.AreEqual(2, views[4][0].Offset, "view [4][0] offset"); - Assert.AreEqual(2, views[4][1].Offset, "view [4][1] offset"); - Assert.AreEqual(2, views[4][2].Offset, "view [4][2] offset"); - Assert.AreEqual(2, views[5][0].Offset, "view [5][0] offset"); - Assert.AreEqual(2, views[5][1].Offset, "view [5][1] offset"); - Assert.AreEqual(3, views[6][0].Offset, "view [6][0] offset"); - - Assert.AreEqual(0, views[0][0].Count, "view [0][0] count"); - Assert.AreEqual(1, views[0][1].Count, "view [0][1] count"); - Assert.AreEqual(1, views[0][2].Count, "view [0][2] count"); - Assert.AreEqual(2, views[0][3].Count, "view [0][3] count"); - Assert.AreEqual(2, views[0][4].Count, "view [0][4] count"); - Assert.AreEqual(2, views[0][5].Count, "view [0][5] count"); - Assert.AreEqual(3, views[0][6].Count, "view [0][6] count"); - Assert.AreEqual(0, views[1][0].Count, "view [1][0] count"); - Assert.AreEqual(0, views[1][1].Count, "view [1][1] count"); - Assert.AreEqual(1, views[1][2].Count, "view [1][2] count"); - Assert.AreEqual(1, views[1][3].Count, "view [1][3] count"); - Assert.AreEqual(1, views[1][4].Count, "view [1][4] count"); - Assert.AreEqual(2, views[1][5].Count, "view [1][5] count"); - Assert.AreEqual(0, views[2][0].Count, "view [2][0] count"); - Assert.AreEqual(1, views[2][1].Count, "view [2][1] count"); - Assert.AreEqual(1, views[2][2].Count, "view [2][2] count"); - Assert.AreEqual(1, views[2][3].Count, "view [2][3] count"); - Assert.AreEqual(2, views[2][4].Count, "view [2][4] count"); - Assert.AreEqual(0, views[3][0].Count, "view [3][0] count"); - Assert.AreEqual(0, views[3][1].Count, "view [3][1] count"); - Assert.AreEqual(0, views[3][2].Count, "view [3][2] count"); - Assert.AreEqual(1, views[3][3].Count, "view [3][3] count"); - Assert.AreEqual(0, views[4][0].Count, "view [4][0] count"); - Assert.AreEqual(0, views[4][1].Count, "view [4][1] count"); - Assert.AreEqual(1, views[4][2].Count, "view [4][2] count"); - Assert.AreEqual(0, views[5][0].Count, "view [5][0] count"); - Assert.AreEqual(1, views[5][1].Count, "view [5][1] count"); - Assert.AreEqual(0, views[6][0].Count, "view [6][0] count"); - - Assert.IsTrue(list.Check(), "list check after RemoveAll"); + Assert.Multiple(() => + { + Assert.That(views[0][0].Offset, Is.EqualTo(0), "view [0][0] offset"); + Assert.That(views[0][1].Offset, Is.EqualTo(0), "view [0][1] offset"); + Assert.That(views[0][2].Offset, Is.EqualTo(0), "view [0][2] offset"); + Assert.That(views[0][3].Offset, Is.EqualTo(0), "view [0][3] offset"); + Assert.That(views[0][4].Offset, Is.EqualTo(0), "view [0][4] offset"); + Assert.That(views[0][5].Offset, Is.EqualTo(0), "view [0][5] offset"); + Assert.That(views[0][6].Offset, Is.EqualTo(0), "view [0][6] offset"); + Assert.That(views[1][0].Offset, Is.EqualTo(1), "view [1][0] offset"); + Assert.That(views[1][1].Offset, Is.EqualTo(1), "view [1][1] offset"); + Assert.That(views[1][2].Offset, Is.EqualTo(1), "view [1][2] offset"); + Assert.That(views[1][3].Offset, Is.EqualTo(1), "view [1][3] offset"); + Assert.That(views[1][4].Offset, Is.EqualTo(1), "view [1][4] offset"); + Assert.That(views[1][5].Offset, Is.EqualTo(1), "view [1][5] offset"); + Assert.That(views[2][0].Offset, Is.EqualTo(1), "view [2][0] offset"); + Assert.That(views[2][1].Offset, Is.EqualTo(1), "view [2][1] offset"); + Assert.That(views[2][2].Offset, Is.EqualTo(1), "view [2][2] offset"); + Assert.That(views[2][3].Offset, Is.EqualTo(1), "view [2][3] offset"); + Assert.That(views[2][4].Offset, Is.EqualTo(1), "view [2][4] offset"); + Assert.That(views[3][0].Offset, Is.EqualTo(2), "view [3][0] offset"); + Assert.That(views[3][1].Offset, Is.EqualTo(2), "view [3][1] offset"); + Assert.That(views[3][2].Offset, Is.EqualTo(2), "view [3][2] offset"); + Assert.That(views[3][3].Offset, Is.EqualTo(2), "view [3][3] offset"); + Assert.That(views[4][0].Offset, Is.EqualTo(2), "view [4][0] offset"); + Assert.That(views[4][1].Offset, Is.EqualTo(2), "view [4][1] offset"); + Assert.That(views[4][2].Offset, Is.EqualTo(2), "view [4][2] offset"); + Assert.That(views[5][0].Offset, Is.EqualTo(2), "view [5][0] offset"); + Assert.That(views[5][1].Offset, Is.EqualTo(2), "view [5][1] offset"); + Assert.That(views[6][0].Offset, Is.EqualTo(3), "view [6][0] offset"); + + Assert.That(views[0][0], Is.Empty, "view [0][0] count"); + Assert.That(views[0][1], Has.Count.EqualTo(1), "view [0][1] count"); + Assert.That(views[0][2], Has.Count.EqualTo(1), "view [0][2] count"); + Assert.That(views[0][3], Has.Count.EqualTo(2), "view [0][3] count"); + Assert.That(views[0][4], Has.Count.EqualTo(2), "view [0][4] count"); + Assert.That(views[0][5], Has.Count.EqualTo(2), "view [0][5] count"); + Assert.That(views[0][6], Has.Count.EqualTo(3), "view [0][6] count"); + Assert.That(views[1][0], Is.Empty, "view [1][0] count"); + Assert.That(views[1][1], Is.Empty, "view [1][1] count"); + Assert.That(views[1][2], Has.Count.EqualTo(1), "view [1][2] count"); + Assert.That(views[1][3], Has.Count.EqualTo(1), "view [1][3] count"); + Assert.That(views[1][4], Has.Count.EqualTo(1), "view [1][4] count"); + Assert.That(views[1][5], Has.Count.EqualTo(2), "view [1][5] count"); + Assert.That(views[2][0], Is.Empty, "view [2][0] count"); + Assert.That(views[2][1], Has.Count.EqualTo(1), "view [2][1] count"); + Assert.That(views[2][2], Has.Count.EqualTo(1), "view [2][2] count"); + Assert.That(views[2][3], Has.Count.EqualTo(1), "view [2][3] count"); + Assert.That(views[2][4], Has.Count.EqualTo(2), "view [2][4] count"); + Assert.That(views[3][0], Is.Empty, "view [3][0] count"); + Assert.That(views[3][1], Is.Empty, "view [3][1] count"); + Assert.That(views[3][2], Is.Empty, "view [3][2] count"); + Assert.That(views[3][3], Has.Count.EqualTo(1), "view [3][3] count"); + Assert.That(views[4][0], Is.Empty, "view [4][0] count"); + Assert.That(views[4][1], Is.Empty, "view [4][1] count"); + Assert.That(views[4][2], Has.Count.EqualTo(1), "view [4][2] count"); + Assert.That(views[5][0], Is.Empty, "view [5][0] count"); + Assert.That(views[5][1], Has.Count.EqualTo(1), "view [5][1] count"); + Assert.That(views[6][0], Is.Empty, "view [6][0] count"); + + Assert.That(list.Check(), Is.True, "list check after RemoveAll"); + }); } [Test] @@ -2905,67 +3279,70 @@ public void RetainAll() 4, 5 }; - Assert.IsTrue(list.Check(), "list check before RetainAll"); + Assert.That(list.Check(), Is.True, "list check before RetainAll"); list.RetainAll(list2); - Assert.AreEqual(0, views[0][0].Offset, "view [0][0] offset"); - Assert.AreEqual(0, views[0][1].Offset, "view [0][1] offset"); - Assert.AreEqual(0, views[0][2].Offset, "view [0][2] offset"); - Assert.AreEqual(0, views[0][3].Offset, "view [0][3] offset"); - Assert.AreEqual(0, views[0][4].Offset, "view [0][4] offset"); - Assert.AreEqual(0, views[0][5].Offset, "view [0][5] offset"); - Assert.AreEqual(0, views[0][6].Offset, "view [0][6] offset"); - Assert.AreEqual(0, views[1][0].Offset, "view [1][0] offset"); - Assert.AreEqual(0, views[1][1].Offset, "view [1][1] offset"); - Assert.AreEqual(0, views[1][2].Offset, "view [1][2] offset"); - Assert.AreEqual(0, views[1][3].Offset, "view [1][3] offset"); - Assert.AreEqual(0, views[1][4].Offset, "view [1][4] offset"); - Assert.AreEqual(0, views[1][5].Offset, "view [1][5] offset"); - Assert.AreEqual(0, views[2][0].Offset, "view [2][0] offset"); - Assert.AreEqual(0, views[2][1].Offset, "view [2][1] offset"); - Assert.AreEqual(0, views[2][2].Offset, "view [2][2] offset"); - Assert.AreEqual(0, views[2][3].Offset, "view [2][3] offset"); - Assert.AreEqual(0, views[2][4].Offset, "view [2][4] offset"); - Assert.AreEqual(1, views[3][0].Offset, "view [3][0] offset"); - Assert.AreEqual(1, views[3][1].Offset, "view [3][1] offset"); - Assert.AreEqual(1, views[3][2].Offset, "view [3][2] offset"); - Assert.AreEqual(1, views[3][3].Offset, "view [3][3] offset"); - Assert.AreEqual(1, views[4][0].Offset, "view [4][0] offset"); - Assert.AreEqual(1, views[4][1].Offset, "view [4][1] offset"); - Assert.AreEqual(1, views[4][2].Offset, "view [4][2] offset"); - Assert.AreEqual(2, views[5][0].Offset, "view [5][0] offset"); - Assert.AreEqual(2, views[5][1].Offset, "view [5][1] offset"); - Assert.AreEqual(3, views[6][0].Offset, "view [6][0] offset"); - - Assert.AreEqual(0, views[0][0].Count, "view [0][0] count"); - Assert.AreEqual(0, views[0][1].Count, "view [0][1] count"); - Assert.AreEqual(0, views[0][2].Count, "view [0][2] count"); - Assert.AreEqual(1, views[0][3].Count, "view [0][3] count"); - Assert.AreEqual(1, views[0][4].Count, "view [0][4] count"); - Assert.AreEqual(2, views[0][5].Count, "view [0][5] count"); - Assert.AreEqual(3, views[0][6].Count, "view [0][6] count"); - Assert.AreEqual(0, views[1][0].Count, "view [1][0] count"); - Assert.AreEqual(0, views[1][1].Count, "view [1][1] count"); - Assert.AreEqual(1, views[1][2].Count, "view [1][2] count"); - Assert.AreEqual(1, views[1][3].Count, "view [1][3] count"); - Assert.AreEqual(2, views[1][4].Count, "view [1][4] count"); - Assert.AreEqual(3, views[1][5].Count, "view [1][5] count"); - Assert.AreEqual(0, views[2][0].Count, "view [2][0] count"); - Assert.AreEqual(1, views[2][1].Count, "view [2][1] count"); - Assert.AreEqual(1, views[2][2].Count, "view [2][2] count"); - Assert.AreEqual(2, views[2][3].Count, "view [2][3] count"); - Assert.AreEqual(3, views[2][4].Count, "view [2][4] count"); - Assert.AreEqual(0, views[3][0].Count, "view [3][0] count"); - Assert.AreEqual(0, views[3][1].Count, "view [3][1] count"); - Assert.AreEqual(1, views[3][2].Count, "view [3][2] count"); - Assert.AreEqual(2, views[3][3].Count, "view [3][3] count"); - Assert.AreEqual(0, views[4][0].Count, "view [4][0] count"); - Assert.AreEqual(1, views[4][1].Count, "view [4][1] count"); - Assert.AreEqual(2, views[4][2].Count, "view [4][2] count"); - Assert.AreEqual(0, views[5][0].Count, "view [5][0] count"); - Assert.AreEqual(1, views[5][1].Count, "view [5][1] count"); - Assert.AreEqual(0, views[6][0].Count, "view [6][0] count"); - - Assert.IsTrue(list.Check(), "list check after RetainAll"); + Assert.Multiple(() => + { + Assert.That(views[0][0].Offset, Is.EqualTo(0), "view [0][0] offset"); + Assert.That(views[0][1].Offset, Is.EqualTo(0), "view [0][1] offset"); + Assert.That(views[0][2].Offset, Is.EqualTo(0), "view [0][2] offset"); + Assert.That(views[0][3].Offset, Is.EqualTo(0), "view [0][3] offset"); + Assert.That(views[0][4].Offset, Is.EqualTo(0), "view [0][4] offset"); + Assert.That(views[0][5].Offset, Is.EqualTo(0), "view [0][5] offset"); + Assert.That(views[0][6].Offset, Is.EqualTo(0), "view [0][6] offset"); + Assert.That(views[1][0].Offset, Is.EqualTo(0), "view [1][0] offset"); + Assert.That(views[1][1].Offset, Is.EqualTo(0), "view [1][1] offset"); + Assert.That(views[1][2].Offset, Is.EqualTo(0), "view [1][2] offset"); + Assert.That(views[1][3].Offset, Is.EqualTo(0), "view [1][3] offset"); + Assert.That(views[1][4].Offset, Is.EqualTo(0), "view [1][4] offset"); + Assert.That(views[1][5].Offset, Is.EqualTo(0), "view [1][5] offset"); + Assert.That(views[2][0].Offset, Is.EqualTo(0), "view [2][0] offset"); + Assert.That(views[2][1].Offset, Is.EqualTo(0), "view [2][1] offset"); + Assert.That(views[2][2].Offset, Is.EqualTo(0), "view [2][2] offset"); + Assert.That(views[2][3].Offset, Is.EqualTo(0), "view [2][3] offset"); + Assert.That(views[2][4].Offset, Is.EqualTo(0), "view [2][4] offset"); + Assert.That(views[3][0].Offset, Is.EqualTo(1), "view [3][0] offset"); + Assert.That(views[3][1].Offset, Is.EqualTo(1), "view [3][1] offset"); + Assert.That(views[3][2].Offset, Is.EqualTo(1), "view [3][2] offset"); + Assert.That(views[3][3].Offset, Is.EqualTo(1), "view [3][3] offset"); + Assert.That(views[4][0].Offset, Is.EqualTo(1), "view [4][0] offset"); + Assert.That(views[4][1].Offset, Is.EqualTo(1), "view [4][1] offset"); + Assert.That(views[4][2].Offset, Is.EqualTo(1), "view [4][2] offset"); + Assert.That(views[5][0].Offset, Is.EqualTo(2), "view [5][0] offset"); + Assert.That(views[5][1].Offset, Is.EqualTo(2), "view [5][1] offset"); + Assert.That(views[6][0].Offset, Is.EqualTo(3), "view [6][0] offset"); + + Assert.That(views[0][0], Is.Empty, "view [0][0] count"); + Assert.That(views[0][1], Is.Empty, "view [0][1] count"); + Assert.That(views[0][2], Is.Empty, "view [0][2] count"); + Assert.That(views[0][3], Has.Count.EqualTo(1), "view [0][3] count"); + Assert.That(views[0][4], Has.Count.EqualTo(1), "view [0][4] count"); + Assert.That(views[0][5], Has.Count.EqualTo(2), "view [0][5] count"); + Assert.That(views[0][6], Has.Count.EqualTo(3), "view [0][6] count"); + Assert.That(views[1][0], Is.Empty, "view [1][0] count"); + Assert.That(views[1][1], Is.Empty, "view [1][1] count"); + Assert.That(views[1][2], Has.Count.EqualTo(1), "view [1][2] count"); + Assert.That(views[1][3], Has.Count.EqualTo(1), "view [1][3] count"); + Assert.That(views[1][4], Has.Count.EqualTo(2), "view [1][4] count"); + Assert.That(views[1][5], Has.Count.EqualTo(3), "view [1][5] count"); + Assert.That(views[2][0], Is.Empty, "view [2][0] count"); + Assert.That(views[2][1], Has.Count.EqualTo(1), "view [2][1] count"); + Assert.That(views[2][2], Has.Count.EqualTo(1), "view [2][2] count"); + Assert.That(views[2][3], Has.Count.EqualTo(2), "view [2][3] count"); + Assert.That(views[2][4], Has.Count.EqualTo(3), "view [2][4] count"); + Assert.That(views[3][0], Is.Empty, "view [3][0] count"); + Assert.That(views[3][1], Is.Empty, "view [3][1] count"); + Assert.That(views[3][2], Has.Count.EqualTo(1), "view [3][2] count"); + Assert.That(views[3][3], Has.Count.EqualTo(2), "view [3][3] count"); + Assert.That(views[4][0], Is.Empty, "view [4][0] count"); + Assert.That(views[4][1], Has.Count.EqualTo(1), "view [4][1] count"); + Assert.That(views[4][2], Has.Count.EqualTo(2), "view [4][2] count"); + Assert.That(views[5][0], Is.Empty, "view [5][0] count"); + Assert.That(views[5][1], Has.Count.EqualTo(1), "view [5][1] count"); + Assert.That(views[6][0], Is.Empty, "view [6][0] count"); + + Assert.That(list.Check(), Is.True, "list check after RetainAll"); + }); } [Test] @@ -2989,7 +3366,7 @@ public void RemoveAllCopies() list.AddAll(list2); _ = (HashedArrayList)list.View(i, j); list.RemoveAllCopies(2); - Assert.IsTrue(list.Check(), "list check after RemoveAllCopies, i=" + i + ", j=" + j); + Assert.That(list.Check(), Is.True, "list check after RemoveAllCopies, i=" + i + ", j=" + j); } } } @@ -3011,14 +3388,14 @@ private void checkDisposed(bool reverse, int start, int count) { Assert.Fail("view[" + i + "][" + j + "] threw"); } - Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] size"); + Assert.That(views[i][j], Has.Count.EqualTo(j), "view[" + i + "][" + j + "] size"); if (reverse && ((j > 0 && start <= i && start + count >= i + j) || (j == 0 && start < i && start + count > i))) { - Assert.AreEqual(start + (start + count - i - j), views[i][j].Offset, "view[" + i + "][" + j + "] offset (mirrored)"); + Assert.That(views[i][j].Offset, Is.EqualTo(start + (start + count - i - j)), "view[" + i + "][" + j + "] offset (mirrored)"); } else { - Assert.AreEqual(i, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j].Offset, Is.EqualTo(i), "view[" + i + "][" + j + "] offset"); } } else @@ -3039,9 +3416,9 @@ public void Reverse() { int start = 2, count = 3; IList list2 = list.View(start, count); - Assert.IsTrue(list.Check(), "list check before Reverse"); + Assert.That(list.Check(), Is.True, "list check before Reverse"); list2.Reverse(); - Assert.IsTrue(list.Check(), "list check after Reverse"); + Assert.That(list.Check(), Is.True, "list check after Reverse"); checkDisposed(true, start, count); } @@ -3050,9 +3427,9 @@ public void Sort() { int start = 2, count = 3; IList list2 = list.View(start, count); - Assert.IsTrue(list.Check(), "list check before Sort"); + Assert.That(list.Check(), Is.True, "list check before Sort"); list2.Sort(); - Assert.IsTrue(list.Check(), "list check after Sort"); + Assert.That(list.Check(), Is.True, "list check after Sort"); checkDisposed(false, start, count); } [Test] @@ -3060,9 +3437,9 @@ public void Shuffle() { int start = 2, count = 3; IList list2 = list.View(start, count); - Assert.IsTrue(list.Check(), "list check before Shuffle"); + Assert.That(list.Check(), Is.True, "list check before Shuffle"); list2.Shuffle(); - Assert.IsTrue(list.Check(), "list check after Shuffle"); + Assert.That(list.Check(), Is.True, "list check after Shuffle"); checkDisposed(false, start, count); } @@ -3076,7 +3453,7 @@ namespace HashingAndEquals [TestFixture] public class IIndexed { - private ISequenced dit, dat, dut; + private HashedArrayList dit, dat, dut; [SetUp] @@ -3091,7 +3468,7 @@ public void Init() [Test] public void EmptyEmpty() { - Assert.IsTrue(dit.SequencedEquals(dat)); + Assert.That(dit.SequencedEquals(dat), Is.True); } @@ -3099,23 +3476,29 @@ public void EmptyEmpty() public void EmptyNonEmpty() { dit.Add(3); - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsFalse(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dat.SequencedEquals(dit), Is.False); + }); } [Test] public void HashVal() { - Assert.AreEqual(CHC.SequencedHashCode(), dit.GetSequencedHashCode()); + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode())); dit.Add(3); - Assert.AreEqual(CHC.SequencedHashCode(3), dit.GetSequencedHashCode()); + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(3))); dit.Add(7); - Assert.AreEqual(CHC.SequencedHashCode(3, 7), dit.GetSequencedHashCode()); - Assert.AreEqual(CHC.SequencedHashCode(), dut.GetSequencedHashCode()); + Assert.Multiple(() => + { + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(3, 7))); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode())); + }); dut.Add(7); - Assert.AreEqual(CHC.SequencedHashCode(7), dut.GetSequencedHashCode()); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(7))); dut.Add(3); - Assert.AreEqual(CHC.SequencedHashCode(7, 3), dut.GetSequencedHashCode()); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(7, 3))); } @@ -3124,8 +3507,11 @@ public void EqualHashButDifferent() { dit.Add(0); dit.Add(31); dat.Add(1); dat.Add(0); - Assert.AreEqual(dit.GetSequencedHashCode(), dat.GetSequencedHashCode()); - Assert.IsFalse(dit.SequencedEquals(dat)); + Assert.Multiple(() => + { + Assert.That(dat.GetSequencedHashCode(), Is.EqualTo(dit.GetSequencedHashCode())); + Assert.That(dit.SequencedEquals(dat), Is.False); + }); } @@ -3135,11 +3521,17 @@ public void Normal() dit.Add(3); dit.Add(7); dat.Add(3); - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsFalse(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dat.SequencedEquals(dit), Is.False); + }); dat.Add(7); - Assert.IsTrue(dit.SequencedEquals(dat)); - Assert.IsTrue(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.True); + Assert.That(dat.SequencedEquals(dit), Is.True); + }); } @@ -3148,32 +3540,38 @@ public void WrongOrder() { dit.Add(3); dut.Add(3); - Assert.IsTrue(dit.SequencedEquals(dut)); - Assert.IsTrue(dut.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dut), Is.True); + Assert.That(dut.SequencedEquals(dit), Is.True); + }); dit.Add(7); ((HashedArrayList)dut).InsertFirst(7); - Assert.IsFalse(dit.SequencedEquals(dut)); - Assert.IsFalse(dut.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dut), Is.False); + Assert.That(dut.SequencedEquals(dit), Is.False); + }); } [Test] public void Reflexive() { - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); dit.Add(3); - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); dit.Add(7); - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); } [TearDown] public void Dispose() { - dit = null; - dat = null; - dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); } } @@ -3182,7 +3580,7 @@ public void Dispose() [TestFixture] public class IEditableCollection { - private ICollection dit, dat, dut; + private HashedArrayList dit, dat, dut; [SetUp] @@ -3197,7 +3595,7 @@ public void Init() [Test] public void EmptyEmpty() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); + Assert.That(dit.UnsequencedEquals(dat), Is.True); } @@ -3205,24 +3603,30 @@ public void EmptyEmpty() public void EmptyNonEmpty() { dit.Add(3); - Assert.IsFalse(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.False); + Assert.That(dat.UnsequencedEquals(dit), Is.False); + }); } [Test] public void HashVal() { - Assert.AreEqual(CHC.UnsequencedHashCode(), dit.GetUnsequencedHashCode()); + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode())); dit.Add(3); - Assert.AreEqual(CHC.UnsequencedHashCode(3), dit.GetUnsequencedHashCode()); + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3))); dit.Add(7); - Assert.AreEqual(CHC.UnsequencedHashCode(3, 7), dit.GetUnsequencedHashCode()); - Assert.AreEqual(CHC.UnsequencedHashCode(), dut.GetUnsequencedHashCode()); + Assert.Multiple(() => + { + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3, 7))); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode())); + }); dut.Add(3); - Assert.AreEqual(CHC.UnsequencedHashCode(3), dut.GetUnsequencedHashCode()); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3))); dut.Add(7); - Assert.AreEqual(CHC.UnsequencedHashCode(7, 3), dut.GetUnsequencedHashCode()); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(7, 3))); } @@ -3231,8 +3635,11 @@ public void EqualHashButDifferent() { dit.Add(-1657792980); dit.Add(-1570288808); dat.Add(1862883298); dat.Add(-272461342); - Assert.AreEqual(dit.GetUnsequencedHashCode(), dat.GetUnsequencedHashCode()); - Assert.IsFalse(dit.UnsequencedEquals(dat)); + Assert.Multiple(() => + { + Assert.That(dat.GetUnsequencedHashCode(), Is.EqualTo(dit.GetUnsequencedHashCode())); + Assert.That(dit.UnsequencedEquals(dat), Is.False); + }); } @@ -3242,11 +3649,17 @@ public void Normal() dit.Add(3); dit.Add(7); dat.Add(3); - Assert.IsFalse(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.False); + Assert.That(dat.UnsequencedEquals(dit), Is.False); + }); dat.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsTrue(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dat.UnsequencedEquals(dit), Is.True); + }); } @@ -3255,43 +3668,46 @@ public void WrongOrder() { dit.Add(3); dut.Add(3); - Assert.IsTrue(dit.UnsequencedEquals(dut)); - Assert.IsTrue(dut.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dut), Is.True); + Assert.That(dut.UnsequencedEquals(dit), Is.True); + }); dit.Add(7); dut.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dut)); - Assert.IsTrue(dut.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dut), Is.True); + Assert.That(dut.UnsequencedEquals(dit), Is.True); + }); } [Test] public void Reflexive() { - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); dit.Add(3); - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); dit.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); } - [TearDown] public void Dispose() { - dit = null; - dat = null; - dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); } } - - [TestFixture] public class MultiLevelUnorderedOfUnOrdered { - private ICollection dit, dat, dut; + private HashedArrayList dit, dat, dut; - private ICollection> Dit, Dat, Dut; + private HashedArrayList> Dit, Dat, Dut; [SetUp] @@ -3312,8 +3728,11 @@ public void Init() [Test] public void Check() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dit.UnsequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dit.UnsequencedEquals(dut), Is.False); + }); } @@ -3322,16 +3741,23 @@ public void Multi() { Dit.Add(dit); Dit.Add(dut); Dit.Add(dit); Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); - Assert.IsTrue(Dit.UnsequencedEquals(Dat)); - Assert.IsFalse(Dit.UnsequencedEquals(Dut)); + Assert.Multiple(() => + { + Assert.That(Dit.UnsequencedEquals(Dat), Is.True); + Assert.That(Dit.UnsequencedEquals(Dut), Is.False); + }); } [TearDown] public void Dispose() { - dit = dat = dut = null; - Dit = Dat = Dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); } } @@ -3340,9 +3766,9 @@ public void Dispose() [TestFixture] public class MultiLevelOrderedOfUnOrdered { - private ICollection dit, dat, dut; + private HashedArrayList dit, dat, dut; - private ISequenced> Dit, Dat, Dut; + private HashedArrayList> Dit, Dat, Dut; [SetUp] @@ -3363,8 +3789,11 @@ public void Init() [Test] public void Check() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dit.UnsequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dit.UnsequencedEquals(dut), Is.False); + }); } @@ -3374,16 +3803,23 @@ public void Multi() Dit.Add(dit); Dit.Add(dut); Dit.Add(dit); Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); Dut.Add(dit); Dut.Add(dut); Dut.Add(dat); - Assert.IsFalse(Dit.SequencedEquals(Dat)); - Assert.IsTrue(Dit.SequencedEquals(Dut)); + Assert.Multiple(() => + { + Assert.That(Dit.SequencedEquals(Dat), Is.False); + Assert.That(Dit.SequencedEquals(Dut), Is.True); + }); } [TearDown] public void Dispose() { - dit = dat = dut = null; - Dit = Dat = Dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); } } @@ -3392,9 +3828,9 @@ public void Dispose() [TestFixture] public class MultiLevelUnOrderedOfOrdered { - private ISequenced dit, dat, dut, dot; + private HashedArrayList dit, dat, dut, dot; - private ICollection> Dit, Dat, Dut, Dot; + private HashedArrayList> Dit, Dat, Dut, Dot; [SetUp] @@ -3418,9 +3854,12 @@ public void Init() [Test] public void Check() { - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsTrue(dit.SequencedEquals(dot)); - Assert.IsFalse(dit.SequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dit.SequencedEquals(dot), Is.True); + Assert.That(dit.SequencedEquals(dut), Is.False); + }); } @@ -3431,17 +3870,26 @@ public void Multi() Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); Dut.Add(dot); Dut.Add(dut); Dut.Add(dit); Dot.Add(dit); Dot.Add(dit); Dot.Add(dut); - Assert.IsTrue(Dit.UnsequencedEquals(Dut)); - Assert.IsFalse(Dit.UnsequencedEquals(Dat)); - Assert.IsTrue(Dit.UnsequencedEquals(Dot)); + Assert.Multiple(() => + { + Assert.That(Dit.UnsequencedEquals(Dut), Is.True); + Assert.That(Dit.UnsequencedEquals(Dat), Is.False); + Assert.That(Dit.UnsequencedEquals(Dot), Is.True); + }); } [TearDown] public void Dispose() { - dit = dat = dut = dot = null; - Dit = Dat = Dut = Dot = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + dot.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); + Dot.Dispose(); } } @@ -3450,9 +3898,9 @@ public void Dispose() [TestFixture] public class MultiLevelOrderedOfOrdered { - private ISequenced dit, dat, dut, dot; + private HashedArrayList dit, dat, dut, dot; - private ISequenced> Dit, Dat, Dut, Dot; + private HashedArrayList> Dit, Dat, Dut, Dot; [SetUp] @@ -3476,9 +3924,12 @@ public void Init() [Test] public void Check() { - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsTrue(dit.SequencedEquals(dot)); - Assert.IsFalse(dit.SequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dit.SequencedEquals(dot), Is.True); + Assert.That(dit.SequencedEquals(dut), Is.False); + }); } @@ -3489,17 +3940,26 @@ public void Multi() Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); // {{3},{2,1},{1,2}} Dut.Add(dot); Dut.Add(dut); Dut.Add(dit); // {{2,1},{3}} Dot.Add(dit); Dot.Add(dit); Dot.Add(dut); // {{2,1},{3}} - Assert.IsTrue(Dit.SequencedEquals(Dut)); - Assert.IsFalse(Dit.SequencedEquals(Dat)); - Assert.IsTrue(Dit.SequencedEquals(Dot)); + Assert.Multiple(() => + { + Assert.That(Dit.SequencedEquals(Dut), Is.True); + Assert.That(Dit.SequencedEquals(Dat), Is.False); + Assert.That(Dit.SequencedEquals(Dot), Is.True); + }); } [TearDown] public void Dispose() { - dit = dat = dut = dot = null; - Dit = Dat = Dut = Dot = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + dot.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); + Dot.Dispose(); } } } diff --git a/C5.Tests/Arrays/SortedArrayTests.cs b/C5.Tests/Arrays/SortedArrayTests.cs index 9d942a58..903e67c4 100644 --- a/C5.Tests/Arrays/SortedArrayTests.cs +++ b/C5.Tests/Arrays/SortedArrayTests.cs @@ -7,24 +7,15 @@ namespace C5.Tests.arrays.sorted { - using CollectionOfInt = SortedArray; - [TestFixture] public class GenericTesters { [Test] public void TestEvents() { - CollectionOfInt factory() { return new CollectionOfInt(TenEqualityComparer.Default); } - new C5.Tests.Templates.Events.SortedIndexedTester().Test(factory); + SortedArray factory() { return new SortedArray(TenEqualityComparer.Default); } + new C5.Tests.Templates.Events.SortedIndexedTester>().Test(factory); } - - //[Test] - //public void Extensible() - //{ - // C5.Tests.Templates.Extensible.Clone.Tester(); - // C5.Tests.Templates.Extensible.Serialization.Tester(); - //} } internal static class Factory @@ -45,12 +36,15 @@ public class Formatting [Test] public void Format() { - Assert.AreEqual("{ }", coll.ToString()); - coll.AddAll(new int[] { -4, 28, 129, 65530 }); - Assert.AreEqual("{ -4, 28, 129, 65530 }", coll.ToString()); - Assert.AreEqual("{ -4, 1C, 81, FFFA }", coll.ToString(null, rad16)); - Assert.AreEqual("{ -4, 28, 129... }", coll.ToString("L14", null)); - Assert.AreEqual("{ -4, 1C, 81... }", coll.ToString("L14", rad16)); + Assert.That(coll.ToString(), Is.EqualTo("{ }")); + coll.AddAll([-4, 28, 129, 65530]); + Assert.Multiple(() => + { + Assert.That(coll.ToString(), Is.EqualTo("{ -4, 28, 129, 65530 }")); + Assert.That(coll.ToString(null, rad16), Is.EqualTo("{ -4, 1C, 81, FFFA }")); + Assert.That(coll.ToString("L14", null), Is.EqualTo("{ -4, 28, 129... }")); + Assert.That(coll.ToString("L14", rad16), Is.EqualTo("{ -4, 1C, 81... }")); + }); } } @@ -82,10 +76,10 @@ public void Enumerator() while (e.MoveNext()) { - Assert.AreEqual(2 * i++, e.Current); + Assert.That(e.Current, Is.EqualTo(2 * i++)); } - Assert.AreEqual(9, i); + Assert.That(i, Is.EqualTo(9)); } @@ -104,117 +98,126 @@ public void Enumerator3() [Test] public void Remove() { - int[] all = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 }; + int[] all = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]; array.RemoveRangeFrom(18); - Assert.IsTrue(IC.Eq(array, new int[] { 2, 4, 6, 8, 10, 12, 14, 16 })); + Assert.That(IC.Eq(array, [2, 4, 6, 8, 10, 12, 14, 16]), Is.True); array.RemoveRangeFrom(28); - Assert.IsTrue(IC.Eq(array, new int[] { 2, 4, 6, 8, 10, 12, 14, 16 })); + Assert.That(IC.Eq(array, [2, 4, 6, 8, 10, 12, 14, 16]), Is.True); array.RemoveRangeFrom(13); - Assert.IsTrue(IC.Eq(array, new int[] { 2, 4, 6, 8, 10, 12 })); + Assert.That(IC.Eq(array, [2, 4, 6, 8, 10, 12]), Is.True); array.RemoveRangeFrom(2); - Assert.IsTrue(IC.Eq(array)); + Assert.That(IC.Eq(array), Is.True); foreach (int i in all) { array.Add(i); } array.RemoveRangeTo(10); - Assert.IsTrue(IC.Eq(array, new int[] { 10, 12, 14, 16, 18, 20 })); + Assert.That(IC.Eq(array, [10, 12, 14, 16, 18, 20]), Is.True); array.RemoveRangeTo(2); - Assert.IsTrue(IC.Eq(array, new int[] { 10, 12, 14, 16, 18, 20 })); + Assert.That(IC.Eq(array, [10, 12, 14, 16, 18, 20]), Is.True); array.RemoveRangeTo(21); - Assert.IsTrue(IC.Eq(array)); + Assert.That(IC.Eq(array), Is.True); foreach (int i in all) { array.Add(i); } array.RemoveRangeFromTo(4, 8); - Assert.IsTrue(IC.Eq(array, 2, 8, 10, 12, 14, 16, 18, 20)); + Assert.That(IC.Eq(array, 2, 8, 10, 12, 14, 16, 18, 20), Is.True); array.RemoveRangeFromTo(14, 28); - Assert.IsTrue(IC.Eq(array, 2, 8, 10, 12)); + Assert.That(IC.Eq(array, 2, 8, 10, 12), Is.True); array.RemoveRangeFromTo(0, 9); - Assert.IsTrue(IC.Eq(array, 10, 12)); + Assert.That(IC.Eq(array, 10, 12), Is.True); array.RemoveRangeFromTo(0, 81); - Assert.IsTrue(IC.Eq(array)); + Assert.That(IC.Eq(array), Is.True); } [Test] public void Normal() { - int[] all = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 }; - - Assert.IsTrue(IC.Eq(array, all)); - Assert.IsTrue(IC.Eq(array.RangeAll(), all)); - Assert.AreEqual(10, array.RangeAll().Count); - Assert.IsTrue(IC.Eq(array.RangeFrom(11), new int[] { 12, 14, 16, 18, 20 })); - Assert.AreEqual(5, array.RangeFrom(11).Count); - Assert.IsTrue(IC.Eq(array.RangeFrom(12), new int[] { 12, 14, 16, 18, 20 })); - Assert.IsTrue(IC.Eq(array.RangeFrom(2), all)); - Assert.IsTrue(IC.Eq(array.RangeFrom(1), all)); - Assert.IsTrue(IC.Eq(array.RangeFrom(21), new int[] { })); - Assert.IsTrue(IC.Eq(array.RangeFrom(20), new int[] { 20 })); - Assert.IsTrue(IC.Eq(array.RangeTo(8), new int[] { 2, 4, 6 })); - Assert.IsTrue(IC.Eq(array.RangeTo(7), new int[] { 2, 4, 6 })); - Assert.AreEqual(3, array.RangeTo(7).Count); - Assert.IsTrue(IC.Eq(array.RangeTo(2), new int[] { })); - Assert.IsTrue(IC.Eq(array.RangeTo(1), new int[] { })); - Assert.IsTrue(IC.Eq(array.RangeTo(3), new int[] { 2 })); - Assert.IsTrue(IC.Eq(array.RangeTo(20), new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18 })); - Assert.IsTrue(IC.Eq(array.RangeTo(21), all)); - Assert.IsTrue(IC.Eq(array.RangeFromTo(7, 12), new int[] { 8, 10 })); - Assert.IsTrue(IC.Eq(array.RangeFromTo(6, 11), new int[] { 6, 8, 10 })); - Assert.IsTrue(IC.Eq(array.RangeFromTo(1, 12), new int[] { 2, 4, 6, 8, 10 })); - Assert.AreEqual(5, array.RangeFromTo(1, 12).Count); - Assert.IsTrue(IC.Eq(array.RangeFromTo(2, 12), new int[] { 2, 4, 6, 8, 10 })); - Assert.IsTrue(IC.Eq(array.RangeFromTo(6, 21), new int[] { 6, 8, 10, 12, 14, 16, 18, 20 })); - Assert.IsTrue(IC.Eq(array.RangeFromTo(6, 20), new int[] { 6, 8, 10, 12, 14, 16, 18 })); + int[] all = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]; + + Assert.Multiple(() => + { + Assert.That(IC.Eq(array, all), Is.True); + Assert.That(IC.Eq(array.RangeAll(), all), Is.True); + Assert.That(array.RangeAll(), Has.Count.EqualTo(10)); + Assert.That(IC.Eq(array.RangeFrom(11), [12, 14, 16, 18, 20]), Is.True); + Assert.That(array.RangeFrom(11), Has.Count.EqualTo(5)); + Assert.That(IC.Eq(array.RangeFrom(12), [12, 14, 16, 18, 20]), Is.True); + Assert.That(IC.Eq(array.RangeFrom(2), all), Is.True); + Assert.That(IC.Eq(array.RangeFrom(1), all), Is.True); + Assert.That(IC.Eq(array.RangeFrom(21), []), Is.True); + Assert.That(IC.Eq(array.RangeFrom(20), [20]), Is.True); + Assert.That(IC.Eq(array.RangeTo(8), [2, 4, 6]), Is.True); + Assert.That(IC.Eq(array.RangeTo(7), [2, 4, 6]), Is.True); + Assert.That(array.RangeTo(7), Has.Count.EqualTo(3)); + Assert.That(IC.Eq(array.RangeTo(2), []), Is.True); + Assert.That(IC.Eq(array.RangeTo(1), []), Is.True); + Assert.That(IC.Eq(array.RangeTo(3), [2]), Is.True); + Assert.That(IC.Eq(array.RangeTo(20), [2, 4, 6, 8, 10, 12, 14, 16, 18]), Is.True); + Assert.That(IC.Eq(array.RangeTo(21), all), Is.True); + Assert.That(IC.Eq(array.RangeFromTo(7, 12), [8, 10]), Is.True); + Assert.That(IC.Eq(array.RangeFromTo(6, 11), [6, 8, 10]), Is.True); + Assert.That(IC.Eq(array.RangeFromTo(1, 12), [2, 4, 6, 8, 10]), Is.True); + Assert.That(array.RangeFromTo(1, 12), Has.Count.EqualTo(5)); + Assert.That(IC.Eq(array.RangeFromTo(2, 12), [2, 4, 6, 8, 10]), Is.True); + Assert.That(IC.Eq(array.RangeFromTo(6, 21), [6, 8, 10, 12, 14, 16, 18, 20]), Is.True); + Assert.That(IC.Eq(array.RangeFromTo(6, 20), [6, 8, 10, 12, 14, 16, 18]), Is.True); + }); } [Test] public void Backwards() { - int[] all = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 }; - int[] lla = new int[] { 20, 18, 16, 14, 12, 10, 8, 6, 4, 2 }; - - Assert.IsTrue(IC.Eq(array, all)); - Assert.IsTrue(IC.Eq(array.RangeAll().Backwards(), lla)); - Assert.IsTrue(IC.Eq(array.RangeFrom(11).Backwards(), new int[] { 20, 18, 16, 14, 12 })); - Assert.IsTrue(IC.Eq(array.RangeFrom(12).Backwards(), new int[] { 20, 18, 16, 14, 12 })); - Assert.IsTrue(IC.Eq(array.RangeFrom(2).Backwards(), lla)); - Assert.IsTrue(IC.Eq(array.RangeFrom(1).Backwards(), lla)); - Assert.IsTrue(IC.Eq(array.RangeFrom(21).Backwards(), new int[] { })); - Assert.IsTrue(IC.Eq(array.RangeFrom(20).Backwards(), new int[] { 20 })); - Assert.IsTrue(IC.Eq(array.RangeTo(8).Backwards(), new int[] { 6, 4, 2 })); - Assert.IsTrue(IC.Eq(array.RangeTo(7).Backwards(), new int[] { 6, 4, 2 })); - Assert.IsTrue(IC.Eq(array.RangeTo(2).Backwards(), new int[] { })); - Assert.IsTrue(IC.Eq(array.RangeTo(1).Backwards(), new int[] { })); - Assert.IsTrue(IC.Eq(array.RangeTo(3).Backwards(), new int[] { 2 })); - Assert.IsTrue(IC.Eq(array.RangeTo(20).Backwards(), new int[] { 18, 16, 14, 12, 10, 8, 6, 4, 2 })); - Assert.IsTrue(IC.Eq(array.RangeTo(21).Backwards(), lla)); - Assert.IsTrue(IC.Eq(array.RangeFromTo(7, 12).Backwards(), new int[] { 10, 8 })); - Assert.IsTrue(IC.Eq(array.RangeFromTo(6, 11).Backwards(), new int[] { 10, 8, 6 })); - Assert.IsTrue(IC.Eq(array.RangeFromTo(1, 12).Backwards(), new int[] { 10, 8, 6, 4, 2 })); - Assert.IsTrue(IC.Eq(array.RangeFromTo(2, 12).Backwards(), new int[] { 10, 8, 6, 4, 2 })); - Assert.IsTrue(IC.Eq(array.RangeFromTo(6, 21).Backwards(), new int[] { 20, 18, 16, 14, 12, 10, 8, 6 })); - Assert.IsTrue(IC.Eq(array.RangeFromTo(6, 20).Backwards(), new int[] { 18, 16, 14, 12, 10, 8, 6 })); + int[] all = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]; + int[] lla = [20, 18, 16, 14, 12, 10, 8, 6, 4, 2]; + + Assert.Multiple(() => + { + Assert.That(IC.Eq(array, all), Is.True); + Assert.That(IC.Eq(array.RangeAll().Backwards(), lla), Is.True); + Assert.That(IC.Eq(array.RangeFrom(11).Backwards(), [20, 18, 16, 14, 12]), Is.True); + Assert.That(IC.Eq(array.RangeFrom(12).Backwards(), [20, 18, 16, 14, 12]), Is.True); + Assert.That(IC.Eq(array.RangeFrom(2).Backwards(), lla), Is.True); + Assert.That(IC.Eq(array.RangeFrom(1).Backwards(), lla), Is.True); + Assert.That(IC.Eq(array.RangeFrom(21).Backwards(), []), Is.True); + Assert.That(IC.Eq(array.RangeFrom(20).Backwards(), [20]), Is.True); + Assert.That(IC.Eq(array.RangeTo(8).Backwards(), [6, 4, 2]), Is.True); + Assert.That(IC.Eq(array.RangeTo(7).Backwards(), [6, 4, 2]), Is.True); + Assert.That(IC.Eq(array.RangeTo(2).Backwards(), []), Is.True); + Assert.That(IC.Eq(array.RangeTo(1).Backwards(), []), Is.True); + Assert.That(IC.Eq(array.RangeTo(3).Backwards(), [2]), Is.True); + Assert.That(IC.Eq(array.RangeTo(20).Backwards(), [18, 16, 14, 12, 10, 8, 6, 4, 2]), Is.True); + Assert.That(IC.Eq(array.RangeTo(21).Backwards(), lla), Is.True); + Assert.That(IC.Eq(array.RangeFromTo(7, 12).Backwards(), [10, 8]), Is.True); + Assert.That(IC.Eq(array.RangeFromTo(6, 11).Backwards(), [10, 8, 6]), Is.True); + Assert.That(IC.Eq(array.RangeFromTo(1, 12).Backwards(), [10, 8, 6, 4, 2]), Is.True); + Assert.That(IC.Eq(array.RangeFromTo(2, 12).Backwards(), [10, 8, 6, 4, 2]), Is.True); + Assert.That(IC.Eq(array.RangeFromTo(6, 21).Backwards(), [20, 18, 16, 14, 12, 10, 8, 6]), Is.True); + Assert.That(IC.Eq(array.RangeFromTo(6, 20).Backwards(), [18, 16, 14, 12, 10, 8, 6]), Is.True); + }); } [Test] public void Direction() { - Assert.AreEqual(C5.Direction.Forwards, array.Direction); - Assert.AreEqual(C5.Direction.Forwards, array.RangeFrom(20).Direction); - Assert.AreEqual(C5.Direction.Forwards, array.RangeTo(7).Direction); - Assert.AreEqual(C5.Direction.Forwards, array.RangeFromTo(1, 12).Direction); - Assert.AreEqual(C5.Direction.Forwards, array.RangeAll().Direction); - Assert.AreEqual(C5.Direction.Backwards, array.Backwards().Direction); - Assert.AreEqual(C5.Direction.Backwards, array.RangeFrom(20).Backwards().Direction); - Assert.AreEqual(C5.Direction.Backwards, array.RangeTo(7).Backwards().Direction); - Assert.AreEqual(C5.Direction.Backwards, array.RangeFromTo(1, 12).Backwards().Direction); - Assert.AreEqual(C5.Direction.Backwards, array.RangeAll().Backwards().Direction); + Assert.Multiple(() => + { + Assert.That(array.Direction, Is.EqualTo(C5.Direction.Forwards)); + Assert.That(array.RangeFrom(20).Direction, Is.EqualTo(C5.Direction.Forwards)); + Assert.That(array.RangeTo(7).Direction, Is.EqualTo(C5.Direction.Forwards)); + Assert.That(array.RangeFromTo(1, 12).Direction, Is.EqualTo(C5.Direction.Forwards)); + Assert.That(array.RangeAll().Direction, Is.EqualTo(C5.Direction.Forwards)); + Assert.That(array.Backwards().Direction, Is.EqualTo(C5.Direction.Backwards)); + Assert.That(array.RangeFrom(20).Backwards().Direction, Is.EqualTo(C5.Direction.Backwards)); + Assert.That(array.RangeTo(7).Backwards().Direction, Is.EqualTo(C5.Direction.Backwards)); + Assert.That(array.RangeFromTo(1, 12).Backwards().Direction, Is.EqualTo(C5.Direction.Backwards)); + Assert.That(array.RangeAll().Backwards().Direction, Is.EqualTo(C5.Direction.Backwards)); + }); } @@ -247,10 +250,13 @@ public void Init() [Test] public void Both() { - Assert.AreEqual(0, array.ContainsCount(7)); - Assert.AreEqual(1, array.ContainsCount(10)); + Assert.Multiple(() => + { + Assert.That(array.ContainsCount(7), Is.EqualTo(0)); + Assert.That(array.ContainsCount(10), Is.EqualTo(1)); + }); array.RemoveAllCopies(10); - Assert.AreEqual(0, array.ContainsCount(10)); + Assert.That(array.ContainsCount(10), Is.EqualTo(0)); array.RemoveAllCopies(7); } @@ -309,7 +315,7 @@ public void NullEqualityComparerinConstructor5() public void Choose() { array.Add(7); - Assert.AreEqual(7, array.Choose()); + Assert.That(array.Choose(), Is.EqualTo(7)); } [Test] @@ -331,23 +337,32 @@ private void loadup() [Test] public void NoDuplicatesEtc() { - Assert.IsFalse(array.AllowsDuplicates); + Assert.That(array.AllowsDuplicates, Is.False); loadup(); - Assert.IsFalse(array.AllowsDuplicates); - Assert.AreEqual(Speed.Log, array.ContainsSpeed); - Assert.IsTrue(array.Comparer.Compare(2, 3) < 0); - Assert.IsTrue(array.Comparer.Compare(4, 3) > 0); - Assert.IsTrue(array.Comparer.Compare(3, 3) == 0); + Assert.Multiple(() => + { + Assert.That(array.AllowsDuplicates, Is.False); + Assert.That(array.ContainsSpeed, Is.EqualTo(Speed.Log)); + Assert.That(array.Comparer.Compare(2, 3), Is.LessThan(0)); + Assert.That(array.Comparer.Compare(4, 3), Is.GreaterThan(0)); + Assert.That(array.Comparer.Compare(3, 3), Is.EqualTo(0)); + }); } [Test] public void Add() { - Assert.IsTrue(array.Add(17)); - Assert.IsFalse(array.Add(17)); - Assert.IsTrue(array.Add(18)); - Assert.IsFalse(array.Add(18)); - Assert.AreEqual(2, array.Count); + Assert.That(array.Add(17), Is.True); + Assert.Multiple(() => + { + Assert.That(array.Add(17), Is.False); + Assert.That(array.Add(18), Is.True); + }); + Assert.Multiple(() => + { + Assert.That(array.Add(18), Is.False); + Assert.That(array, Has.Count.EqualTo(2)); + }); } @@ -382,15 +397,21 @@ public void Dispose() [Test] public void Test() { - SCG.KeyValuePair p = new SCG.KeyValuePair(3, "tre"); + SCG.KeyValuePair p = new(3, "tre"); - Assert.IsFalse(bag.FindOrAdd(ref p)); + Assert.That(bag.FindOrAdd(ref p), Is.False); p = new SCG.KeyValuePair(p.Key, "drei"); - Assert.IsTrue(bag.FindOrAdd(ref p)); - Assert.AreEqual("tre", p.Value); + Assert.Multiple(() => + { + Assert.That(bag.FindOrAdd(ref p), Is.True); + Assert.That(p.Value, Is.EqualTo("tre")); + }); p = new SCG.KeyValuePair(p.Key, "three"); - Assert.AreEqual(1, bag.ContainsCount(p)); - Assert.AreEqual("tre", bag[0].Value); + Assert.Multiple(() => + { + Assert.That(bag.ContainsCount(p), Is.EqualTo(1)); + Assert.That(bag[0].Value, Is.EqualTo("tre")); + }); } } @@ -413,43 +434,49 @@ public void Init() [Test] public void Find() { - Assert.IsFalse(list.Find(pred, out int i)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(list.Find(pred, out i)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.IsTrue(list.Find(pred, out i)); - Assert.AreEqual(45, i); + Assert.That(list.Find(pred, out int i), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(list.Find(pred, out i), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.Multiple(() => + { + Assert.That(list.Find(pred, out i), Is.True); + Assert.That(i, Is.EqualTo(45)); + }); } [Test] public void FindLast() { - Assert.IsFalse(list.FindLast(pred, out int i)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(list.FindLast(pred, out i)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.IsTrue(list.FindLast(pred, out i)); - Assert.AreEqual(675, i); + Assert.That(list.FindLast(pred, out int i), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(list.FindLast(pred, out i), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.Multiple(() => + { + Assert.That(list.FindLast(pred, out i), Is.True); + Assert.That(i, Is.EqualTo(675)); + }); } [Test] public void FindIndex() { - Assert.IsFalse(0 <= list.FindIndex(pred)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(0 <= list.FindIndex(pred)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.AreEqual(3, list.FindIndex(pred)); + Assert.That(list.FindIndex(pred), Is.LessThanOrEqualTo(0)); + list.AddAll([4, 22, 67, 37]); + Assert.That(list.FindIndex(pred), Is.LessThanOrEqualTo(0)); + list.AddAll([45, 122, 675, 137]); + Assert.That(list.FindIndex(pred), Is.EqualTo(3)); } [Test] public void FindLastIndex() { - Assert.IsFalse(0 <= list.FindLastIndex(pred)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(0 <= list.FindLastIndex(pred)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.AreEqual(7, list.FindLastIndex(pred)); + Assert.That(list.FindLastIndex(pred), Is.LessThanOrEqualTo(0)); + list.AddAll([4, 22, 67, 37]); + Assert.That(list.FindLastIndex(pred), Is.LessThanOrEqualTo(0)); + list.AddAll([45, 122, 675, 137]); + Assert.That(list.FindLastIndex(pred), Is.EqualTo(7)); } } @@ -459,7 +486,7 @@ public class UniqueItems private SortedArray list; [SetUp] - public void Init() { list = new SortedArray(); } + public void Init() { list = []; } [TearDown] public void Dispose() { list = null; } @@ -467,11 +494,17 @@ public class UniqueItems [Test] public void Test() { - Assert.IsTrue(IC.SetEq(list.UniqueItems())); - Assert.IsTrue(IC.SetEq(list.ItemMultiplicities())); - list.AddAll(new int[] { 7, 9, 7 }); - Assert.IsTrue(IC.SetEq(list.UniqueItems(), 7, 9)); - Assert.IsTrue(IC.SetEq(list.ItemMultiplicities(), 7, 1, 9, 1)); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(list.UniqueItems()), Is.True); + Assert.That(IC.SetEq(list.ItemMultiplicities()), Is.True); + }); + list.AddAll([7, 9, 7]); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(list.UniqueItems(), 7, 9), Is.True); + Assert.That(IC.SetEq(list.ItemMultiplicities(), 7, 1, 9, 1), Is.True); + }); } } @@ -520,10 +553,10 @@ private string aeq(int[] a, params int[] b) [Test] public void ToArray() { - Assert.AreEqual("Alles klar", aeq(tree.ToArray())); + Assert.That(aeq(tree.ToArray()), Is.EqualTo("Alles klar")); tree.Add(7); tree.Add(4); - Assert.AreEqual("Alles klar", aeq(tree.ToArray(), 4, 7)); + Assert.That(aeq(tree.ToArray(), 4, 7), Is.EqualTo("Alles klar")); } @@ -531,18 +564,18 @@ public void ToArray() public void CopyTo() { tree.CopyTo(a, 1); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009), Is.EqualTo("Alles klar")); tree.Add(6); tree.CopyTo(a, 2); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009), Is.EqualTo("Alles klar")); tree.Add(4); tree.Add(9); tree.CopyTo(a, 4); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 4, 6, 9, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 4, 6, 9, 1007, 1008, 1009), Is.EqualTo("Alles klar")); tree.Clear(); tree.Add(7); tree.CopyTo(a, 9); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 4, 6, 9, 1007, 1008, 7)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 4, 6, 9, 1007, 1008, 7), Is.EqualTo("Alles klar")); } @@ -593,110 +626,134 @@ public void Init() [Test] public void Find() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + System.Collections.Generic.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Find(ref p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); + Assert.Multiple(() => + { + Assert.That(lst.Find(ref p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Find(ref p)); + Assert.That(lst.Find(ref p), Is.False); } [Test] public void FindOrAdd() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + System.Collections.Generic.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.FindOrAdd(ref p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); + Assert.Multiple(() => + { + Assert.That(lst.FindOrAdd(ref p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); p = new System.Collections.Generic.KeyValuePair(13, 79); - Assert.IsFalse(lst.FindOrAdd(ref p)); - Assert.AreEqual(13, lst[10].Key); - Assert.AreEqual(79, lst[10].Value); + Assert.Multiple(() => + { + Assert.That(lst.FindOrAdd(ref p), Is.False); + Assert.That(lst[10].Key, Is.EqualTo(13)); + Assert.That(lst[10].Value, Is.EqualTo(79)); + }); } [Test] public void Update() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + System.Collections.Generic.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Update(p)); - Assert.AreEqual(3, lst[3].Key); - Assert.AreEqual(78, lst[3].Value); + Assert.Multiple(() => + { + Assert.That(lst.Update(p), Is.True); + Assert.That(lst[3].Key, Is.EqualTo(3)); + Assert.That(lst[3].Value, Is.EqualTo(78)); + }); p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Update(p)); + Assert.That(lst.Update(p), Is.False); } [Test] public void UpdateOrAdd1() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + System.Collections.Generic.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.UpdateOrAdd(p)); - Assert.AreEqual(3, lst[3].Key); - Assert.AreEqual(78, lst[3].Value); + Assert.Multiple(() => + { + Assert.That(lst.UpdateOrAdd(p), Is.True); + Assert.That(lst[3].Key, Is.EqualTo(3)); + Assert.That(lst[3].Value, Is.EqualTo(78)); + }); p = new System.Collections.Generic.KeyValuePair(13, 79); - Assert.IsFalse(lst.UpdateOrAdd(p)); - Assert.AreEqual(13, lst[10].Key); - Assert.AreEqual(79, lst[10].Value); + Assert.Multiple(() => + { + Assert.That(lst.UpdateOrAdd(p), Is.False); + Assert.That(lst[10].Key, Is.EqualTo(13)); + Assert.That(lst[10].Value, Is.EqualTo(79)); + }); } [Test] public void UpdateOrAdd2() { - ICollection coll = new SortedArray(); + ICollection coll = new SortedArray(); // s1 and s2 are distinct objects but contain the same text: - String s1 = "abc", s2 = ("def" + s1).Substring(3); - Assert.IsFalse(coll.UpdateOrAdd(s1, out string old)); - Assert.AreEqual(null, old); - Assert.IsTrue(coll.UpdateOrAdd(s2, out old)); - Assert.IsTrue(Object.ReferenceEquals(s1, old)); - Assert.IsFalse(Object.ReferenceEquals(s2, old)); + string s1 = "abc", s2 = ("def" + s1).Substring(3); + Assert.Multiple(() => + { + Assert.That(coll.UpdateOrAdd(s1, out string old), Is.False); + Assert.That(old, Is.EqualTo(null)); + Assert.That(coll.UpdateOrAdd(s2, out old), Is.True); + Assert.That(ReferenceEquals(s1, old), Is.True); + Assert.That(ReferenceEquals(s2, old), Is.False); + }); } [Test] public void UpdateOrAddWithExpand() { // bug20071217 - SortedArray arr = new SortedArray(); + SortedArray arr = new(); for (int i = 0; i < 50; i++) { arr.UpdateOrAdd(i + 0.1); arr.Add(i + 0.2); } - Assert.IsTrue(arr.Count == 100); + Assert.That(arr, Has.Count.EqualTo(100)); } [Test] public void FindOrAddWithExpand() { // bug20071217 - SortedArray arr = new SortedArray(); + SortedArray arr = new(); for (int i = 0; i < 50; i++) { double iVar = i + 0.1; arr.FindOrAdd(ref iVar); arr.Add(i * 0.2); } - Assert.IsTrue(arr.Count == 100); + Assert.That(arr, Has.Count.EqualTo(100)); } [Test] public void RemoveWithReturn() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + System.Collections.Generic.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Remove(p, out p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); - Assert.AreEqual(4, lst[3].Key); - Assert.AreEqual(34, lst[3].Value); + Assert.Multiple(() => + { + Assert.That(lst.Remove(p, out p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + Assert.That(lst[3].Key, Is.EqualTo(4)); + Assert.That(lst[3].Value, Is.EqualTo(34)); + }); p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Remove(p, out _)); + Assert.That(lst.Remove(p, out _), Is.False); } } @@ -725,8 +782,11 @@ public void SmallTrees() array.Clear(); array.Add(7); array.Add(9); - Assert.IsTrue(array.Remove(7)); - Assert.IsTrue(array.Check()); + Assert.Multiple(() => + { + Assert.That(array.Remove(7), Is.True); + Assert.That(array.Check(), Is.True); + }); } @@ -738,30 +798,42 @@ public void ByIndex() int i = array[10]; array.RemoveAt(10); - Assert.IsTrue(array.Check()); - Assert.IsFalse(array.Contains(i)); - Assert.AreEqual(n - 1, array.Count); + Assert.Multiple(() => + { + Assert.That(array.Check(), Is.True); + Assert.That(array, Does.Not.Contain(i)); + Assert.That(array, Has.Count.EqualTo(n - 1)); + }); //Low end i = array.FindMin(); array.RemoveAt(0); - Assert.IsTrue(array.Check()); - Assert.IsFalse(array.Contains(i)); - Assert.AreEqual(n - 2, array.Count); + Assert.Multiple(() => + { + Assert.That(array.Check(), Is.True); + Assert.That(array, Does.Not.Contain(i)); + Assert.That(array, Has.Count.EqualTo(n - 2)); + }); //high end i = array.FindMax(); array.RemoveAt(array.Count - 1); - Assert.IsTrue(array.Check()); - Assert.IsFalse(array.Contains(i)); - Assert.AreEqual(n - 3, array.Count); + Assert.Multiple(() => + { + Assert.That(array.Check(), Is.True); + Assert.That(array, Does.Not.Contain(i)); + Assert.That(array, Has.Count.EqualTo(n - 3)); + }); //Some leaf i = 18; array.RemoveAt(7); - Assert.IsTrue(array.Check()); - Assert.IsFalse(array.Contains(i)); - Assert.AreEqual(n - 4, array.Count); + Assert.Multiple(() => + { + Assert.That(array.Check(), Is.True); + Assert.That(array, Does.Not.Contain(i)); + Assert.That(array, Has.Count.EqualTo(n - 4)); + }); } @@ -772,9 +844,12 @@ public void AlmostEmpty() array.Clear(); array.Add(3); array.RemoveAt(0); - Assert.IsTrue(array.Check()); - Assert.IsFalse(array.Contains(3)); - Assert.AreEqual(0, array.Count); + Assert.Multiple(() => + { + Assert.That(array.Check(), Is.True); + Assert.That(array, Does.Not.Contain(3)); + Assert.That(array, Is.Empty); + }); } @@ -784,7 +859,7 @@ public void Empty() array.Clear(); var exception = Assert.Throws(() => array.RemoveAt(0)); - Assert.AreEqual("Index out of range for sequenced collectionvalue", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Index out of range for sequenced collectionvalue")); } @@ -792,7 +867,7 @@ public void Empty() public void HighIndex() { var exception = Assert.Throws(() => array.RemoveAt(array.Count)); - Assert.AreEqual("Index out of range for sequenced collectionvalue", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Index out of range for sequenced collectionvalue")); } @@ -800,44 +875,47 @@ public void HighIndex() public void LowIndex() { var exception = Assert.Throws(() => array.RemoveAt(-1)); - Assert.AreEqual("Index out of range for sequenced collectionvalue", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Index out of range for sequenced collectionvalue")); } [Test] public void Normal() { - Assert.IsFalse(array.Remove(-20)); + Assert.Multiple(() => + { + Assert.That(array.Remove(-20), Is.False); - //No demote case, with move_item - Assert.IsTrue(array.Remove(20)); - Assert.IsTrue(array.Check()); - Assert.IsFalse(array.Remove(20)); + //No demote case, with move_item + Assert.That(array.Remove(20), Is.True); + Assert.That(array.Check(), Is.True); + Assert.That(array.Remove(20), Is.False); - //plain case 2 - Assert.IsTrue(array.Remove(14)); - Assert.IsTrue(array.Check(), "Bad tree"); + //plain case 2 + Assert.That(array.Remove(14), Is.True); + Assert.That(array.Check(), Is.True, "Bad tree"); - //case 1b - Assert.IsTrue(array.Remove(25)); - Assert.IsTrue(array.Check(), "Bad tree"); + //case 1b + Assert.That(array.Remove(25), Is.True); + Assert.That(array.Check(), Is.True, "Bad tree"); - //case 1c - Assert.IsTrue(array.Remove(29)); - Assert.IsTrue(array.Check(), "Bad tree"); + //case 1c + Assert.That(array.Remove(29), Is.True); + Assert.That(array.Check(), Is.True, "Bad tree"); - //1a (terminating) - Assert.IsTrue(array.Remove(10)); - Assert.IsTrue(array.Check(), "Bad tree"); + //1a (terminating) + Assert.That(array.Remove(10), Is.True); + Assert.That(array.Check(), Is.True, "Bad tree"); - //2+1b - Assert.IsTrue(array.Remove(12)); - Assert.IsTrue(array.Remove(11)); + //2+1b + Assert.That(array.Remove(12), Is.True); + Assert.That(array.Remove(11), Is.True); - //1a+1b - Assert.IsTrue(array.Remove(18)); - Assert.IsTrue(array.Remove(13)); - Assert.IsTrue(array.Remove(15)); + //1a+1b + Assert.That(array.Remove(18), Is.True); + Assert.That(array.Remove(13), Is.True); + Assert.That(array.Remove(15), Is.True); + }); //2+1c for (int i = 0; i < 10; i++) @@ -845,34 +923,40 @@ public void Normal() array.Add(50 - 2 * i); } - Assert.IsTrue(array.Remove(42)); - Assert.IsTrue(array.Remove(38)); - Assert.IsTrue(array.Remove(28)); - Assert.IsTrue(array.Remove(40)); - - // - Assert.IsTrue(array.Remove(16)); - Assert.IsTrue(array.Remove(23)); - Assert.IsTrue(array.Remove(17)); - Assert.IsTrue(array.Remove(19)); - Assert.IsTrue(array.Remove(50)); - Assert.IsTrue(array.Remove(26)); - Assert.IsTrue(array.Remove(21)); - Assert.IsTrue(array.Remove(22)); - Assert.IsTrue(array.Remove(24)); + Assert.Multiple(() => + { + Assert.That(array.Remove(42), Is.True); + Assert.That(array.Remove(38), Is.True); + Assert.That(array.Remove(28), Is.True); + Assert.That(array.Remove(40), Is.True); + + // + Assert.That(array.Remove(16), Is.True); + Assert.That(array.Remove(23), Is.True); + Assert.That(array.Remove(17), Is.True); + Assert.That(array.Remove(19), Is.True); + Assert.That(array.Remove(50), Is.True); + Assert.That(array.Remove(26), Is.True); + Assert.That(array.Remove(21), Is.True); + Assert.That(array.Remove(22), Is.True); + Assert.That(array.Remove(24), Is.True); + }); for (int i = 0; i < 48; i++) { array.Remove(i); } - //Almost empty tree: - Assert.IsFalse(array.Remove(26)); - Assert.IsTrue(array.Remove(48)); - Assert.IsTrue(array.Check(), "Bad tree"); + Assert.Multiple(() => + { + //Almost empty tree: + Assert.That(array.Remove(26), Is.False); + Assert.That(array.Remove(48), Is.True); + Assert.That(array.Check(), Is.True, "Bad tree"); - //Empty tree: - Assert.IsFalse(array.Remove(26)); - Assert.IsTrue(array.Check(), "Bad tree"); + //Empty tree: + Assert.That(array.Remove(26), Is.False); + Assert.That(array.Check(), Is.True, "Bad tree"); + }); } @@ -910,93 +994,117 @@ private void loadup() public void FindPredecessor() { loadup(); - Assert.IsTrue(tree.TryPredecessor(7, out int res) && res == 6); - Assert.IsTrue(tree.TryPredecessor(8, out res) && res == 6); + Assert.Multiple(() => + { + Assert.That(tree.TryPredecessor(7, out int res) && res == 6, Is.True); + Assert.That(tree.TryPredecessor(8, out res) && res == 6, Is.True); - //The bottom - Assert.IsTrue(tree.TryPredecessor(1, out res) && res == 0); + //The bottom + Assert.That(tree.TryPredecessor(1, out res) && res == 0, Is.True); - //The top - Assert.IsTrue(tree.TryPredecessor(39, out res) && res == 38); + //The top + Assert.That(tree.TryPredecessor(39, out res) && res == 38, Is.True); + }); } [Test] public void FindPredecessorTooLow1() { - Assert.IsFalse(tree.TryPredecessor(-2, out int res)); - Assert.AreEqual(0, res); - Assert.IsFalse(tree.TryPredecessor(0, out res)); - Assert.AreEqual(0, res); + Assert.Multiple(() => + { + Assert.That(tree.TryPredecessor(-2, out int res), Is.False); + Assert.That(res, Is.EqualTo(0)); + Assert.That(tree.TryPredecessor(0, out res), Is.False); + Assert.That(res, Is.EqualTo(0)); + }); } [Test] public void FindWeakPredecessor() { loadup(); - Assert.IsTrue(tree.TryWeakPredecessor(7, out int res) && res == 6); - Assert.IsTrue(tree.TryWeakPredecessor(8, out res) && res == 8); + Assert.Multiple(() => + { + Assert.That(tree.TryWeakPredecessor(7, out int res) && res == 6, Is.True); + Assert.That(tree.TryWeakPredecessor(8, out res) && res == 8, Is.True); - //The bottom - Assert.IsTrue(tree.TryWeakPredecessor(1, out res) && res == 0); - Assert.IsTrue(tree.TryWeakPredecessor(0, out res) && res == 0); + //The bottom + Assert.That(tree.TryWeakPredecessor(1, out res) && res == 0, Is.True); + Assert.That(tree.TryWeakPredecessor(0, out res) && res == 0, Is.True); - //The top - Assert.IsTrue(tree.TryWeakPredecessor(39, out res) && res == 38); - Assert.IsTrue(tree.TryWeakPredecessor(38, out res) && res == 38); + //The top + Assert.That(tree.TryWeakPredecessor(39, out res) && res == 38, Is.True); + Assert.That(tree.TryWeakPredecessor(38, out res) && res == 38, Is.True); + }); } [Test] public void FindWeakPredecessorTooLow1() { - Assert.IsFalse(tree.TryWeakPredecessor(-1, out int res)); - Assert.AreEqual(0, res); + Assert.Multiple(() => + { + Assert.That(tree.TryWeakPredecessor(-1, out int res), Is.False); + Assert.That(res, Is.EqualTo(0)); + }); } [Test] public void FindSuccessor() { loadup(); - Assert.IsTrue(tree.TrySuccessor(7, out int res) && res == 8); - Assert.IsTrue(tree.TrySuccessor(8, out res) && res == 10); + Assert.Multiple(() => + { + Assert.That(tree.TrySuccessor(7, out int res) && res == 8, Is.True); + Assert.That(tree.TrySuccessor(8, out res) && res == 10, Is.True); - //The bottom - Assert.IsTrue(tree.TrySuccessor(0, out res) && res == 2); - Assert.IsTrue(tree.TrySuccessor(-1, out res) && res == 0); + //The bottom + Assert.That(tree.TrySuccessor(0, out res) && res == 2, Is.True); + Assert.That(tree.TrySuccessor(-1, out res) && res == 0, Is.True); - //The top - Assert.IsTrue(tree.TrySuccessor(37, out res) && res == 38); + //The top + Assert.That(tree.TrySuccessor(37, out res) && res == 38, Is.True); + }); } [Test] public void FindSuccessorTooHigh() { - Assert.IsFalse(tree.TrySuccessor(38, out int res)); - Assert.AreEqual(0, res); - Assert.IsFalse(tree.TrySuccessor(39, out res)); - Assert.AreEqual(0, res); + Assert.Multiple(() => + { + Assert.That(tree.TrySuccessor(38, out int res), Is.False); + Assert.That(res, Is.EqualTo(0)); + Assert.That(tree.TrySuccessor(39, out res), Is.False); + Assert.That(res, Is.EqualTo(0)); + }); } [Test] public void FindWeakSuccessor() { loadup(); - Assert.IsTrue(tree.TryWeakSuccessor(6, out int res) && res == 6); - Assert.IsTrue(tree.TryWeakSuccessor(7, out res) && res == 8); + Assert.Multiple(() => + { + Assert.That(tree.TryWeakSuccessor(6, out int res) && res == 6, Is.True); + Assert.That(tree.TryWeakSuccessor(7, out res) && res == 8, Is.True); - //The bottom - Assert.IsTrue(tree.TryWeakSuccessor(-1, out res) && res == 0); - Assert.IsTrue(tree.TryWeakSuccessor(0, out res) && res == 0); + //The bottom + Assert.That(tree.TryWeakSuccessor(-1, out res) && res == 0, Is.True); + Assert.That(tree.TryWeakSuccessor(0, out res) && res == 0, Is.True); - //The top - Assert.IsTrue(tree.TryWeakSuccessor(37, out res) && res == 38); - Assert.IsTrue(tree.TryWeakSuccessor(38, out res) && res == 38); + //The top + Assert.That(tree.TryWeakSuccessor(37, out res) && res == 38, Is.True); + Assert.That(tree.TryWeakSuccessor(38, out res) && res == 38, Is.True); + }); } [Test] public void FindWeakSuccessorTooHigh1() { - Assert.IsFalse(tree.TryWeakSuccessor(39, out int res)); - Assert.AreEqual(0, res); + Assert.Multiple(() => + { + Assert.That(tree.TryWeakSuccessor(39, out int res), Is.False); + Assert.That(res, Is.EqualTo(0)); + }); } @@ -1004,14 +1112,17 @@ public void FindWeakSuccessorTooHigh1() public void Predecessor() { loadup(); - Assert.AreEqual(6, tree.Predecessor(7)); - Assert.AreEqual(6, tree.Predecessor(8)); + Assert.Multiple(() => + { + Assert.That(tree.Predecessor(7), Is.EqualTo(6)); + Assert.That(tree.Predecessor(8), Is.EqualTo(6)); - //The bottom - Assert.AreEqual(0, tree.Predecessor(1)); + //The bottom + Assert.That(tree.Predecessor(1), Is.EqualTo(0)); - //The top - Assert.AreEqual(38, tree.Predecessor(39)); + //The top + Assert.That(tree.Predecessor(39), Is.EqualTo(38)); + }); } [Test] @@ -1031,16 +1142,19 @@ public void PredecessorTooLow2() public void WeakPredecessor() { loadup(); - Assert.AreEqual(6, tree.WeakPredecessor(7)); - Assert.AreEqual(8, tree.WeakPredecessor(8)); + Assert.Multiple(() => + { + Assert.That(tree.WeakPredecessor(7), Is.EqualTo(6)); + Assert.That(tree.WeakPredecessor(8), Is.EqualTo(8)); - //The bottom - Assert.AreEqual(0, tree.WeakPredecessor(1)); - Assert.AreEqual(0, tree.WeakPredecessor(0)); + //The bottom + Assert.That(tree.WeakPredecessor(1), Is.EqualTo(0)); + Assert.That(tree.WeakPredecessor(0), Is.EqualTo(0)); - //The top - Assert.AreEqual(38, tree.WeakPredecessor(39)); - Assert.AreEqual(38, tree.WeakPredecessor(38)); + //The top + Assert.That(tree.WeakPredecessor(39), Is.EqualTo(38)); + Assert.That(tree.WeakPredecessor(38), Is.EqualTo(38)); + }); } [Test] @@ -1054,15 +1168,18 @@ public void WeakPredecessorTooLow1() public void Successor() { loadup(); - Assert.AreEqual(8, tree.Successor(7)); - Assert.AreEqual(10, tree.Successor(8)); + Assert.Multiple(() => + { + Assert.That(tree.Successor(7), Is.EqualTo(8)); + Assert.That(tree.Successor(8), Is.EqualTo(10)); - //The bottom - Assert.AreEqual(2, tree.Successor(0)); - Assert.AreEqual(0, tree.Successor(-1)); + //The bottom + Assert.That(tree.Successor(0), Is.EqualTo(2)); + Assert.That(tree.Successor(-1), Is.EqualTo(0)); - //The top - Assert.AreEqual(38, tree.Successor(37)); + //The top + Assert.That(tree.Successor(37), Is.EqualTo(38)); + }); } @@ -1084,16 +1201,19 @@ public void SuccessorTooHigh2() public void WeakSuccessor() { loadup(); - Assert.AreEqual(6, tree.WeakSuccessor(6)); - Assert.AreEqual(8, tree.WeakSuccessor(7)); + Assert.Multiple(() => + { + Assert.That(tree.WeakSuccessor(6), Is.EqualTo(6)); + Assert.That(tree.WeakSuccessor(7), Is.EqualTo(8)); - //The bottom - Assert.AreEqual(0, tree.WeakSuccessor(-1)); - Assert.AreEqual(0, tree.WeakSuccessor(0)); + //The bottom + Assert.That(tree.WeakSuccessor(-1), Is.EqualTo(0)); + Assert.That(tree.WeakSuccessor(0), Is.EqualTo(0)); - //The top - Assert.AreEqual(38, tree.WeakSuccessor(37)); - Assert.AreEqual(38, tree.WeakSuccessor(38)); + //The top + Assert.That(tree.WeakSuccessor(37), Is.EqualTo(38)); + Assert.That(tree.WeakSuccessor(38), Is.EqualTo(38)); + }); } [Test] @@ -1138,16 +1258,19 @@ private void loadup() public void Normal() { loadup(); - Assert.AreEqual(1, tree.FindMin()); - Assert.AreEqual(4, tree.FindMax()); - Assert.AreEqual(1, tree.DeleteMin()); - Assert.AreEqual(4, tree.DeleteMax()); - Assert.IsTrue(tree.Check(), "Bad tree"); - Assert.AreEqual(2, tree.FindMin()); - Assert.AreEqual(3, tree.FindMax()); - Assert.AreEqual(2, tree.DeleteMin()); - Assert.AreEqual(3, tree.DeleteMax()); - Assert.IsTrue(tree.Check(), "Bad tree"); + Assert.Multiple(() => + { + Assert.That(tree.FindMin(), Is.EqualTo(1)); + Assert.That(tree.FindMax(), Is.EqualTo(4)); + Assert.That(tree.DeleteMin(), Is.EqualTo(1)); + Assert.That(tree.DeleteMax(), Is.EqualTo(4)); + Assert.That(tree.Check(), Is.True, "Bad tree"); + Assert.That(tree.FindMin(), Is.EqualTo(2)); + Assert.That(tree.FindMax(), Is.EqualTo(3)); + Assert.That(tree.DeleteMin(), Is.EqualTo(2)); + Assert.That(tree.DeleteMax(), Is.EqualTo(3)); + Assert.That(tree.Check(), Is.True, "Bad tree"); + }); } @@ -1215,40 +1338,49 @@ public void ToArray() { populate(); - int[] a = array.ToArray(); + int[] a = [.. array]; - Assert.AreEqual(4, a.Length); - Assert.AreEqual(10, a[0]); - Assert.AreEqual(30, a[1]); - Assert.AreEqual(50, a[2]); - Assert.AreEqual(70, a[3]); + Assert.Multiple(() => + { + Assert.That(a, Has.Length.EqualTo(4)); + Assert.That(a[0], Is.EqualTo(10)); + Assert.That(a[1], Is.EqualTo(30)); + Assert.That(a[2], Is.EqualTo(50)); + Assert.That(a[3], Is.EqualTo(70)); + }); } [Test] public void GoodIndex() { - Assert.AreEqual(~0, array.IndexOf(20)); - Assert.AreEqual(~0, array.LastIndexOf(20)); + Assert.Multiple(() => + { + Assert.That(array.IndexOf(20), Is.EqualTo(~0)); + Assert.That(array.LastIndexOf(20), Is.EqualTo(~0)); + }); populate(); - Assert.AreEqual(10, array[0]); - Assert.AreEqual(30, array[1]); - Assert.AreEqual(50, array[2]); - Assert.AreEqual(70, array[3]); - Assert.AreEqual(0, array.IndexOf(10)); - Assert.AreEqual(1, array.IndexOf(30)); - Assert.AreEqual(2, array.IndexOf(50)); - Assert.AreEqual(3, array.IndexOf(70)); - Assert.AreEqual(~1, array.IndexOf(20)); - Assert.AreEqual(~0, array.IndexOf(0)); - Assert.AreEqual(~4, array.IndexOf(90)); - Assert.AreEqual(0, array.LastIndexOf(10)); - Assert.AreEqual(1, array.LastIndexOf(30)); - Assert.AreEqual(2, array.LastIndexOf(50)); - Assert.AreEqual(3, array.LastIndexOf(70)); - Assert.AreEqual(~1, array.LastIndexOf(20)); - Assert.AreEqual(~0, array.LastIndexOf(0)); - Assert.AreEqual(~4, array.LastIndexOf(90)); + Assert.Multiple(() => + { + Assert.That(array[0], Is.EqualTo(10)); + Assert.That(array[1], Is.EqualTo(30)); + Assert.That(array[2], Is.EqualTo(50)); + Assert.That(array[3], Is.EqualTo(70)); + Assert.That(array.IndexOf(10), Is.EqualTo(0)); + Assert.That(array.IndexOf(30), Is.EqualTo(1)); + Assert.That(array.IndexOf(50), Is.EqualTo(2)); + Assert.That(array.IndexOf(70), Is.EqualTo(3)); + Assert.That(array.IndexOf(20), Is.EqualTo(~1)); + Assert.That(array.IndexOf(0), Is.EqualTo(~0)); + Assert.That(array.IndexOf(90), Is.EqualTo(~4)); + Assert.That(array.LastIndexOf(10), Is.EqualTo(0)); + Assert.That(array.LastIndexOf(30), Is.EqualTo(1)); + Assert.That(array.LastIndexOf(50), Is.EqualTo(2)); + Assert.That(array.LastIndexOf(70), Is.EqualTo(3)); + Assert.That(array.LastIndexOf(20), Is.EqualTo(~1)); + Assert.That(array.LastIndexOf(0), Is.EqualTo(~0)); + Assert.That(array.LastIndexOf(90), Is.EqualTo(~4)); + }); } @@ -1272,13 +1404,16 @@ public void IndexTooSmall() public void FilledTreeOutsideInput() { populate(); - Assert.AreEqual(0, array.CountFrom(90)); - Assert.AreEqual(0, array.CountFromTo(-20, 0)); - Assert.AreEqual(0, array.CountFromTo(80, 100)); - Assert.AreEqual(0, array.CountTo(0)); - Assert.AreEqual(4, array.CountTo(90)); - Assert.AreEqual(4, array.CountFromTo(-20, 90)); - Assert.AreEqual(4, array.CountFrom(0)); + Assert.Multiple(() => + { + Assert.That(array.CountFrom(90), Is.EqualTo(0)); + Assert.That(array.CountFromTo(-20, 0), Is.EqualTo(0)); + Assert.That(array.CountFromTo(80, 100), Is.EqualTo(0)); + Assert.That(array.CountTo(0), Is.EqualTo(0)); + Assert.That(array.CountTo(90), Is.EqualTo(4)); + Assert.That(array.CountFromTo(-20, 90), Is.EqualTo(4)); + Assert.That(array.CountFrom(0), Is.EqualTo(4)); + }); } @@ -1286,9 +1421,12 @@ public void FilledTreeOutsideInput() public void FilledTreeIntermediateInput() { populate(); - Assert.AreEqual(3, array.CountFrom(20)); - Assert.AreEqual(1, array.CountFromTo(20, 40)); - Assert.AreEqual(2, array.CountTo(40)); + Assert.Multiple(() => + { + Assert.That(array.CountFrom(20), Is.EqualTo(3)); + Assert.That(array.CountFromTo(20, 40), Is.EqualTo(1)); + Assert.That(array.CountTo(40), Is.EqualTo(2)); + }); } @@ -1296,21 +1434,27 @@ public void FilledTreeIntermediateInput() public void FilledTreeMatchingInput() { populate(); - Assert.AreEqual(3, array.CountFrom(30)); - Assert.AreEqual(2, array.CountFromTo(30, 70)); - Assert.AreEqual(0, array.CountFromTo(50, 30)); - Assert.AreEqual(0, array.CountFromTo(50, 50)); - Assert.AreEqual(0, array.CountTo(10)); - Assert.AreEqual(2, array.CountTo(50)); + Assert.Multiple(() => + { + Assert.That(array.CountFrom(30), Is.EqualTo(3)); + Assert.That(array.CountFromTo(30, 70), Is.EqualTo(2)); + Assert.That(array.CountFromTo(50, 30), Is.EqualTo(0)); + Assert.That(array.CountFromTo(50, 50), Is.EqualTo(0)); + Assert.That(array.CountTo(10), Is.EqualTo(0)); + Assert.That(array.CountTo(50), Is.EqualTo(2)); + }); } [Test] public void CountEmptyTree() { - Assert.AreEqual(0, array.CountFrom(20)); - Assert.AreEqual(0, array.CountFromTo(20, 40)); - Assert.AreEqual(0, array.CountTo(40)); + Assert.Multiple(() => + { + Assert.That(array.CountFrom(20), Is.EqualTo(0)); + Assert.That(array.CountFromTo(20, 40), Is.EqualTo(0)); + Assert.That(array.CountTo(40), Is.EqualTo(0)); + }); } @@ -1351,7 +1495,7 @@ public void CurrentAfterModification() { e.MoveNext(); tree.Add(34); - Assert.AreEqual(0, e.Current); + Assert.That(e.Current, Is.EqualTo(0)); } @@ -1388,7 +1532,7 @@ public void MoveNextAfterClear() public void Dispose() { tree = null; - e = null; + e.Dispose(); } } @@ -1418,7 +1562,7 @@ public void CurrentAfterModification() { e.MoveNext(); tree.Add(34); - Assert.AreEqual(3, e.Current); + Assert.That(e.Current, Is.EqualTo(3)); } @@ -1455,7 +1599,7 @@ public void MoveNextAfterClear() public void Dispose() { tree = null; - e = null; + e.Dispose(); } } } @@ -1533,13 +1677,16 @@ public void Init() [Test] public void Apply() { - Simple simple1 = new Simple(); + Simple simple1 = new(); array.Apply(new Action(simple1.apply)); - Assert.AreEqual(0, simple1.appfield1); - Assert.AreEqual(0, simple1.appfield2); + Assert.Multiple(() => + { + Assert.That(simple1.appfield1, Is.EqualTo(0)); + Assert.That(simple1.appfield2, Is.EqualTo(0)); + }); - Simple simple2 = new Simple(); + Simple simple2 = new(); for (int i = 0; i < 10; i++) { @@ -1547,101 +1694,131 @@ public void Apply() } array.Apply(new Action(simple2.apply)); - Assert.AreEqual(10, simple2.appfield1); - Assert.AreEqual(285, simple2.appfield2); + Assert.Multiple(() => + { + Assert.That(simple2.appfield1, Is.EqualTo(10)); + Assert.That(simple2.appfield2, Is.EqualTo(285)); + }); } [Test] public void All() { - Assert.IsTrue(array.All(new Func(never))); - Assert.IsTrue(array.All(new Func(even))); - Assert.IsTrue(array.All(new Func(always))); + Assert.Multiple(() => + { + Assert.That(array.All(new Func(never)), Is.True); + Assert.That(array.All(new Func(even)), Is.True); + Assert.That(array.All(new Func(always)), Is.True); + }); for (int i = 0; i < 10; i++) { array.Add(i); } - Assert.IsFalse(array.All(new Func(never))); - Assert.IsFalse(array.All(new Func(even))); - Assert.IsTrue(array.All(new Func(always))); + Assert.Multiple(() => + { + Assert.That(array.All(new Func(never)), Is.False); + Assert.That(array.All(new Func(even)), Is.False); + Assert.That(array.All(new Func(always)), Is.True); + }); array.Clear(); for (int i = 0; i < 10; i++) { array.Add(i * 2); } - Assert.IsFalse(array.All(new Func(never))); - Assert.IsTrue(array.All(new Func(even))); - Assert.IsTrue(array.All(new Func(always))); + Assert.Multiple(() => + { + Assert.That(array.All(new Func(never)), Is.False); + Assert.That(array.All(new Func(even)), Is.True); + Assert.That(array.All(new Func(always)), Is.True); + }); array.Clear(); for (int i = 0; i < 10; i++) { array.Add(i * 2 + 1); } - Assert.IsFalse(array.All(new Func(never))); - Assert.IsFalse(array.All(new Func(even))); - Assert.IsTrue(array.All(new Func(always))); + Assert.Multiple(() => + { + Assert.That(array.All(new Func(never)), Is.False); + Assert.That(array.All(new Func(even)), Is.False); + Assert.That(array.All(new Func(always)), Is.True); + }); } [Test] public void Exists() { - Assert.IsFalse(array.Exists(new Func(never))); - Assert.IsFalse(array.Exists(new Func(even))); - Assert.IsFalse(array.Exists(new Func(always))); + Assert.Multiple(() => + { + Assert.That(array.Exists(new Func(never)), Is.False); + Assert.That(array.Exists(new Func(even)), Is.False); + Assert.That(array.Exists(new Func(always)), Is.False); + }); for (int i = 0; i < 10; i++) { array.Add(i); } - Assert.IsFalse(array.Exists(new Func(never))); - Assert.IsTrue(array.Exists(new Func(even))); - Assert.IsTrue(array.Exists(new Func(always))); + Assert.Multiple(() => + { + Assert.That(array.Exists(new Func(never)), Is.False); + Assert.That(array.Exists(new Func(even)), Is.True); + Assert.That(array.Exists(new Func(always)), Is.True); + }); array.Clear(); for (int i = 0; i < 10; i++) { array.Add(i * 2); } - Assert.IsFalse(array.Exists(new Func(never))); - Assert.IsTrue(array.Exists(new Func(even))); - Assert.IsTrue(array.Exists(new Func(always))); + Assert.Multiple(() => + { + Assert.That(array.Exists(new Func(never)), Is.False); + Assert.That(array.Exists(new Func(even)), Is.True); + Assert.That(array.Exists(new Func(always)), Is.True); + }); array.Clear(); for (int i = 0; i < 10; i++) { array.Add(i * 2 + 1); } - Assert.IsFalse(array.Exists(new Func(never))); - Assert.IsFalse(array.Exists(new Func(even))); - Assert.IsTrue(array.Exists(new Func(always))); + Assert.Multiple(() => + { + Assert.That(array.Exists(new Func(never)), Is.False); + Assert.That(array.Exists(new Func(even)), Is.False); + Assert.That(array.Exists(new Func(always)), Is.True); + }); } [Test] public void FindAll() { - Assert.AreEqual(0, array.FindAll(new Func(never)).Count); + Assert.That(array.FindAll(new Func(never)), Is.Empty); for (int i = 0; i < 10; i++) { array.Add(i); } - Assert.AreEqual(0, array.FindAll(new Func(never)).Count); - Assert.AreEqual(10, array.FindAll(new Func(always)).Count); - Assert.AreEqual(5, array.FindAll(new Func(even)).Count); - Assert.IsTrue(((SortedArray)array.FindAll(new Func(even))).Check()); + Assert.Multiple(() => + { + Assert.That(array.FindAll(new Func(never)), Is.Empty); + Assert.That(array.FindAll(new Func(always)), Has.Count.EqualTo(10)); + Assert.That(array.FindAll(new Func(even)), Has.Count.EqualTo(5)); + Assert.That(((SortedArray)array.FindAll(new Func(even))).Check(), Is.True); + }); } [Test] public void Map() { - Assert.AreEqual(0, array.Map(new Func(themap), new SC()).Count); + Assert.That(array.Map(new Func(themap), new SC()), Is.Empty); for (int i = 0; i < 11; i++) { array.Add(i * i * i); @@ -1649,12 +1826,18 @@ public void Map() IIndexedSorted res = array.Map(new Func(themap), new SC()); - Assert.IsTrue(((SortedArray)res).Check()); - Assert.AreEqual(11, res.Count); - Assert.AreEqual("AA 0 BB", res[0]); - Assert.AreEqual("AA 27 BB", res[3]); - Assert.AreEqual("AA 125 BB", res[5]); - Assert.AreEqual("AA 1000 BB", res[10]); + Assert.Multiple(() => + { + Assert.That(((SortedArray)res).Check(), Is.True); + Assert.That(res, Has.Count.EqualTo(11)); + }); + Assert.Multiple(() => + { + Assert.That(res[0], Is.EqualTo("AA 0 BB")); + Assert.That(res[3], Is.EqualTo("AA 27 BB")); + Assert.That(res[5], Is.EqualTo("AA 125 BB")); + Assert.That(res[10], Is.EqualTo("AA 1000 BB")); + }); } @@ -1667,7 +1850,7 @@ public void BadMap() } var exception = Assert.Throws(() => { ISorted res = array.Map(new Func(badmap), new SC()); }); - Assert.AreEqual("mapper not monotonic", exception.Message); + Assert.That(exception.Message, Is.EqualTo("mapper not monotonic")); } @@ -1679,14 +1862,17 @@ public void Cut() array.Add(i); } - Assert.IsTrue(array.Cut(new CubeRoot(27), out int low, out bool lval, out int high, out bool hval)); - Assert.IsTrue(lval && hval); - Assert.AreEqual(4, high); - Assert.AreEqual(2, low); - Assert.IsFalse(array.Cut(new CubeRoot(30), out low, out lval, out high, out hval)); - Assert.IsTrue(lval && hval); - Assert.AreEqual(4, high); - Assert.AreEqual(3, low); + Assert.Multiple(() => + { + Assert.That(array.Cut(new CubeRoot(27), out int low, out bool lval, out int high, out bool hval), Is.True); + Assert.That(lval && hval, Is.True); + Assert.That(high, Is.EqualTo(4)); + Assert.That(low, Is.EqualTo(2)); + Assert.That(array.Cut(new CubeRoot(30), out low, out lval, out high, out hval), Is.False); + Assert.That(lval && hval, Is.True); + Assert.That(high, Is.EqualTo(4)); + Assert.That(low, Is.EqualTo(3)); + }); } @@ -1698,14 +1884,17 @@ public void CutInt() array.Add(2 * i); } - Assert.IsFalse(array.Cut(new IC(3), out int low, out bool lval, out int high, out bool hval)); - Assert.IsTrue(lval && hval); - Assert.AreEqual(4, high); - Assert.AreEqual(2, low); - Assert.IsTrue(array.Cut(new IC(6), out low, out lval, out high, out hval)); - Assert.IsTrue(lval && hval); - Assert.AreEqual(8, high); - Assert.AreEqual(4, low); + Assert.Multiple(() => + { + Assert.That(array.Cut(new IC(3), out int low, out bool lval, out int high, out bool hval), Is.False); + Assert.That(lval && hval, Is.True); + Assert.That(high, Is.EqualTo(4)); + Assert.That(low, Is.EqualTo(2)); + Assert.That(array.Cut(new IC(6), out low, out lval, out high, out hval), Is.True); + Assert.That(lval && hval, Is.True); + Assert.That(high, Is.EqualTo(8)); + Assert.That(low, Is.EqualTo(4)); + }); } @@ -1717,31 +1906,41 @@ public void CutInterval() array.Add(2 * i); } - Assert.IsTrue(array.Cut(new Interval(5, 9), out int lo, out bool lv, out int hi, out bool hv)); - Assert.IsTrue(lv && hv); - Assert.AreEqual(10, hi); - Assert.AreEqual(4, lo); - Assert.IsTrue(array.Cut(new Interval(6, 10), out lo, out lv, out hi, out hv)); - Assert.IsTrue(lv && hv); - Assert.AreEqual(12, hi); - Assert.AreEqual(4, lo); + Assert.That(array.Cut(new Interval(5, 9), out int lo, out bool lv, out int hi, out bool hv), Is.True); + Assert.That(lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(10)); + Assert.That(lo, Is.EqualTo(4)); + Assert.That(array.Cut(new Interval(6, 10), out lo, out lv, out hi, out hv), Is.True); + Assert.That(lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(12)); + Assert.That(lo, Is.EqualTo(4)); + for (int i = 0; i < 100; i++) { array.Add(2 * i); } array.Cut(new Interval(77, 105), out lo, out lv, out hi, out hv); - Assert.IsTrue(lv && hv); - Assert.AreEqual(106, hi); - Assert.AreEqual(76, lo); + Assert.Multiple(() => + { + Assert.That(lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(106)); + Assert.That(lo, Is.EqualTo(76)); + }); array.Cut(new Interval(5, 7), out lo, out lv, out hi, out hv); - Assert.IsTrue(lv && hv); - Assert.AreEqual(8, hi); - Assert.AreEqual(4, lo); + Assert.Multiple(() => + { + Assert.That(lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(8)); + Assert.That(lo, Is.EqualTo(4)); + }); array.Cut(new Interval(80, 110), out lo, out lv, out hi, out hv); - Assert.IsTrue(lv && hv); - Assert.AreEqual(112, hi); - Assert.AreEqual(78, lo); + Assert.Multiple(() => + { + Assert.That(lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(112)); + Assert.That(lo, Is.EqualTo(78)); + }); } @@ -1753,12 +1952,15 @@ public void UpperCut() array.Add(i); } - Assert.IsFalse(array.Cut(new CubeRoot(1000), out int l, out bool lv, out _, out bool hv)); - Assert.IsTrue(lv && !hv); - Assert.AreEqual(9, l); - Assert.IsFalse(array.Cut(new CubeRoot(-50), out _, out lv, out int h, out hv)); - Assert.IsTrue(!lv && hv); - Assert.AreEqual(0, h); + Assert.Multiple(() => + { + Assert.That(array.Cut(new CubeRoot(1000), out int l, out bool lv, out _, out bool hv), Is.False); + Assert.That(lv && !hv, Is.True); + Assert.That(l, Is.EqualTo(9)); + Assert.That(array.Cut(new CubeRoot(-50), out _, out lv, out int h, out hv), Is.False); + Assert.That(!lv && hv, Is.True); + Assert.That(h, Is.EqualTo(0)); + }); } @@ -1788,8 +1990,8 @@ public class AddAll public void EmptyEmpty() { array.AddAll(new FunEnumerable(0, new Func(sqr))); - Assert.AreEqual(0, array.Count); - Assert.IsTrue(array.Check()); + Assert.That(array, Is.Empty); + Assert.That(array.Check(), Is.True); } @@ -1802,8 +2004,8 @@ public void SomeEmpty() } array.AddAll(new FunEnumerable(0, new Func(sqr))); - Assert.AreEqual(5, array.Count); - Assert.IsTrue(array.Check()); + Assert.That(array, Has.Count.EqualTo(5)); + Assert.That(array.Check(), Is.True); } @@ -1811,12 +2013,15 @@ public void SomeEmpty() public void EmptySome() { array.AddAll(new FunEnumerable(4, new Func(sqr))); - Assert.AreEqual(4, array.Count); - Assert.IsTrue(array.Check()); - Assert.AreEqual(0, array[0]); - Assert.AreEqual(1, array[1]); - Assert.AreEqual(4, array[2]); - Assert.AreEqual(9, array[3]); + Assert.Multiple(() => + { + Assert.That(array, Has.Count.EqualTo(4)); + Assert.That(array.Check(), Is.True); + Assert.That(array[0], Is.EqualTo(0)); + Assert.That(array[1], Is.EqualTo(1)); + Assert.That(array[2], Is.EqualTo(4)); + Assert.That(array[3], Is.EqualTo(9)); + }); } @@ -1829,9 +2034,12 @@ public void SomeSome() } array.AddAll(new FunEnumerable(4, new Func(sqr))); - Assert.AreEqual(9, array.Count); - Assert.IsTrue(array.Check()); - Assert.IsTrue(IC.Eq(array, 0, 1, 3, 4, 5, 6, 7, 8, 9)); + Assert.That(array, Has.Count.EqualTo(9)); + Assert.Multiple(() => + { + Assert.That(array.Check(), Is.True); + Assert.That(IC.Eq(array, 0, 1, 3, 4, 5, 6, 7, 8, 9), Is.True); + }); } @@ -1860,8 +2068,8 @@ public class AddSorted public void EmptyEmpty() { array.AddSorted(new FunEnumerable(0, new Func(sqr))); - Assert.AreEqual(0, array.Count); - Assert.IsTrue(array.Check()); + Assert.That(array, Is.Empty); + Assert.That(array.Check(), Is.True); } @@ -1875,8 +2083,8 @@ public void SomeEmpty() } array.AddSorted(new FunEnumerable(0, new Func(sqr))); - Assert.AreEqual(5, array.Count); - Assert.IsTrue(array.Check()); + Assert.That(array, Has.Count.EqualTo(5)); + Assert.That(array.Check(), Is.True); } @@ -1885,12 +2093,15 @@ public void SomeEmpty() public void EmptySome() { array.AddSorted(new FunEnumerable(4, new Func(sqr))); - Assert.AreEqual(4, array.Count); - Assert.IsTrue(array.Check()); - Assert.AreEqual(0, array[0]); - Assert.AreEqual(1, array[1]); - Assert.AreEqual(4, array[2]); - Assert.AreEqual(9, array[3]); + Assert.That(array, Has.Count.EqualTo(4)); + Assert.Multiple(() => + { + Assert.That(array.Check(), Is.True); + Assert.That(array[0], Is.EqualTo(0)); + Assert.That(array[1], Is.EqualTo(1)); + Assert.That(array[2], Is.EqualTo(4)); + Assert.That(array[3], Is.EqualTo(9)); + }); } @@ -1904,16 +2115,19 @@ public void SomeSome() } array.AddSorted(new FunEnumerable(4, new Func(sqr))); - Assert.AreEqual(9, array.Count); - Assert.IsTrue(array.Check()); - Assert.IsTrue(IC.Eq(array, 0, 1, 3, 4, 5, 6, 7, 8, 9)); + Assert.That(array, Has.Count.EqualTo(9)); + Assert.Multiple(() => + { + Assert.That(array.Check(), Is.True); + Assert.That(IC.Eq(array, 0, 1, 3, 4, 5, 6, 7, 8, 9), Is.True); + }); } [Test] public void EmptyBad() { var exception = Assert.Throws(() => array.AddSorted(new FunEnumerable(9, new Func(bad)))); - Assert.AreEqual("Argument not sorted", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Argument not sorted")); } @@ -1948,30 +2162,45 @@ public void Init() public void RemoveAll() { array.RemoveAll(array2.RangeFromTo(3, 7)); - Assert.AreEqual(8, array.Count); - Assert.IsTrue(array.Check()); - Assert.IsTrue(IC.Eq(array, 0, 1, 2, 3, 5, 7, 8, 9)); + Assert.Multiple(() => + { + Assert.That(array, Has.Count.EqualTo(8)); + Assert.That(array.Check(), Is.True); + Assert.That(IC.Eq(array, 0, 1, 2, 3, 5, 7, 8, 9), Is.True); + }); array.RemoveAll(array2.RangeFromTo(3, 7)); - Assert.AreEqual(8, array.Count); - Assert.IsTrue(array.Check()); - Assert.IsTrue(IC.Eq(array, 0, 1, 2, 3, 5, 7, 8, 9)); + Assert.Multiple(() => + { + Assert.That(array, Has.Count.EqualTo(8)); + Assert.That(array.Check(), Is.True); + Assert.That(IC.Eq(array, 0, 1, 2, 3, 5, 7, 8, 9), Is.True); + }); array.RemoveAll(array2.RangeFromTo(13, 17)); - Assert.AreEqual(8, array.Count); - Assert.IsTrue(array.Check()); - Assert.IsTrue(IC.Eq(array, 0, 1, 2, 3, 5, 7, 8, 9)); + Assert.That(array, Has.Count.EqualTo(8)); + Assert.Multiple(() => + { + Assert.That(array.Check(), Is.True); + Assert.That(IC.Eq(array, 0, 1, 2, 3, 5, 7, 8, 9), Is.True); + }); array.RemoveAll(array2.RangeFromTo(3, 17)); - Assert.AreEqual(7, array.Count); - Assert.IsTrue(array.Check()); - Assert.IsTrue(IC.Eq(array, 0, 1, 2, 3, 5, 7, 9)); + Assert.That(array, Has.Count.EqualTo(7)); + Assert.Multiple(() => + { + Assert.That(array.Check(), Is.True); + Assert.That(IC.Eq(array, 0, 1, 2, 3, 5, 7, 9), Is.True); + }); for (int i = 0; i < 10; i++) { array2.Add(i); } array.RemoveAll(array2.RangeFromTo(-1, 10)); - Assert.AreEqual(0, array.Count); - Assert.IsTrue(array.Check()); - Assert.IsTrue(IC.Eq(array)); + Assert.Multiple(() => + { + Assert.That(array, Is.Empty); + Assert.That(array.Check(), Is.True); + Assert.That(IC.Eq(array), Is.True); + }); } @@ -1979,53 +2208,74 @@ public void RemoveAll() public void RetainAll() { array.RetainAll(array2.RangeFromTo(3, 17)); - Assert.AreEqual(3, array.Count); - Assert.IsTrue(array.Check()); - Assert.IsTrue(IC.Eq(array, 4, 6, 8)); + Assert.Multiple(() => + { + Assert.That(array, Has.Count.EqualTo(3)); + Assert.That(array.Check(), Is.True); + Assert.That(IC.Eq(array, 4, 6, 8), Is.True); + }); array.RetainAll(array2.RangeFromTo(1, 17)); - Assert.AreEqual(3, array.Count); - Assert.IsTrue(array.Check()); - Assert.IsTrue(IC.Eq(array, 4, 6, 8)); + Assert.That(array, Has.Count.EqualTo(3)); + Assert.Multiple(() => + { + Assert.That(array.Check(), Is.True); + Assert.That(IC.Eq(array, 4, 6, 8), Is.True); + }); array.RetainAll(array2.RangeFromTo(3, 5)); - Assert.AreEqual(1, array.Count); - Assert.IsTrue(array.Check()); - Assert.IsTrue(IC.Eq(array, 4)); + Assert.That(array, Has.Count.EqualTo(1)); + Assert.Multiple(() => + { + Assert.That(array.Check(), Is.True); + Assert.That(IC.Eq(array, 4), Is.True); + }); array.RetainAll(array2.RangeFromTo(7, 17)); - Assert.AreEqual(0, array.Count); - Assert.IsTrue(array.Check()); - Assert.IsTrue(IC.Eq(array)); + Assert.That(array, Is.Empty); + Assert.Multiple(() => + { + Assert.That(array.Check(), Is.True); + Assert.That(IC.Eq(array), Is.True); + }); for (int i = 0; i < 10; i++) { array.Add(i); } array.RetainAll(array2.RangeFromTo(5, 5)); - Assert.AreEqual(0, array.Count); - Assert.IsTrue(array.Check()); - Assert.IsTrue(IC.Eq(array)); + Assert.Multiple(() => + { + Assert.That(array, Is.Empty); + Assert.That(array.Check(), Is.True); + Assert.That(IC.Eq(array), Is.True); + }); for (int i = 0; i < 10; i++) { array.Add(i); } array.RetainAll(array2.RangeFromTo(15, 25)); - Assert.AreEqual(0, array.Count); - Assert.IsTrue(array.Check()); - Assert.IsTrue(IC.Eq(array)); + Assert.Multiple(() => + { + Assert.That(array, Is.Empty); + Assert.That(array.Check(), Is.True); + Assert.That(IC.Eq(array), Is.True); + }); } [Test] public void ContainsAll() { - Assert.IsFalse(array.ContainsAll(array2)); - Assert.IsTrue(array.ContainsAll(array)); + Assert.Multiple(() => + { + Assert.That(array.ContainsAll(array2), Is.False); + Assert.That(array.ContainsAll(array), Is.True); + }); array2.Clear(); - Assert.IsTrue(array.ContainsAll(array2)); + Assert.That(array.ContainsAll(array2), Is.True); array.Clear(); - Assert.IsTrue(array.ContainsAll(array2)); + Assert.That(array.ContainsAll(array2), Is.True); array2.Add(8); - Assert.IsFalse(array.ContainsAll(array2)); + Assert.That(array.ContainsAll(array2), Is.False); } @@ -2033,17 +2283,26 @@ public void ContainsAll() public void RemoveInterval() { array.RemoveInterval(3, 4); - Assert.IsTrue(array.Check()); - Assert.AreEqual(6, array.Count); - Assert.IsTrue(IC.Eq(array, 0, 1, 2, 7, 8, 9)); + Assert.Multiple(() => + { + Assert.That(array.Check(), Is.True); + Assert.That(array, Has.Count.EqualTo(6)); + Assert.That(IC.Eq(array, 0, 1, 2, 7, 8, 9), Is.True); + }); array.RemoveInterval(2, 3); - Assert.IsTrue(array.Check()); - Assert.AreEqual(3, array.Count); - Assert.IsTrue(IC.Eq(array, 0, 1, 9)); + Assert.Multiple(() => + { + Assert.That(array.Check(), Is.True); + Assert.That(array, Has.Count.EqualTo(3)); + Assert.That(IC.Eq(array, 0, 1, 9), Is.True); + }); array.RemoveInterval(0, 3); - Assert.IsTrue(array.Check()); - Assert.AreEqual(0, array.Count); - Assert.IsTrue(IC.Eq(array)); + Assert.Multiple(() => + { + Assert.That(array.Check(), Is.True); + Assert.That(array, Is.Empty); + Assert.That(IC.Eq(array), Is.True); + }); } @@ -2073,9 +2332,9 @@ public void GetRange() { SCG.IEnumerable e = array[3, 3]; - Assert.IsTrue(IC.Eq(e, 3, 4, 5)); + Assert.That(IC.Eq(e, 3, 4, 5), Is.True); e = array[3, 0]; - Assert.IsTrue(IC.Eq(e)); + Assert.That(IC.Eq(e), Is.True); } [Test] @@ -2110,22 +2369,22 @@ namespace Sync public class SyncRoot { private SortedArray tree; - private readonly Object mySyncRoot = new Object(); + private readonly object mySyncRoot = new(); private readonly int sz = 5000; [Test] public void Safe() { - System.Threading.Thread t1 = new System.Threading.Thread(new System.Threading.ThreadStart(safe1)); - System.Threading.Thread t2 = new System.Threading.Thread(new System.Threading.ThreadStart(safe2)); + System.Threading.Thread t1 = new(new System.Threading.ThreadStart(safe1)); + System.Threading.Thread t2 = new(new System.Threading.ThreadStart(safe2)); t1.Start(); t2.Start(); t1.Join(); t2.Join(); - Assert.AreEqual(2 * sz + 1, tree.Count); - Assert.IsTrue(tree.Check()); + Assert.That(tree, Has.Count.EqualTo(2 * sz + 1)); + Assert.That(tree.Check(), Is.True); } @@ -2136,8 +2395,8 @@ public void UnSafe() for (int i = 0; i < 10; i++) { - System.Threading.Thread t1 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe1)); - System.Threading.Thread t2 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe2)); + System.Threading.Thread t1 = new(new System.Threading.ThreadStart(unsafe1)); + System.Threading.Thread t2 = new(new System.Threading.ThreadStart(unsafe2)); t1.Start(); t2.Start(); @@ -2150,21 +2409,21 @@ public void UnSafe() } } - Assert.IsTrue(bad, "No sync problems!"); + Assert.That(bad, Is.True, "No sync problems!"); } [Test] public void SafeUnSafe() { - System.Threading.Thread t1 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe1)); - System.Threading.Thread t2 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe2)); + System.Threading.Thread t1 = new(new System.Threading.ThreadStart(unsafe1)); + System.Threading.Thread t2 = new(new System.Threading.ThreadStart(unsafe2)); t1.Start(); t1.Join(); t2.Start(); t2.Join(); - Assert.AreEqual(2 * sz + 1, tree.Count); + Assert.That(tree, Has.Count.EqualTo(2 * sz + 1)); } @@ -2284,10 +2543,10 @@ private class A [Test] public void Safe() { - A a = new A(tree); + A a = new(tree); a.traverse(); - Assert.AreEqual(sz, a.count); + Assert.That(a.count, Is.EqualTo(sz)); } @@ -2314,7 +2573,7 @@ public void RegrettablyUnsafe() for (int i = 0; i < 10; i++) { - Assert.AreEqual(sz, a[i].count); + Assert.That(a[i].count, Is.EqualTo(sz)); } } @@ -2347,7 +2606,7 @@ public void Init() [Test] public void EmptyEmpty() { - Assert.IsTrue(dit.SequencedEquals(dat)); + Assert.That(dit.SequencedEquals(dat), Is.True); } @@ -2355,23 +2614,29 @@ public void EmptyEmpty() public void EmptyNonEmpty() { dit.Add(3); - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsFalse(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dat.SequencedEquals(dit), Is.False); + }); } [Test] public void HashVal() { - Assert.AreEqual(CHC.SequencedHashCode(), dit.GetSequencedHashCode()); + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode())); dit.Add(3); - Assert.AreEqual(CHC.SequencedHashCode(3), dit.GetSequencedHashCode()); + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(3))); dit.Add(7); - Assert.AreEqual(CHC.SequencedHashCode(3, 7), dit.GetSequencedHashCode()); - Assert.AreEqual(CHC.SequencedHashCode(), dut.GetSequencedHashCode()); + Assert.Multiple(() => + { + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(3, 7))); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode())); + }); dut.Add(3); - Assert.AreEqual(CHC.SequencedHashCode(3), dut.GetSequencedHashCode()); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(3))); dut.Add(7); - Assert.AreEqual(CHC.SequencedHashCode(7, 3), dut.GetSequencedHashCode()); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(7, 3))); } @@ -2381,11 +2646,17 @@ public void Normal() dit.Add(3); dit.Add(7); dat.Add(3); - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsFalse(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dat.SequencedEquals(dit), Is.False); + }); dat.Add(7); - Assert.IsTrue(dit.SequencedEquals(dat)); - Assert.IsTrue(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.True); + Assert.That(dat.SequencedEquals(dit), Is.True); + }); } @@ -2394,23 +2665,29 @@ public void WrongOrder() { dit.Add(3); dut.Add(3); - Assert.IsTrue(dit.SequencedEquals(dut)); - Assert.IsTrue(dut.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dut), Is.True); + Assert.That(dut.SequencedEquals(dit), Is.True); + }); dit.Add(7); dut.Add(7); - Assert.IsFalse(dit.SequencedEquals(dut)); - Assert.IsFalse(dut.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dut), Is.False); + Assert.That(dut.SequencedEquals(dit), Is.False); + }); } [Test] public void Reflexive() { - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); dit.Add(3); - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); dit.Add(7); - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); } @@ -2443,7 +2720,7 @@ public void Init() [Test] public void EmptyEmpty() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); + Assert.That(dit.UnsequencedEquals(dat), Is.True); } @@ -2451,24 +2728,30 @@ public void EmptyEmpty() public void EmptyNonEmpty() { dit.Add(3); - Assert.IsFalse(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.False); + Assert.That(dat.UnsequencedEquals(dit), Is.False); + }); } [Test] public void HashVal() { - Assert.AreEqual(CHC.UnsequencedHashCode(), dit.GetUnsequencedHashCode()); + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode())); dit.Add(3); - Assert.AreEqual(CHC.UnsequencedHashCode(3), dit.GetUnsequencedHashCode()); + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3))); dit.Add(7); - Assert.AreEqual(CHC.UnsequencedHashCode(3, 7), dit.GetUnsequencedHashCode()); - Assert.AreEqual(CHC.UnsequencedHashCode(), dut.GetUnsequencedHashCode()); + Assert.Multiple(() => + { + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3, 7))); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode())); + }); dut.Add(3); - Assert.AreEqual(CHC.UnsequencedHashCode(3), dut.GetUnsequencedHashCode()); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3))); dut.Add(7); - Assert.AreEqual(CHC.UnsequencedHashCode(7, 3), dut.GetUnsequencedHashCode()); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(7, 3))); } @@ -2478,11 +2761,17 @@ public void Normal() dit.Add(3); dit.Add(7); dat.Add(3); - Assert.IsFalse(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.False); + Assert.That(dat.UnsequencedEquals(dit), Is.False); + }); dat.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsTrue(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dat.UnsequencedEquals(dit), Is.True); + }); } @@ -2491,23 +2780,29 @@ public void WrongOrder() { dit.Add(3); dut.Add(3); - Assert.IsTrue(dit.UnsequencedEquals(dut)); - Assert.IsTrue(dut.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dut), Is.True); + Assert.That(dut.UnsequencedEquals(dit), Is.True); + }); dit.Add(7); dut.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dut)); - Assert.IsTrue(dut.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dut), Is.True); + Assert.That(dut.UnsequencedEquals(dit), Is.True); + }); } [Test] public void Reflexive() { - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); dit.Add(3); - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); dit.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); } diff --git a/C5.Tests/BasesTest.cs b/C5.Tests/BasesTest.cs index 13a993f7..b9c5cbfd 100644 --- a/C5.Tests/BasesTest.cs +++ b/C5.Tests/BasesTest.cs @@ -15,7 +15,7 @@ public class ArrayBaseTest { private class ABT : ArrayBase { - public ABT() : base(8, C5.EqualityComparer.Default) { } + public ABT() : base(8, EqualityComparer.Default) { } public override string Choose() { if (size > 0) { return array[0]; } throw new NoSuchItemException(); } @@ -29,15 +29,14 @@ public ABT() : base(8, C5.EqualityComparer.Default) { } [Test] public void Check() { - ABT abt = new ABT + ABT abt = new() { thesize = 3 }; abt[2] = "aaa"; - // Assert.IsFalse(abt.Check()); abt[0] = "##"; abt[1] = "##"; - Assert.IsTrue(abt.Check()); + Assert.That(abt.Check(), Is.True); } } } @@ -64,12 +63,15 @@ public int CompareTo(dbl that) public void GenericC() { SCG.IComparer h = SCG.Comparer.Default; - dbl s = new dbl(3.4); - dbl t = new dbl(3.4); - dbl u = new dbl(7.4); + dbl s = new(3.4); + dbl t = new(3.4); + dbl u = new(7.4); - Assert.AreEqual(0, h.Compare(s, t)); - Assert.IsTrue(h.Compare(s, u) < 0); + Assert.Multiple(() => + { + Assert.That(h.Compare(s, t), Is.EqualTo(0)); + Assert.That(h.Compare(s, u), Is.LessThan(0)); + }); } @@ -81,8 +83,11 @@ public void OrdinaryC() string t = "bamse"; string u = "bimse"; - Assert.AreEqual(0, h.Compare(s, t)); - Assert.IsTrue(h.Compare(s, u) < 0); + Assert.Multiple(() => + { + Assert.That(h.Compare(s, t), Is.EqualTo(0)); + Assert.That(h.Compare(s, u), Is.LessThan(0)); + }); } @@ -90,13 +95,16 @@ public void OrdinaryC() public void GenericCViaBuilder() { SCG.IComparer h = SCG.Comparer.Default; - dbl s = new dbl(3.4); - dbl t = new dbl(3.4); - dbl u = new dbl(7.4); + dbl s = new(3.4); + dbl t = new(3.4); + dbl u = new(7.4); - Assert.AreEqual(0, h.Compare(s, t)); - Assert.IsTrue(h.Compare(s, u) < 0); - Assert.AreSame(h, SCG.Comparer.Default); + Assert.Multiple(() => + { + Assert.That(h.Compare(s, t), Is.EqualTo(0)); + Assert.That(h.Compare(s, u), Is.LessThan(0)); + Assert.That(SCG.Comparer.Default, Is.SameAs(h)); + }); } @@ -108,9 +116,12 @@ public void OrdinaryCViaBuilder() string t = "bamse"; string u = "bimse"; - Assert.AreEqual(0, h.Compare(s, t)); - Assert.IsTrue(h.Compare(s, u) < 0); - Assert.AreSame(h, SCG.Comparer.Default); + Assert.Multiple(() => + { + Assert.That(h.Compare(s, t), Is.EqualTo(0)); + Assert.That(h.Compare(s, u), Is.LessThan(0)); + Assert.That(SCG.Comparer.Default, Is.SameAs(h)); + }); } @@ -118,13 +129,16 @@ public void ComparerViaBuilderTest(T item1, T item2) where T : IComparable { SCG.IComparer h = SCG.Comparer.Default; - Assert.AreSame(h, SCG.Comparer.Default); - Assert.AreEqual(0, h.Compare(item1, item1)); - Assert.AreEqual(0, h.Compare(item2, item2)); - Assert.IsTrue(h.Compare(item1, item2) < 0); - Assert.IsTrue(h.Compare(item2, item1) > 0); - Assert.AreEqual(Math.Sign(item1.CompareTo(item2)), Math.Sign(h.Compare(item1, item2))); - Assert.AreEqual(Math.Sign(item2.CompareTo(item1)), Math.Sign(h.Compare(item2, item1))); + Assert.Multiple(() => + { + Assert.That(SCG.Comparer.Default, Is.SameAs(h)); + Assert.That(h.Compare(item1, item1), Is.EqualTo(0)); + Assert.That(h.Compare(item2, item2), Is.EqualTo(0)); + Assert.That(h.Compare(item1, item2), Is.LessThan(0)); + Assert.That(h.Compare(item2, item1), Is.GreaterThan(0)); + Assert.That(Math.Sign(h.Compare(item1, item2)), Is.EqualTo(Math.Sign(item1.CompareTo(item2)))); + Assert.That(Math.Sign(h.Compare(item2, item1)), Is.EqualTo(Math.Sign(item2.CompareTo(item1)))); + }); } [Test] @@ -153,17 +167,23 @@ public void IntComparerViaBuilder() int t = 4; int u = 5; - Assert.AreEqual(0, h.Compare(s, t)); - Assert.IsTrue(h.Compare(s, u) < 0); - Assert.AreSame(h, SCG.Comparer.Default); + Assert.Multiple(() => + { + Assert.That(h.Compare(s, t), Is.EqualTo(0)); + Assert.That(h.Compare(s, u), Is.LessThan(0)); + Assert.That(SCG.Comparer.Default, Is.SameAs(h)); + }); } [Test] public void Nulls() { - Assert.IsTrue(SCG.Comparer.Default.Compare(null, "abe") < 0); - Assert.IsTrue(SCG.Comparer.Default.Compare(null, null) == 0); - Assert.IsTrue(SCG.Comparer.Default.Compare("abe", null) > 0); + Assert.Multiple(() => + { + Assert.That(SCG.Comparer.Default.Compare(null, "abe"), Is.LessThan(0)); + Assert.That(SCG.Comparer.Default.Compare(null, null), Is.EqualTo(0)); + Assert.That(SCG.Comparer.Default.Compare("abe", null), Is.GreaterThan(0)); + }); } } @@ -173,266 +193,317 @@ public class EqualityComparers [Test] public void ReftypeequalityComparer() { - SCG.IEqualityComparer h = C5.EqualityComparer.Default; + SCG.IEqualityComparer h = EqualityComparer.Default; string s = "bamse"; string t = "bamse"; string u = "bimse"; - Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s)); - Assert.IsTrue(h.Equals(s, t)); - Assert.IsFalse(h.Equals(s, u)); + Assert.Multiple(() => + { + Assert.That(h.GetHashCode(s), Is.EqualTo(s.GetHashCode())); + Assert.That(h.Equals(s, t), Is.True); + Assert.That(h.Equals(s, u), Is.False); + }); } [Test] public void ValuetypeequalityComparer() { - SCG.IEqualityComparer h = C5.EqualityComparer.Default; + SCG.IEqualityComparer h = EqualityComparer.Default; double s = 3.4; double t = 3.4; double u = 5.7; - Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s)); - Assert.IsTrue(h.Equals(s, t)); - Assert.IsFalse(h.Equals(s, u)); + Assert.Multiple(() => + { + Assert.That(h.GetHashCode(s), Is.EqualTo(s.GetHashCode())); + Assert.That(h.Equals(s, t), Is.True); + Assert.That(h.Equals(s, u), Is.False); + }); } [Test] public void ReftypeequalityComparerViaBuilder() { - SCG.IEqualityComparer h = C5.EqualityComparer.Default; + SCG.IEqualityComparer h = EqualityComparer.Default; string s = "bamse"; string t = "bamse"; string u = "bimse"; - Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s)); - Assert.IsTrue(h.Equals(s, t)); - Assert.IsFalse(h.Equals(s, u)); - Assert.AreSame(h, C5.EqualityComparer.Default); + Assert.Multiple(() => + { + Assert.That(h.GetHashCode(s), Is.EqualTo(s.GetHashCode())); + Assert.That(h.Equals(s, t), Is.True); + Assert.That(h.Equals(s, u), Is.False); + Assert.That(EqualityComparer.Default, Is.SameAs(h)); + }); } [Test] public void ValuetypeequalityComparerViaBuilder() { - SCG.IEqualityComparer h = C5.EqualityComparer.Default; + SCG.IEqualityComparer h = EqualityComparer.Default; double s = 3.4; double t = 3.4; double u = 5.7; - Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s)); - Assert.IsTrue(h.Equals(s, t)); - Assert.IsFalse(h.Equals(s, u)); - Assert.AreSame(h, C5.EqualityComparer.Default); + Assert.Multiple(() => + { + Assert.That(h.GetHashCode(s), Is.EqualTo(s.GetHashCode())); + Assert.That(h.Equals(s, t), Is.True); + Assert.That(h.Equals(s, u), Is.False); + Assert.That(EqualityComparer.Default, Is.SameAs(h)); + }); } [Test] public void CharequalityComparerViaBuilder() { - SCG.IEqualityComparer h = C5.EqualityComparer.Default; + SCG.IEqualityComparer h = EqualityComparer.Default; char s = '�'; char t = '�'; char u = 'r'; - Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s)); - Assert.IsTrue(h.Equals(s, t)); - Assert.IsFalse(h.Equals(s, u)); - Assert.AreSame(h, C5.EqualityComparer.Default); + Assert.Multiple(() => + { + Assert.That(h.GetHashCode(s), Is.EqualTo(s.GetHashCode())); + Assert.That(h.Equals(s, t), Is.True); + Assert.That(h.Equals(s, u), Is.False); + Assert.That(EqualityComparer.Default, Is.SameAs(h)); + }); } [Test] public void SbyteequalityComparerViaBuilder() { - SCG.IEqualityComparer h = C5.EqualityComparer.Default; + SCG.IEqualityComparer h = EqualityComparer.Default; sbyte s = 3; sbyte t = 3; sbyte u = -5; - Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s)); - Assert.IsTrue(h.Equals(s, t)); - Assert.IsFalse(h.Equals(s, u)); - Assert.AreSame(h, C5.EqualityComparer.Default); + Assert.Multiple(() => + { + Assert.That(h.GetHashCode(s), Is.EqualTo(s.GetHashCode())); + Assert.That(h.Equals(s, t), Is.True); + Assert.That(h.Equals(s, u), Is.False); + Assert.That(EqualityComparer.Default, Is.SameAs(h)); + }); } [Test] public void ByteequalityComparerViaBuilder() { - SCG.IEqualityComparer h = C5.EqualityComparer.Default; + SCG.IEqualityComparer h = EqualityComparer.Default; byte s = 3; byte t = 3; byte u = 5; - Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s)); - Assert.IsTrue(h.Equals(s, t)); - Assert.IsFalse(h.Equals(s, u)); - Assert.AreSame(h, C5.EqualityComparer.Default); + Assert.Multiple(() => + { + Assert.That(h.GetHashCode(s), Is.EqualTo(s.GetHashCode())); + Assert.That(h.Equals(s, t), Is.True); + Assert.That(h.Equals(s, u), Is.False); + Assert.That(EqualityComparer.Default, Is.SameAs(h)); + }); } [Test] public void ShortequalityComparerViaBuilder() { - SCG.IEqualityComparer h = C5.EqualityComparer.Default; + SCG.IEqualityComparer h = EqualityComparer.Default; short s = 3; short t = 3; short u = -5; - Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s)); - Assert.IsTrue(h.Equals(s, t)); - Assert.IsFalse(h.Equals(s, u)); - Assert.AreSame(h, C5.EqualityComparer.Default); + Assert.Multiple(() => + { + Assert.That(h.GetHashCode(s), Is.EqualTo(s.GetHashCode())); + Assert.That(h.Equals(s, t), Is.True); + Assert.That(h.Equals(s, u), Is.False); + Assert.That(EqualityComparer.Default, Is.SameAs(h)); + }); } [Test] public void UshortequalityComparerViaBuilder() { - SCG.IEqualityComparer h = C5.EqualityComparer.Default; + SCG.IEqualityComparer h = EqualityComparer.Default; ushort s = 3; ushort t = 3; ushort u = 60000; - Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s)); - Assert.IsTrue(h.Equals(s, t)); - Assert.IsFalse(h.Equals(s, u)); - Assert.AreSame(h, C5.EqualityComparer.Default); + Assert.Multiple(() => + { + Assert.That(h.GetHashCode(s), Is.EqualTo(s.GetHashCode())); + Assert.That(h.Equals(s, t), Is.True); + Assert.That(h.Equals(s, u), Is.False); + Assert.That(EqualityComparer.Default, Is.SameAs(h)); + }); } [Test] public void IntequalityComparerViaBuilder() { - SCG.IEqualityComparer h = C5.EqualityComparer.Default; + SCG.IEqualityComparer h = EqualityComparer.Default; int s = 3; int t = 3; int u = -5; - Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s)); - Assert.IsTrue(h.Equals(s, t)); - Assert.IsFalse(h.Equals(s, u)); - Assert.AreSame(h, C5.EqualityComparer.Default); + Assert.Multiple(() => + { + Assert.That(h.GetHashCode(s), Is.EqualTo(s.GetHashCode())); + Assert.That(h.Equals(s, t), Is.True); + Assert.That(h.Equals(s, u), Is.False); + Assert.That(EqualityComparer.Default, Is.SameAs(h)); + }); } [Test] public void UintequalityComparerViaBuilder() { - SCG.IEqualityComparer h = C5.EqualityComparer.Default; + SCG.IEqualityComparer h = EqualityComparer.Default; uint s = 3; uint t = 3; uint u = 3000000000; - Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s)); - Assert.IsTrue(h.Equals(s, t)); - Assert.IsFalse(h.Equals(s, u)); - Assert.AreSame(h, C5.EqualityComparer.Default); + Assert.Multiple(() => + { + Assert.That(h.GetHashCode(s), Is.EqualTo(s.GetHashCode())); + Assert.That(h.Equals(s, t), Is.True); + Assert.That(h.Equals(s, u), Is.False); + Assert.That(EqualityComparer.Default, Is.SameAs(h)); + }); } [Test] public void LongequalityComparerViaBuilder() { - SCG.IEqualityComparer h = C5.EqualityComparer.Default; + SCG.IEqualityComparer h = EqualityComparer.Default; long s = 3; long t = 3; long u = -500000000000000L; - Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s)); - Assert.IsTrue(h.Equals(s, t)); - Assert.IsFalse(h.Equals(s, u)); - Assert.AreSame(h, C5.EqualityComparer.Default); + Assert.Multiple(() => + { + Assert.That(h.GetHashCode(s), Is.EqualTo(s.GetHashCode())); + Assert.That(h.Equals(s, t), Is.True); + Assert.That(h.Equals(s, u), Is.False); + Assert.That(EqualityComparer.Default, Is.SameAs(h)); + }); } [Test] public void UlongequalityComparerViaBuilder() { - SCG.IEqualityComparer h = C5.EqualityComparer.Default; + SCG.IEqualityComparer h = EqualityComparer.Default; ulong s = 3; ulong t = 3; ulong u = 500000000000000UL; - Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s)); - Assert.IsTrue(h.Equals(s, t)); - Assert.IsFalse(h.Equals(s, u)); - Assert.AreSame(h, C5.EqualityComparer.Default); + Assert.Multiple(() => + { + Assert.That(h.GetHashCode(s), Is.EqualTo(s.GetHashCode())); + Assert.That(h.Equals(s, t), Is.True); + Assert.That(h.Equals(s, u), Is.False); + Assert.That(EqualityComparer.Default, Is.SameAs(h)); + }); } [Test] public void FloatequalityComparerViaBuilder() { - SCG.IEqualityComparer h = C5.EqualityComparer.Default; + SCG.IEqualityComparer h = EqualityComparer.Default; float s = 3.1F; float t = 3.1F; float u = -5.2F; - Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s)); - Assert.IsTrue(h.Equals(s, t)); - Assert.IsFalse(h.Equals(s, u)); - Assert.AreSame(h, C5.EqualityComparer.Default); + Assert.Multiple(() => + { + Assert.That(h.GetHashCode(s), Is.EqualTo(s.GetHashCode())); + Assert.That(h.Equals(s, t), Is.True); + Assert.That(h.Equals(s, u), Is.False); + Assert.That(EqualityComparer.Default, Is.SameAs(h)); + }); } [Test] public void DoubleequalityComparerViaBuilder() { - SCG.IEqualityComparer h = C5.EqualityComparer.Default; + SCG.IEqualityComparer h = EqualityComparer.Default; double s = 3.12345; double t = 3.12345; double u = -5.2; - Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s)); - Assert.IsTrue(h.Equals(s, t)); - Assert.IsFalse(h.Equals(s, u)); - Assert.AreSame(h, C5.EqualityComparer.Default); + Assert.Multiple(() => + { + Assert.That(h.GetHashCode(s), Is.EqualTo(s.GetHashCode())); + Assert.That(h.Equals(s, t), Is.True); + Assert.That(h.Equals(s, u), Is.False); + Assert.That(EqualityComparer.Default, Is.SameAs(h)); + }); } [Test] public void DecimalequalityComparerViaBuilder() { - SCG.IEqualityComparer h = C5.EqualityComparer.Default; + SCG.IEqualityComparer h = EqualityComparer.Default; decimal s = 3.0001M; decimal t = 3.0001M; decimal u = -500000000000000M; - Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s)); - Assert.IsTrue(h.Equals(s, t)); - Assert.IsFalse(h.Equals(s, u)); - Assert.AreSame(h, C5.EqualityComparer.Default); + Assert.Multiple(() => + { + Assert.That(h.GetHashCode(s), Is.EqualTo(s.GetHashCode())); + Assert.That(h.Equals(s, t), Is.True); + Assert.That(h.Equals(s, u), Is.False); + Assert.That(EqualityComparer.Default, Is.SameAs(h)); + }); } [Test] public void UnseqequalityComparerViaBuilder() { - SCG.IEqualityComparer> h = C5.EqualityComparer>.Default; + SCG.IEqualityComparer> h = EqualityComparer>.Default; C5.ICollection s = new LinkedList(); C5.ICollection t = new LinkedList(); C5.ICollection u = new LinkedList(); s.Add(1); s.Add(2); s.Add(3); t.Add(3); t.Add(2); t.Add(1); u.Add(3); u.Add(2); u.Add(4); - Assert.AreEqual(s.GetUnsequencedHashCode(), h.GetHashCode(s)); - Assert.IsTrue(h.Equals(s, t)); - Assert.IsFalse(h.Equals(s, u)); - Assert.AreSame(h, C5.EqualityComparer>.Default); + Assert.Multiple(() => + { + Assert.That(h.GetHashCode(s), Is.EqualTo(s.GetUnsequencedHashCode())); + Assert.That(h.Equals(s, t), Is.True); + Assert.That(h.Equals(s, u), Is.False); + Assert.That(EqualityComparer>.Default, Is.SameAs(h)); + }); } [Test] public void SeqequalityComparerViaBuilder2() { - SCG.IEqualityComparer> h = C5.EqualityComparer>.Default; - LinkedList s = new LinkedList() { 1, 2, 3 }; - Assert.AreEqual(CHC.SequencedHashCode(1, 2, 3), h.GetHashCode(s)); + SCG.IEqualityComparer> h = EqualityComparer>.Default; + LinkedList s = new() { 1, 2, 3 }; + Assert.That(h.GetHashCode(s), Is.EqualTo(CHC.SequencedHashCode(1, 2, 3))); } [Test] public void UnseqequalityComparerViaBuilder2() { - SCG.IEqualityComparer> h = C5.EqualityComparer>.Default; - C5.HashSet s = new C5.HashSet() { 1, 2, 3 }; - Assert.AreEqual(CHC.UnsequencedHashCode(1, 2, 3), h.GetHashCode(s)); + SCG.IEqualityComparer> h = EqualityComparer>.Default; + C5.HashSet s = new() { 1, 2, 3 }; + Assert.That(h.GetHashCode(s), Is.EqualTo(CHC.UnsequencedHashCode(1, 2, 3))); } //generic types implementing collection interfaces [Test] public void SeqequalityComparerViaBuilder3() { - SCG.IEqualityComparer> h = C5.EqualityComparer>.Default; + SCG.IEqualityComparer> h = EqualityComparer>.Default; C5.IList s = new LinkedList() { 1, 2, 3 }; - Assert.AreEqual(CHC.SequencedHashCode(1, 2, 3), h.GetHashCode(s)); + Assert.That(h.GetHashCode(s), Is.EqualTo(CHC.SequencedHashCode(1, 2, 3))); } private interface IFoo : C5.ICollection { void Bamse(); } @@ -446,9 +517,9 @@ public void Bamse() { } [Test] public void UnseqequalityComparerViaBuilder3() { - SCG.IEqualityComparer> h = C5.EqualityComparer>.Default; + SCG.IEqualityComparer> h = EqualityComparer>.Default; IFoo s = new Foo() { 1, 2, 3 }; - Assert.AreEqual(CHC.UnsequencedHashCode(1, 2, 3), h.GetHashCode(s)); + Assert.That(h.GetHashCode(s), Is.EqualTo(CHC.UnsequencedHashCode(1, 2, 3))); } //Nongeneric types implementing collection types: @@ -465,9 +536,9 @@ public void Bamse() { } [Test] public void SeqequalityComparerViaBuilder4() { - SCG.IEqualityComparer h = C5.EqualityComparer.Default; + SCG.IEqualityComparer h = EqualityComparer.Default; IBaz s = new Baz() { 1, 2, 3 }; - Assert.AreEqual(CHC.SequencedHashCode(1, 2, 3), h.GetHashCode(s)); + Assert.That(h.GetHashCode(s), Is.EqualTo(CHC.SequencedHashCode(1, 2, 3))); } private interface IBar : C5.ICollection @@ -507,30 +578,33 @@ void IExtensible.AddAll(SCG.IEnumerable enumerable) [Test] public void UnseqequalityComparerViaBuilder4() { - SCG.IEqualityComparer h = C5.EqualityComparer.Default; + SCG.IEqualityComparer h = EqualityComparer.Default; IBar s = new Bar() { 1, 2, 3 }; - Assert.AreEqual(CHC.UnsequencedHashCode(1, 2, 3), h.GetHashCode(s)); + Assert.That(h.GetHashCode(s), Is.EqualTo(CHC.UnsequencedHashCode(1, 2, 3))); } [Test] public void StaticEqualityComparerWithNull() { - ArrayList arr = new ArrayList(); - SCG.IEqualityComparer eqc = C5.EqualityComparer.Default; - Assert.IsTrue(CollectionBase.StaticEquals(arr, arr, eqc)); - Assert.IsTrue(CollectionBase.StaticEquals(null, null, eqc)); - Assert.IsFalse(CollectionBase.StaticEquals(arr, null, eqc)); - Assert.IsFalse(CollectionBase.StaticEquals(null, arr, eqc)); + ArrayList arr = new(); + SCG.IEqualityComparer eqc = EqualityComparer.Default; + Assert.Multiple(() => + { + Assert.That(CollectionBase.StaticEquals(arr, arr, eqc), Is.True); + Assert.That(CollectionBase.StaticEquals(null, null, eqc), Is.True); + Assert.That(CollectionBase.StaticEquals(arr, null, eqc), Is.False); + Assert.That(CollectionBase.StaticEquals(null, arr, eqc), Is.False); + }); } - private class EveryThingIsEqual : SCG.IEqualityComparer + private class EveryThingIsEqual : SCG.IEqualityComparer { - public new bool Equals(Object o1, Object o2) + public new bool Equals(object o1, object o2) { return true; } - public int GetHashCode(Object o) + public int GetHashCode(object o) { return 1; } @@ -540,14 +614,17 @@ public int GetHashCode(Object o) public void UnsequencedCollectionComparerEquality() { // Repro for bug20101103 - SCG.IEqualityComparer eqc = new EveryThingIsEqual(); - Object o1 = new Object(), o2 = new Object(); - C5.ICollection coll1 = new ArrayList(eqc); - C5.ICollection coll2 = new ArrayList(eqc); + SCG.IEqualityComparer eqc = new EveryThingIsEqual(); + object o1 = new(), o2 = new(); + C5.ICollection coll1 = new ArrayList(eqc); + C5.ICollection coll2 = new ArrayList(eqc); coll1.Add(o1); coll2.Add(o2); - Assert.IsFalse(o1.Equals(o2)); - Assert.IsTrue(coll1.UnsequencedEquals(coll2)); + Assert.Multiple(() => + { + Assert.That(o1.Equals(o2), Is.False); + Assert.That(coll1.UnsequencedEquals(coll2), Is.True); + }); } } } diff --git a/C5.Tests/C5.Tests.csproj b/C5.Tests/C5.Tests.csproj index c9b2ef77..ed656284 100644 --- a/C5.Tests/C5.Tests.csproj +++ b/C5.Tests/C5.Tests.csproj @@ -12,7 +12,11 @@ all - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/C5.Tests/Hashing/HashBagTests.cs b/C5.Tests/Hashing/HashBagTests.cs index 6358a979..f2f0cc68 100644 --- a/C5.Tests/Hashing/HashBagTests.cs +++ b/C5.Tests/Hashing/HashBagTests.cs @@ -5,23 +5,21 @@ using System; namespace C5.Tests.hashtable.bag { - using CollectionOfInt = HashBag; - [TestFixture] public class GenericTesters { [Test] public void TestEvents() { - CollectionOfInt factory() { return new CollectionOfInt(TenEqualityComparer.Default); } - new C5.Tests.Templates.Events.CollectionTester().Test(factory); + HashBag factory() { return new HashBag(TenEqualityComparer.Default); } + new C5.Tests.Templates.Events.CollectionTester>().Test(factory); } //[Test] //public void Extensible() //{ - // C5.Tests.Templates.Extensible.Clone.Tester(); - // C5.Tests.Templates.Extensible.Serialization.Tester(); + // C5.Tests.Templates.Extensible.Clone.Tester>(); + // C5.Tests.Templates.Extensible.Serialization.Tester>(); //} } @@ -51,12 +49,15 @@ public void Dispose() [Test] public void Format() { - Assert.AreEqual("{{ }}", coll.ToString()); - coll.AddAll(new int[] { -4, 28, 129, 65530, -4, 28 }); - Assert.AreEqual("{{ 65530(*1), -4(*2), 28(*2), 129(*1) }}", coll.ToString()); - Assert.AreEqual("{{ FFFA(*1), -4(*2), 1C(*2), 81(*1) }}", coll.ToString(null, rad16)); - Assert.AreEqual("{{ 65530(*1), -4(*2)... }}", coll.ToString("L18", null)); - Assert.AreEqual("{{ FFFA(*1), -4(*2)... }}", coll.ToString("L18", rad16)); + Assert.That(coll.ToString(), Is.EqualTo("{{ }}")); + coll.AddAll([-4, 28, 129, 65530, -4, 28]); + Assert.Multiple(() => + { + Assert.That(coll.ToString(), Is.EqualTo("{{ 65530(*1), -4(*2), 28(*2), 129(*1) }}")); + Assert.That(coll.ToString(null, rad16), Is.EqualTo("{{ FFFA(*1), -4(*2), 1C(*2), 81(*1) }}")); + Assert.That(coll.ToString("L18", null), Is.EqualTo("{{ 65530(*1), -4(*2)... }}")); + Assert.That(coll.ToString("L18", rad16), Is.EqualTo("{{ FFFA(*1), -4(*2)... }}")); + }); } } @@ -84,47 +85,59 @@ public void Init() [Test] public void Find() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + System.Collections.Generic.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Find(ref p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); + Assert.Multiple(() => + { + Assert.That(lst.Find(ref p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Find(ref p)); + Assert.That(lst.Find(ref p), Is.False); } [Test] public void FindOrAdd() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); - System.Collections.Generic.KeyValuePair q = new System.Collections.Generic.KeyValuePair(); + System.Collections.Generic.KeyValuePair p = new(3, 78); + System.Collections.Generic.KeyValuePair q = new(); - Assert.IsTrue(lst.FindOrAdd(ref p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); + Assert.Multiple(() => + { + Assert.That(lst.FindOrAdd(ref p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); p = new System.Collections.Generic.KeyValuePair(13, 79); - Assert.IsFalse(lst.FindOrAdd(ref p)); + Assert.That(lst.FindOrAdd(ref p), Is.False); q = new System.Collections.Generic.KeyValuePair(13, q.Value); - Assert.IsTrue(lst.Find(ref q)); - Assert.AreEqual(13, q.Key); - Assert.AreEqual(79, q.Value); + Assert.Multiple(() => + { + Assert.That(lst.Find(ref q), Is.True); + Assert.That(q.Key, Is.EqualTo(13)); + Assert.That(q.Value, Is.EqualTo(79)); + }); } [Test] public void Update() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); - System.Collections.Generic.KeyValuePair q = new System.Collections.Generic.KeyValuePair(); + System.Collections.Generic.KeyValuePair p = new(3, 78); + System.Collections.Generic.KeyValuePair q = new(); - Assert.IsTrue(lst.Update(p)); + Assert.That(lst.Update(p), Is.True); q = new System.Collections.Generic.KeyValuePair(3, q.Value); - Assert.IsTrue(lst.Find(ref q)); - Assert.AreEqual(3, q.Key); - Assert.AreEqual(78, q.Value); + Assert.Multiple(() => + { + Assert.That(lst.Find(ref q), Is.True); + Assert.That(q.Key, Is.EqualTo(3)); + Assert.That(q.Value, Is.EqualTo(78)); + }); p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Update(p)); + Assert.That(lst.Update(p), Is.False); } @@ -134,43 +147,55 @@ public void UpdateOrAdd1() var p = new System.Collections.Generic.KeyValuePair(3, 78); var q = new System.Collections.Generic.KeyValuePair(); - Assert.IsTrue(lst.UpdateOrAdd(p)); + Assert.That(lst.UpdateOrAdd(p), Is.True); q = new System.Collections.Generic.KeyValuePair(3, q.Value); - Assert.IsTrue(lst.Find(ref q)); - Assert.AreEqual(3, q.Key); - Assert.AreEqual(78, q.Value); + Assert.Multiple(() => + { + Assert.That(lst.Find(ref q), Is.True); + Assert.That(q.Key, Is.EqualTo(3)); + Assert.That(q.Value, Is.EqualTo(78)); + }); p = new System.Collections.Generic.KeyValuePair(13, 79); - Assert.IsFalse(lst.UpdateOrAdd(p)); + Assert.That(lst.UpdateOrAdd(p), Is.False); q = new System.Collections.Generic.KeyValuePair(13, q.Value); - Assert.IsTrue(lst.Find(ref q)); - Assert.AreEqual(13, q.Key); - Assert.AreEqual(79, q.Value); + Assert.Multiple(() => + { + Assert.That(lst.Find(ref q), Is.True); + Assert.That(q.Key, Is.EqualTo(13)); + Assert.That(q.Value, Is.EqualTo(79)); + }); } [Test] public void UpdateOrAdd2() { - ICollection coll = new HashBag(); + ICollection coll = new HashBag(); // s1 and s2 are distinct objects but contain the same text: - String s1 = "abc", s2 = ("def" + s1).Substring(3); - Assert.IsFalse(coll.UpdateOrAdd(s1, out string old)); - Assert.AreEqual(null, old); - Assert.IsTrue(coll.UpdateOrAdd(s2, out old)); - Assert.IsTrue(Object.ReferenceEquals(s1, old)); - Assert.IsFalse(Object.ReferenceEquals(s2, old)); + string s1 = "abc", s2 = ("def" + s1).Substring(3); + Assert.Multiple(() => + { + Assert.That(coll.UpdateOrAdd(s1, out string old), Is.False); + Assert.That(old, Is.EqualTo(null)); + Assert.That(coll.UpdateOrAdd(s2, out old), Is.True); + Assert.That(ReferenceEquals(s1, old), Is.True); + Assert.That(ReferenceEquals(s2, old), Is.False); + }); } [Test] public void RemoveWithReturn() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); - //System.Collections.Generic.KeyValuePair q = new System.Collections.Generic.KeyValuePair(); + System.Collections.Generic.KeyValuePair p = new(3, 78); + Assert.Multiple(() => + { + //System.Collections.Generic.KeyValuePair q = new System.Collections.Generic.KeyValuePair(); - Assert.IsTrue(lst.Remove(p, out p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); + Assert.That(lst.Remove(p, out p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Remove(p, out _)); + Assert.That(lst.Remove(p, out _), Is.False); } } @@ -211,7 +236,7 @@ public void NullEqualityComparerinConstructor3() public void Choose() { hashbag.Add(7); - Assert.AreEqual(7, hashbag.Choose()); + Assert.That(hashbag.Choose(), Is.EqualTo(7)); } [Test] @@ -223,24 +248,39 @@ public void BadChoose() [Test] public void CountEtAl() { - Assert.IsFalse(hashbag.IsReadOnly); - // Assert.IsFalse(hashbag.SyncRoot == null); - Assert.AreEqual(0, hashbag.Count); - Assert.IsTrue(hashbag.IsEmpty); - Assert.IsTrue(hashbag.AllowsDuplicates); - Assert.IsTrue(hashbag.Add(0)); - Assert.AreEqual(1, hashbag.Count); - Assert.IsFalse(hashbag.IsEmpty); - Assert.IsTrue(hashbag.Add(5)); - Assert.AreEqual(2, hashbag.Count); - Assert.IsTrue(hashbag.Add(5)); - Assert.AreEqual(3, hashbag.Count); - Assert.IsFalse(hashbag.IsEmpty); - Assert.IsTrue(hashbag.Add(8)); - Assert.AreEqual(4, hashbag.Count); - Assert.AreEqual(2, hashbag.ContainsCount(5)); - Assert.AreEqual(1, hashbag.ContainsCount(8)); - Assert.AreEqual(1, hashbag.ContainsCount(0)); + Assert.Multiple(() => + { + Assert.That(hashbag.IsReadOnly, Is.False); + // Assert.IsFalse(hashbag.SyncRoot == null); + Assert.That(hashbag, Is.Empty); + }); + Assert.Multiple(() => + { + Assert.That(hashbag.IsEmpty, Is.True); + Assert.That(hashbag.AllowsDuplicates, Is.True); + Assert.That(hashbag.Add(0), Is.True); + Assert.That(hashbag, Has.Count.EqualTo(1)); + }); + Assert.Multiple(() => + { + Assert.That(hashbag.IsEmpty, Is.False); + Assert.That(hashbag.Add(5), Is.True); + Assert.That(hashbag, Has.Count.EqualTo(2)); + }); + Assert.That(hashbag.Add(5), Is.True); + Assert.That(hashbag, Has.Count.EqualTo(3)); + Assert.Multiple(() => + { + Assert.That(hashbag.IsEmpty, Is.False); + Assert.That(hashbag.Add(8), Is.True); + Assert.That(hashbag, Has.Count.EqualTo(4)); + }); + Assert.Multiple(() => + { + Assert.That(hashbag.ContainsCount(5), Is.EqualTo(2)); + Assert.That(hashbag.ContainsCount(8), Is.EqualTo(1)); + Assert.That(hashbag.ContainsCount(0), Is.EqualTo(1)); + }); } @@ -249,32 +289,41 @@ public void AddAll() { hashbag.Add(3); hashbag.Add(4); hashbag.Add(4); hashbag.Add(5); hashbag.Add(4); - HashBag hashbag2 = new HashBag(); + HashBag hashbag2 = new(); hashbag2.AddAll(hashbag); - Assert.IsTrue(IC.SetEq(hashbag2, 3, 4, 4, 4, 5)); + Assert.That(IC.SetEq(hashbag2, 3, 4, 4, 4, 5), Is.True); hashbag.Add(9); hashbag.AddAll(hashbag2); - Assert.IsTrue(IC.SetEq(hashbag2, 3, 4, 4, 4, 5)); - Assert.IsTrue(IC.SetEq(hashbag, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 9)); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(hashbag2, 3, 4, 4, 4, 5), Is.True); + Assert.That(IC.SetEq(hashbag, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 9), Is.True); + }); } [Test] public void ContainsCount() { - Assert.AreEqual(0, hashbag.ContainsCount(5)); + Assert.That(hashbag.ContainsCount(5), Is.EqualTo(0)); hashbag.Add(5); - Assert.AreEqual(1, hashbag.ContainsCount(5)); - Assert.AreEqual(0, hashbag.ContainsCount(7)); + Assert.Multiple(() => + { + Assert.That(hashbag.ContainsCount(5), Is.EqualTo(1)); + Assert.That(hashbag.ContainsCount(7), Is.EqualTo(0)); + }); hashbag.Add(8); - Assert.AreEqual(1, hashbag.ContainsCount(5)); - Assert.AreEqual(0, hashbag.ContainsCount(7)); - Assert.AreEqual(1, hashbag.ContainsCount(8)); + Assert.Multiple(() => + { + Assert.That(hashbag.ContainsCount(5), Is.EqualTo(1)); + Assert.That(hashbag.ContainsCount(7), Is.EqualTo(0)); + Assert.That(hashbag.ContainsCount(8), Is.EqualTo(1)); + }); hashbag.Add(5); - Assert.AreEqual(2, hashbag.ContainsCount(5)); - Assert.AreEqual(0, hashbag.ContainsCount(7)); - Assert.AreEqual(1, hashbag.ContainsCount(8)); + Assert.That(hashbag.ContainsCount(5), Is.EqualTo(2)); + Assert.That(hashbag.ContainsCount(7), Is.EqualTo(0)); + Assert.That(hashbag.ContainsCount(8), Is.EqualTo(1)); } @@ -282,75 +331,78 @@ public void ContainsCount() public void RemoveAllCopies() { hashbag.Add(5); hashbag.Add(7); hashbag.Add(5); - Assert.AreEqual(2, hashbag.ContainsCount(5)); - Assert.AreEqual(1, hashbag.ContainsCount(7)); + Assert.Multiple(() => + { + Assert.That(hashbag.ContainsCount(5), Is.EqualTo(2)); + Assert.That(hashbag.ContainsCount(7), Is.EqualTo(1)); + }); hashbag.RemoveAllCopies(5); - Assert.AreEqual(0, hashbag.ContainsCount(5)); - Assert.AreEqual(1, hashbag.ContainsCount(7)); + Assert.That(hashbag.ContainsCount(5), Is.EqualTo(0)); + Assert.That(hashbag.ContainsCount(7), Is.EqualTo(1)); hashbag.Add(5); hashbag.Add(8); hashbag.Add(5); hashbag.RemoveAllCopies(8); - Assert.IsTrue(IC.Eq(hashbag, 7, 5, 5)); + Assert.That(IC.Eq(hashbag, 7, 5, 5), Is.True); } [Test] public void ContainsAll() { - HashBag list2 = new HashBag(); + HashBag list2 = new(); - Assert.IsTrue(hashbag.ContainsAll(list2)); + Assert.That(hashbag.ContainsAll(list2), Is.True); list2.Add(4); - Assert.IsFalse(hashbag.ContainsAll(list2)); + Assert.That(hashbag.ContainsAll(list2), Is.False); hashbag.Add(4); - Assert.IsTrue(hashbag.ContainsAll(list2)); + Assert.That(hashbag.ContainsAll(list2), Is.True); hashbag.Add(5); - Assert.IsTrue(hashbag.ContainsAll(list2)); + Assert.That(hashbag.ContainsAll(list2), Is.True); list2.Add(20); - Assert.IsFalse(hashbag.ContainsAll(list2)); + Assert.That(hashbag.ContainsAll(list2), Is.False); hashbag.Add(20); - Assert.IsTrue(hashbag.ContainsAll(list2)); + Assert.That(hashbag.ContainsAll(list2), Is.True); list2.Add(4); - Assert.IsFalse(hashbag.ContainsAll(list2)); + Assert.That(hashbag.ContainsAll(list2), Is.False); hashbag.Add(4); - Assert.IsTrue(hashbag.ContainsAll(list2)); + Assert.That(hashbag.ContainsAll(list2), Is.True); } [Test] public void RetainAll() { - HashBag list2 = new HashBag(); + HashBag list2 = new(); hashbag.Add(4); hashbag.Add(5); hashbag.Add(4); hashbag.Add(6); hashbag.Add(4); list2.Add(5); list2.Add(4); list2.Add(7); list2.Add(4); hashbag.RetainAll(list2); - Assert.IsTrue(IC.SetEq(hashbag, 4, 4, 5)); + Assert.That(IC.SetEq(hashbag, 4, 4, 5), Is.True); hashbag.Add(6); list2.Clear(); list2.Add(7); list2.Add(8); list2.Add(9); hashbag.RetainAll(list2); - Assert.IsTrue(IC.Eq(hashbag)); + Assert.That(IC.Eq(hashbag), Is.True); } [Test] public void RemoveAll() { - HashBag list2 = new HashBag(); + HashBag list2 = new(); hashbag.Add(4); hashbag.Add(5); hashbag.Add(6); hashbag.Add(4); hashbag.Add(5); list2.Add(5); list2.Add(4); list2.Add(7); list2.Add(4); hashbag.RemoveAll(list2); - Assert.IsTrue(IC.SetEq(hashbag, 5, 6)); + Assert.That(IC.SetEq(hashbag, 5, 6), Is.True); hashbag.Add(5); hashbag.Add(4); list2.Clear(); list2.Add(6); list2.Add(5); hashbag.RemoveAll(list2); - Assert.IsTrue(IC.SetEq(hashbag, 4, 5)); + Assert.That(IC.SetEq(hashbag, 4, 5), Is.True); list2.Clear(); list2.Add(7); list2.Add(8); list2.Add(9); hashbag.RemoveAll(list2); - Assert.IsTrue(IC.SetEq(hashbag, 4, 5)); + Assert.That(IC.SetEq(hashbag, 4, 5), Is.True); } @@ -358,22 +410,28 @@ public void RemoveAll() public void Remove() { hashbag.Add(4); hashbag.Add(4); hashbag.Add(5); hashbag.Add(4); hashbag.Add(6); - Assert.IsFalse(hashbag.Remove(2)); - Assert.IsTrue(hashbag.Remove(4)); - Assert.IsTrue(IC.SetEq(hashbag, 4, 4, 5, 6)); + Assert.Multiple(() => + { + Assert.That(hashbag.Remove(2), Is.False); + Assert.That(hashbag.Remove(4), Is.True); + Assert.That(IC.SetEq(hashbag, 4, 4, 5, 6), Is.True); + }); hashbag.Add(7); hashbag.Add(21); hashbag.Add(37); hashbag.Add(53); hashbag.Add(69); hashbag.Add(53); hashbag.Add(85); - Assert.IsTrue(hashbag.Remove(5)); - Assert.IsTrue(IC.SetEq(hashbag, 4, 4, 6, 7, 21, 37, 53, 53, 69, 85)); - Assert.IsFalse(hashbag.Remove(165)); - Assert.IsTrue(hashbag.Check()); - Assert.IsTrue(IC.SetEq(hashbag, 4, 4, 6, 7, 21, 37, 53, 53, 69, 85)); - Assert.IsTrue(hashbag.Remove(53)); - Assert.IsTrue(IC.SetEq(hashbag, 4, 4, 6, 7, 21, 37, 53, 69, 85)); - Assert.IsTrue(hashbag.Remove(37)); - Assert.IsTrue(IC.SetEq(hashbag, 4, 4, 6, 7, 21, 53, 69, 85)); - Assert.IsTrue(hashbag.Remove(85)); - Assert.IsTrue(IC.SetEq(hashbag, 4, 4, 6, 7, 21, 53, 69)); + Assert.Multiple(() => + { + Assert.That(hashbag.Remove(5), Is.True); + Assert.That(IC.SetEq(hashbag, 4, 4, 6, 7, 21, 37, 53, 53, 69, 85), Is.True); + Assert.That(hashbag.Remove(165), Is.False); + Assert.That(hashbag.Check(), Is.True); + }); + Assert.That(IC.SetEq(hashbag, 4, 4, 6, 7, 21, 37, 53, 53, 69, 85), Is.True); + Assert.That(hashbag.Remove(53), Is.True); + Assert.That(IC.SetEq(hashbag, 4, 4, 6, 7, 21, 37, 53, 69, 85), Is.True); + Assert.That(hashbag.Remove(37), Is.True); + Assert.That(IC.SetEq(hashbag, 4, 4, 6, 7, 21, 53, 69, 85), Is.True); + Assert.That(hashbag.Remove(85), Is.True); + Assert.That(IC.SetEq(hashbag, 4, 4, 6, 7, 21, 53, 69), Is.True); } @@ -409,12 +467,15 @@ public void Dispose() [Test] public void Find() { - Assert.IsFalse(list.Find(pred, out int i)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(list.Find(pred, out i)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.IsTrue(list.Find(pred, out i)); - Assert.AreEqual(45, i); + Assert.That(list.Find(pred, out int i), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(list.Find(pred, out i), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.Multiple(() => + { + Assert.That(list.Find(pred, out i), Is.True); + Assert.That(i, Is.EqualTo(45)); + }); } } @@ -433,11 +494,17 @@ public class UniqueItems [Test] public void Test() { - Assert.IsTrue(IC.SetEq(list.UniqueItems())); - Assert.IsTrue(IC.SetEq(list.ItemMultiplicities())); - list.AddAll(new int[] { 7, 9, 7 }); - Assert.IsTrue(IC.SetEq(list.UniqueItems(), 7, 9)); - Assert.IsTrue(IC.SetEq(list.ItemMultiplicities(), 7, 2, 9, 1)); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(list.UniqueItems()), Is.True); + Assert.That(IC.SetEq(list.ItemMultiplicities()), Is.True); + }); + list.AddAll([7, 9, 7]); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(list.UniqueItems(), 7, 9), Is.True); + Assert.That(IC.SetEq(list.ItemMultiplicities(), 7, 2, 9, 1), Is.True); + }); } } @@ -491,7 +558,7 @@ private string aeq(int[] a, params int[] b) [Test] public void ToArray() { - Assert.AreEqual("Alles klar", aeq(hashbag.ToArray())); + Assert.That(aeq(hashbag.ToArray()), Is.EqualTo("Alles klar")); hashbag.Add(7); hashbag.Add(3); hashbag.Add(10); @@ -500,7 +567,7 @@ public void ToArray() int[] r = hashbag.ToArray(); Array.Sort(r); - Assert.AreEqual("Alles klar", aeq(r, 3, 3, 7, 10)); + Assert.That(aeq(r, 3, 3, 7, 10), Is.EqualTo("Alles klar")); } @@ -509,21 +576,21 @@ public void CopyTo() { //Note: for small ints the itemequalityComparer is the identity! hashbag.CopyTo(a, 1); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009), Is.EqualTo("Alles klar")); hashbag.Add(6); hashbag.CopyTo(a, 2); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009), Is.EqualTo("Alles klar")); hashbag.Add(4); hashbag.Add(6); hashbag.Add(9); hashbag.CopyTo(a, 4); //TODO: make independent of interequalityComparer - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 6, 9, 4, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 6, 6, 9, 4, 1008, 1009), Is.EqualTo("Alles klar")); hashbag.Clear(); hashbag.Add(7); hashbag.CopyTo(a, 9); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 6, 9, 4, 1008, 7)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 6, 6, 9, 4, 1008, 7), Is.EqualTo("Alles klar")); } @@ -554,7 +621,8 @@ public void CopyToTooFar() [TestFixture] public class HashingEquals { - private ICollection h1, h2; + private HashBag h1; + private LinkedList h2; [SetUp] @@ -564,31 +632,29 @@ public void Init() h2 = new LinkedList(); } - [TearDown] public void Dispose() { - h1 = h2 = null; + h1 = null; + h2.Dispose(); } - [Test] public void Hashing() { - Assert.AreEqual(h1.GetUnsequencedHashCode(), h2.GetUnsequencedHashCode()); + Assert.That(h2.GetUnsequencedHashCode(), Is.EqualTo(h1.GetUnsequencedHashCode())); h1.Add(7); h2.Add(9); - Assert.IsTrue(h1.GetUnsequencedHashCode() != h2.GetUnsequencedHashCode()); + Assert.That(h1.GetUnsequencedHashCode() != h2.GetUnsequencedHashCode(), Is.True); h2.Add(7); h1.Add(9); - Assert.IsTrue(h1.GetUnsequencedHashCode() == h2.GetUnsequencedHashCode()); + Assert.That(h1.GetUnsequencedHashCode(), Is.EqualTo(h2.GetUnsequencedHashCode())); } - [Test] public void Equals() { - Assert.IsTrue(h1.UnsequencedEquals(h2)); + Assert.That(h1.UnsequencedEquals(h2), Is.True); // Code 1550734257, Pair (3 x 1602896434, 2 x 1186320090) number 169185 matched oth //er pair (3 x -1615223932, 2 x 1019546595) h1.Add(1602896434); @@ -601,16 +667,19 @@ public void Equals() h2.Add(-1615223932); h2.Add(1019546595); h2.Add(-1615223932); - Assert.IsTrue(h1.GetUnsequencedHashCode() == h2.GetUnsequencedHashCode()); - Assert.IsTrue(!h1.UnsequencedEquals(h2)); + Assert.Multiple(() => + { + Assert.That(h1.GetUnsequencedHashCode(), Is.EqualTo(h2.GetUnsequencedHashCode())); + Assert.That(!h1.UnsequencedEquals(h2), Is.True); + }); h1.Clear(); h2.Clear(); h1.Add(1); h1.Add(2); h2.Add(2); h2.Add(1); - Assert.IsTrue(h1.GetUnsequencedHashCode() == h2.GetUnsequencedHashCode()); - Assert.IsTrue(h1.UnsequencedEquals(h2)); + Assert.That(h1.GetUnsequencedHashCode(), Is.EqualTo(h2.GetUnsequencedHashCode())); + Assert.That(h1.UnsequencedEquals(h2), Is.True); } } } diff --git a/C5.Tests/Hashing/HashDictionaryTests.cs b/C5.Tests/Hashing/HashDictionaryTests.cs index cc0e2db3..f7cc833d 100644 --- a/C5.Tests/Hashing/HashDictionaryTests.cs +++ b/C5.Tests/Hashing/HashDictionaryTests.cs @@ -47,12 +47,15 @@ public void Dispose() [Test] public void Format() { - Assert.AreEqual("{ }", coll.ToString()); + Assert.That(coll.ToString(), Is.EqualTo("{ }")); coll.Add(23, 67); coll.Add(45, 89); - Assert.AreEqual("{ [45, 89], [23, 67] }", coll.ToString()); - Assert.AreEqual("{ [2D, 59], [17, 43] }", coll.ToString(null, rad16)); - Assert.AreEqual("{ [45, 89], ... }", coll.ToString("L14", null)); - Assert.AreEqual("{ [2D, 59], ... }", coll.ToString("L14", rad16)); + Assert.Multiple(() => + { + Assert.That(coll.ToString(), Is.EqualTo("{ [45, 89], [23, 67] }")); + Assert.That(coll.ToString(null, rad16), Is.EqualTo("{ [2D, 59], [17, 43] }")); + Assert.That(coll.ToString("L14", null), Is.EqualTo("{ [45, 89], ... }")); + Assert.That(coll.ToString("L14", rad16), Is.EqualTo("{ [2D, 59], ... }")); + }); } } @@ -85,7 +88,7 @@ public void NullEqualityComparerinConstructor2() public void Choose() { dict.Add("ER", "FOO"); - Assert.AreEqual(new System.Collections.Generic.KeyValuePair("ER", "FOO"), dict.Choose()); + Assert.That(dict.Choose(), Is.EqualTo(new System.Collections.Generic.KeyValuePair("ER", "FOO"))); } [Test] @@ -108,23 +111,35 @@ public void Initial() { bool res; - Assert.IsFalse(dict.IsReadOnly); - Assert.AreEqual(0, dict.Count, "new dict should be empty"); + Assert.Multiple(() => + { + Assert.That(dict.IsReadOnly, Is.False); + Assert.That(dict, Is.Empty, "new dict should be empty"); + }); dict.Add("A", "B"); - Assert.AreEqual(1, dict.Count, "bad count"); - Assert.AreEqual("B", dict["A"], "Wrong value for dict[A]"); + Assert.That(dict, Has.Count.EqualTo(1), "bad count"); + Assert.That(dict["A"], Is.EqualTo("B"), "Wrong value for dict[A]"); dict.Add("C", "D"); - Assert.AreEqual(2, dict.Count, "bad count"); - Assert.AreEqual("B", dict["A"], "Wrong value"); - Assert.AreEqual("D", dict["C"], "Wrong value"); + Assert.That(dict, Has.Count.EqualTo(2), "bad count"); + Assert.Multiple(() => + { + Assert.That(dict["A"], Is.EqualTo("B"), "Wrong value"); + Assert.That(dict["C"], Is.EqualTo("D"), "Wrong value"); + }); res = dict.Remove("A"); - Assert.IsTrue(res, "bad return value from Remove(A)"); - Assert.AreEqual(1, dict.Count, "bad count"); - Assert.AreEqual("D", dict["C"], "Wrong value of dict[C]"); + Assert.Multiple(() => + { + Assert.That(res, Is.True, "bad return value from Remove(A)"); + Assert.That(dict, Has.Count.EqualTo(1), "bad count"); + }); + Assert.That(dict["C"], Is.EqualTo("D"), "Wrong value of dict[C]"); res = dict.Remove("Z"); - Assert.IsFalse(res, "bad return value from Remove(Z)"); - Assert.AreEqual(1, dict.Count, "bad count"); - Assert.AreEqual("D", dict["C"], "Wrong value of dict[C] (2)"); + Assert.Multiple(() => + { + Assert.That(res, Is.False, "bad return value from Remove(Z)"); + Assert.That(dict, Has.Count.EqualTo(1), "bad count"); + }); + Assert.That(dict["C"], Is.EqualTo("D"), "Wrong value of dict[C] (2)"); } @@ -132,8 +147,11 @@ public void Initial() public void Contains() { dict.Add("C", "D"); - Assert.IsTrue(dict.Contains("C")); - Assert.IsFalse(dict.Contains("D")); + Assert.Multiple(() => + { + Assert.That(dict.Contains("C"), Is.True); + Assert.That(dict.Contains("D"), Is.False); + }); } @@ -143,7 +161,7 @@ public void IllegalAdd() dict.Add("A", "B"); var exception = Assert.Throws(() => dict.Add("A", "B")); - Assert.AreEqual("Key being added: 'A'", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Key being added: 'A'")); } @@ -158,12 +176,15 @@ public void GettingNonExisting() public void Setter() { dict["R"] = "UYGUY"; - Assert.AreEqual("UYGUY", dict["R"]); + Assert.That(dict["R"], Is.EqualTo("UYGUY")); dict["R"] = "UIII"; - Assert.AreEqual("UIII", dict["R"]); + Assert.That(dict["R"], Is.EqualTo("UIII")); dict["S"] = "VVV"; - Assert.AreEqual("UIII", dict["R"]); - Assert.AreEqual("VVV", dict["S"]); + Assert.Multiple(() => + { + Assert.That(dict["R"], Is.EqualTo("UIII")); + Assert.That(dict["S"], Is.EqualTo("VVV")); + }); //dict.dump(); } @@ -174,47 +195,64 @@ public void CombinedOps() dict["S"] = "VVV"; dict["T"] = "XYZ"; - - Assert.IsTrue(dict.Remove("S", out string s)); - Assert.AreEqual("VVV", s); - Assert.IsFalse(dict.Contains("S")); - Assert.IsFalse(dict.Remove("A", out _)); + Assert.That(dict.Remove("S", out string s), Is.True); + Assert.That(s, Is.EqualTo("VVV")); + Assert.That(dict.Contains("S"), Is.False); + Assert.That(dict.Remove("A", out _), Is.False); // string t = "T", a = "A"; - Assert.IsTrue(dict.Find(ref t, out s)); - Assert.AreEqual("XYZ", s); - Assert.IsFalse(dict.Find(ref a, out _)); + Assert.Multiple(() => + { + Assert.That(dict.Find(ref t, out s), Is.True); + Assert.That(s, Is.EqualTo("XYZ")); + Assert.That(dict.Find(ref a, out _), Is.False); - // - Assert.IsTrue(dict.Update("R", "UHU")); - Assert.AreEqual("UHU", dict["R"]); - Assert.IsFalse(dict.Update("A", "W")); - Assert.IsFalse(dict.Contains("A")); + // + Assert.That(dict.Update("R", "UHU"), Is.True); + Assert.That(dict["R"], Is.EqualTo("UHU")); + Assert.That(dict.Update("A", "W"), Is.False); + Assert.That(dict.Contains("A"), Is.False); + }); // s = "KKK"; - Assert.IsFalse(dict.FindOrAdd("B", ref s)); - Assert.AreEqual("KKK", dict["B"]); - Assert.IsTrue(dict.FindOrAdd("T", ref s)); - Assert.AreEqual("XYZ", s); + Assert.Multiple(() => + { + Assert.That(dict.FindOrAdd("B", ref s), Is.False); + Assert.That(dict["B"], Is.EqualTo("KKK")); + Assert.That(dict.FindOrAdd("T", ref s), Is.True); + Assert.That(s, Is.EqualTo("XYZ")); + }); // s = "LLL"; - Assert.IsTrue(dict.UpdateOrAdd("R", s)); - Assert.AreEqual("LLL", dict["R"]); + Assert.Multiple(() => + { + Assert.That(dict.UpdateOrAdd("R", s), Is.True); + Assert.That(dict["R"], Is.EqualTo("LLL")); + }); s = "MMM"; - Assert.IsFalse(dict.UpdateOrAdd("C", s)); - Assert.AreEqual("MMM", dict["C"]); + Assert.Multiple(() => + { + Assert.That(dict.UpdateOrAdd("C", s), Is.False); + Assert.That(dict["C"], Is.EqualTo("MMM")); + }); // bug20071112 fixed 2008-02-03 s = "NNN"; - Assert.IsTrue(dict.UpdateOrAdd("R", s, out string old)); - Assert.AreEqual("NNN", dict["R"]); - Assert.AreEqual("LLL", old); + Assert.Multiple(() => + { + Assert.That(dict.UpdateOrAdd("R", s, out string old), Is.True); + Assert.That(dict["R"], Is.EqualTo("NNN")); + Assert.That(old, Is.EqualTo("LLL")); + }); s = "OOO"; - Assert.IsFalse(dict.UpdateOrAdd("D", s, out _)); - Assert.AreEqual("OOO", dict["D"]); + Assert.Multiple(() => + { + Assert.That(dict.UpdateOrAdd("D", s, out _), Is.False); + Assert.That(dict["D"], Is.EqualTo("OOO")); + }); // Unclear which of these is correct: // Assert.AreEqual(null, old); // Assert.AreEqual("OOO", old); @@ -223,7 +261,7 @@ public void CombinedOps() [Test] public void DeepBucket() { - HashDictionary dict2 = new HashDictionary(); + HashDictionary dict2 = new(); for (int i = 0; i < 5; i++) { @@ -232,7 +270,7 @@ public void DeepBucket() for (int i = 0; i < 5; i++) { - Assert.AreEqual(5 * i, dict2[16 * i]); + Assert.That(dict2[16 * i], Is.EqualTo(5 * i)); } for (int i = 0; i < 5; i++) @@ -242,10 +280,10 @@ public void DeepBucket() for (int i = 0; i < 5; i++) { - Assert.AreEqual(7 * i + 1, dict2[16 * i]); + Assert.That(dict2[16 * i], Is.EqualTo(7 * i + 1)); } - Assert.IsTrue(dict.Check()); + Assert.That(dict.Check(), Is.True); } } @@ -276,10 +314,13 @@ public void Keys() { var keys = _dict.Keys.ToArray(); - Assert.AreEqual(3, keys.Length); - Assert.IsTrue(keys.Contains("R")); - Assert.IsTrue(keys.Contains("S")); - Assert.IsTrue(keys.Contains("T")); + Assert.That(keys.Length, Is.EqualTo(3)); + Assert.Multiple(() => + { + Assert.That(keys.Contains("R"), Is.True); + Assert.That(keys.Contains("S"), Is.True); + Assert.That(keys.Contains("T"), Is.True); + }); } @@ -288,16 +329,19 @@ public void Values() { var values = _dict.Values.ToArray(); - Assert.AreEqual(3, values.Length); - Assert.IsTrue(values.Contains("A")); - Assert.IsTrue(values.Contains("B")); - Assert.IsTrue(values.Contains("C")); + Assert.That(values.Length, Is.EqualTo(3)); + Assert.Multiple(() => + { + Assert.That(values.Contains("A"), Is.True); + Assert.That(values.Contains("B"), Is.True); + Assert.That(values.Contains("C"), Is.True); + }); } [Test] public void Fun() { - Assert.AreEqual("B", _dict.Func("T")); + Assert.That(_dict.Func("T"), Is.EqualTo("B")); } @@ -306,10 +350,13 @@ public void NormalUse() { var pairs = _dict.ToDictionary(pair => pair.Key, pair => pair.Value); - Assert.AreEqual(3, pairs.Count); - Assert.IsTrue(pairs.Contains(new SCG.KeyValuePair("R", "C"))); - Assert.IsTrue(pairs.Contains(new SCG.KeyValuePair("S", "A"))); - Assert.IsTrue(pairs.Contains(new SCG.KeyValuePair("T", "B"))); + Assert.That(pairs, Has.Count.EqualTo(3)); + Assert.Multiple(() => + { + Assert.That(pairs.Contains(new SCG.KeyValuePair("R", "C")), Is.True); + Assert.That(pairs.Contains(new SCG.KeyValuePair("S", "A")), Is.True); + Assert.That(pairs.Contains(new SCG.KeyValuePair("T", "B")), Is.True); + }); } } } diff --git a/C5.Tests/Hashing/HashDictionaryTests2.cs b/C5.Tests/Hashing/HashDictionaryTests2.cs index 9a21b24e..4286011d 100644 --- a/C5.Tests/Hashing/HashDictionaryTests2.cs +++ b/C5.Tests/Hashing/HashDictionaryTests2.cs @@ -26,7 +26,7 @@ public void Values_works_multiple_times(int numberOfIterations, int expectedResu } } - Assert.AreEqual(expectedResult, sum); + Assert.That(sum, Is.EqualTo(expectedResult)); } [TestCase(1, 10, Description = "Once")] @@ -47,7 +47,7 @@ public void Keys_works_multiple_times(int numberOfIterations, int expectedResult } } - Assert.AreEqual(expectedResult, sum); + Assert.That(sum, Is.EqualTo(expectedResult)); } [TestCase(1, 10, Description = "Once")] @@ -70,8 +70,11 @@ public void KeyValuePairs_works_multiple_times(int numberOfIterations, int expec } } - Assert.AreEqual(expectedResult, keys); - Assert.AreEqual(-expectedResult, values); + Assert.Multiple(() => + { + Assert.That(keys, Is.EqualTo(expectedResult)); + Assert.That(values, Is.EqualTo(-expectedResult)); + }); } } } diff --git a/C5.Tests/Hashing/HashTableTests.cs b/C5.Tests/Hashing/HashTableTests.cs index 1a49a2bc..4ad49246 100644 --- a/C5.Tests/Hashing/HashTableTests.cs +++ b/C5.Tests/Hashing/HashTableTests.cs @@ -6,24 +6,15 @@ using SCG = System.Collections.Generic; namespace C5.Tests.hashtable.set { - using CollectionOfInt = HashSet; - [TestFixture] public class GenericTesters { [Test] public void TestEvents() { - CollectionOfInt factory() { return new CollectionOfInt(TenEqualityComparer.Default); } - new C5.Tests.Templates.Events.CollectionTester().Test(factory); + HashSet factory() { return new HashSet(TenEqualityComparer.Default); } + new C5.Tests.Templates.Events.CollectionTester>().Test(factory); } - - //[Test] - //public void Extensible() - //{ - // C5.Tests.Templates.Extensible.Clone.Tester(); - // C5.Tests.Templates.Extensible.Serialization.Tester(); - //} } internal static class Factory @@ -56,34 +47,52 @@ public void Init() [Test] public void All() { - Assert.IsTrue(list.All(always)); - Assert.IsTrue(list.All(never)); - Assert.IsTrue(list.All(even)); + Assert.Multiple(() => + { + Assert.That(list.All(always), Is.True); + Assert.That(list.All(never), Is.True); + Assert.That(list.All(even), Is.True); + }); list.Add(0); - Assert.IsTrue(list.All(always)); - Assert.IsFalse(list.All(never)); - Assert.IsTrue(list.All(even)); + Assert.Multiple(() => + { + Assert.That(list.All(always), Is.True); + Assert.That(list.All(never), Is.False); + Assert.That(list.All(even), Is.True); + }); list.Add(5); - Assert.IsTrue(list.All(always)); - Assert.IsFalse(list.All(never)); - Assert.IsFalse(list.All(even)); + Assert.Multiple(() => + { + Assert.That(list.All(always), Is.True); + Assert.That(list.All(never), Is.False); + Assert.That(list.All(even), Is.False); + }); } [Test] public void Exists() { - Assert.IsFalse(list.Exists(always)); - Assert.IsFalse(list.Exists(never)); - Assert.IsFalse(list.Exists(even)); + Assert.Multiple(() => + { + Assert.That(list.Exists(always), Is.False); + Assert.That(list.Exists(never), Is.False); + Assert.That(list.Exists(even), Is.False); + }); list.Add(5); - Assert.IsTrue(list.Exists(always)); - Assert.IsFalse(list.Exists(never)); - Assert.IsFalse(list.Exists(even)); + Assert.Multiple(() => + { + Assert.That(list.Exists(always), Is.True); + Assert.That(list.Exists(never), Is.False); + Assert.That(list.Exists(even), Is.False); + }); list.Add(8); - Assert.IsTrue(list.Exists(always)); - Assert.IsFalse(list.Exists(never)); - Assert.IsTrue(list.Exists(even)); + Assert.Multiple(() => + { + Assert.That(list.Exists(always), Is.True); + Assert.That(list.Exists(never), Is.False); + Assert.That(list.Exists(even), Is.True); + }); } @@ -94,11 +103,11 @@ public void Apply() void a(int i) { sum = i + 10 * sum; } list.Apply(a); - Assert.AreEqual(0, sum); + Assert.That(sum, Is.EqualTo(0)); sum = 0; list.Add(5); list.Add(8); list.Add(7); list.Add(5); list.Apply(a); - Assert.AreEqual(758, sum); + Assert.That(sum, Is.EqualTo(758)); } @@ -127,7 +136,7 @@ public void Empty() { SCG.IEnumerator e = hashset.GetEnumerator(); - Assert.IsFalse(e.MoveNext()); + Assert.That(e.MoveNext(), Is.False); } @@ -144,7 +153,7 @@ public void Normal() hashset.Add(18); hashset.Add(17); hashset.Add(33); - Assert.IsTrue(IC.SetEq(hashset, 1, 5, 8, 10, 16, 17, 18, 33)); + Assert.That(IC.SetEq(hashset, 1, 5, 8, 10, 16, 17, 18, 33), Is.True); } [Test] @@ -208,12 +217,15 @@ public void Dispose() [Test] public void Format() { - Assert.AreEqual("{ }", coll.ToString()); - coll.AddAll(new int[] { -4, 28, 129, 65530 }); - Assert.AreEqual("{ 65530, -4, 28, 129 }", coll.ToString()); - Assert.AreEqual("{ FFFA, -4, 1C, 81 }", coll.ToString(null, rad16)); - Assert.AreEqual("{ 65530, -4, ... }", coll.ToString("L14", null)); - Assert.AreEqual("{ FFFA, -4, ... }", coll.ToString("L14", rad16)); + Assert.That(coll.ToString(), Is.EqualTo("{ }")); + coll.AddAll([-4, 28, 129, 65530]); + Assert.Multiple(() => + { + Assert.That(coll.ToString(), Is.EqualTo("{ 65530, -4, 28, 129 }")); + Assert.That(coll.ToString(null, rad16), Is.EqualTo("{ FFFA, -4, 1C, 81 }")); + Assert.That(coll.ToString("L14", null), Is.EqualTo("{ 65530, -4, ... }")); + Assert.That(coll.ToString("L14", rad16), Is.EqualTo("{ FFFA, -4, ... }")); + }); } } @@ -230,7 +242,7 @@ public class CollectionOrSink public void Choose() { hashset.Add(7); - Assert.AreEqual(7, hashset.Choose()); + Assert.That(hashset.Choose(), Is.EqualTo(7)); } [Test] @@ -242,19 +254,31 @@ public void BadChoose() [Test] public void CountEtAl() { - Assert.AreEqual(0, hashset.Count); - Assert.IsTrue(hashset.IsEmpty); - Assert.IsFalse(hashset.AllowsDuplicates); - Assert.IsTrue(hashset.Add(0)); - Assert.AreEqual(1, hashset.Count); - Assert.IsFalse(hashset.IsEmpty); - Assert.IsTrue(hashset.Add(5)); - Assert.AreEqual(2, hashset.Count); - Assert.IsFalse(hashset.Add(5)); - Assert.AreEqual(2, hashset.Count); - Assert.IsFalse(hashset.IsEmpty); - Assert.IsTrue(hashset.Add(8)); - Assert.AreEqual(3, hashset.Count); + Assert.That(hashset, Is.Empty); + Assert.Multiple(() => + { + Assert.That(hashset.IsEmpty, Is.True); + Assert.That(hashset.AllowsDuplicates, Is.False); + Assert.That(hashset.Add(0), Is.True); + Assert.That(hashset, Has.Count.EqualTo(1)); + }); + Assert.Multiple(() => + { + Assert.That(hashset.IsEmpty, Is.False); + Assert.That(hashset.Add(5), Is.True); + Assert.That(hashset, Has.Count.EqualTo(2)); + }); + Assert.Multiple(() => + { + Assert.That(hashset.Add(5), Is.False); + Assert.That(hashset, Has.Count.EqualTo(2)); + }); + Assert.Multiple(() => + { + Assert.That(hashset.IsEmpty, Is.False); + Assert.That(hashset.Add(8), Is.True); + Assert.That(hashset, Has.Count.EqualTo(3)); + }); } @@ -263,14 +287,17 @@ public void AddAll() { hashset.Add(3); hashset.Add(4); hashset.Add(5); - HashSet hashset2 = new HashSet(); + HashSet hashset2 = new(); hashset2.AddAll(hashset); - Assert.IsTrue(IC.SetEq(hashset2, 3, 4, 5)); + Assert.That(IC.SetEq(hashset2, 3, 4, 5), Is.True); hashset.Add(9); hashset.AddAll(hashset2); - Assert.IsTrue(IC.SetEq(hashset2, 3, 4, 5)); - Assert.IsTrue(IC.SetEq(hashset, 3, 4, 5, 9)); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(hashset2, 3, 4, 5), Is.True); + Assert.That(IC.SetEq(hashset, 3, 4, 5, 9), Is.True); + }); } @@ -302,12 +329,15 @@ public void Dispose() [Test] public void Find() { - Assert.IsFalse(list.Find(pred, out int i)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(list.Find(pred, out i)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.IsTrue(list.Find(pred, out i)); - Assert.AreEqual(45, i); + Assert.That(list.Find(pred, out int i), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(list.Find(pred, out i), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.Multiple(() => + { + Assert.That(list.Find(pred, out i), Is.True); + Assert.That(i, Is.EqualTo(45)); + }); } } @@ -325,11 +355,17 @@ public class UniqueItems [Test] public void Test() { - Assert.IsTrue(IC.SetEq(list.UniqueItems())); - Assert.IsTrue(IC.SetEq(list.ItemMultiplicities())); - list.AddAll(new int[] { 7, 9, 7 }); - Assert.IsTrue(IC.SetEq(list.UniqueItems(), 7, 9)); - Assert.IsTrue(IC.SetEq(list.ItemMultiplicities(), 7, 1, 9, 1)); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(list.UniqueItems()), Is.True); + Assert.That(IC.SetEq(list.ItemMultiplicities()), Is.True); + }); + list.AddAll([7, 9, 7]); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(list.UniqueItems(), 7, 9), Is.True); + Assert.That(IC.SetEq(list.ItemMultiplicities(), 7, 1, 9, 1), Is.True); + }); } } @@ -383,7 +419,7 @@ private string aeq(int[] a, params int[] b) [Test] public void ToArray() { - Assert.AreEqual("Alles klar", aeq(hashset.ToArray())); + Assert.That(aeq(hashset.ToArray()), Is.EqualTo("Alles klar")); hashset.Add(7); hashset.Add(3); hashset.Add(10); @@ -391,7 +427,7 @@ public void ToArray() int[] r = hashset.ToArray(); Array.Sort(r); - Assert.AreEqual("Alles klar", aeq(r, 3, 7, 10)); + Assert.That(aeq(r, 3, 7, 10), Is.EqualTo("Alles klar")); } @@ -400,20 +436,20 @@ public void CopyTo() { //Note: for small ints the itemequalityComparer is the identity! hashset.CopyTo(a, 1); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009), Is.EqualTo("Alles klar")); hashset.Add(6); hashset.CopyTo(a, 2); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009), Is.EqualTo("Alles klar")); hashset.Add(4); hashset.Add(9); hashset.CopyTo(a, 4); //TODO: make test independent on onterequalityComparer - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 9, 4, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 6, 9, 4, 1007, 1008, 1009), Is.EqualTo("Alles klar")); hashset.Clear(); hashset.Add(7); hashset.CopyTo(a, 9); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 9, 4, 1007, 1008, 7)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 6, 9, 4, 1007, 1008, 7), Is.EqualTo("Alles klar")); } @@ -465,7 +501,7 @@ public void SingleCollision() //foreach (int cell in hashset) Console.WriteLine("A: {0}", cell); hashset.Remove(7); - Assert.IsTrue(hashset.Contains(7 - 1503427877)); + Assert.That(hashset.Contains(7 - 1503427877), Is.True); } @@ -513,48 +549,78 @@ public void NullEqualityComparerinConstructor3() [Test] public void Contains() { - Assert.IsFalse(hashset.Contains(5)); + Assert.That(hashset.Contains(5), Is.False); hashset.Add(5); - Assert.IsTrue(hashset.Contains(5)); - Assert.IsFalse(hashset.Contains(7)); + Assert.Multiple(() => + { + Assert.That(hashset.Contains(5), Is.True); + Assert.That(hashset.Contains(7), Is.False); + }); hashset.Add(8); hashset.Add(10); - Assert.IsTrue(hashset.Contains(5)); - Assert.IsFalse(hashset.Contains(7)); - Assert.IsTrue(hashset.Contains(8)); - Assert.IsTrue(hashset.Contains(10)); + Assert.Multiple(() => + { + Assert.That(hashset.Contains(5), Is.True); + Assert.That(hashset.Contains(7), Is.False); + Assert.That(hashset.Contains(8), Is.True); + Assert.That(hashset.Contains(10), Is.True); + }); hashset.Remove(8); - Assert.IsTrue(hashset.Contains(5)); - Assert.IsFalse(hashset.Contains(7)); - Assert.IsFalse(hashset.Contains(8)); - Assert.IsTrue(hashset.Contains(10)); + Assert.Multiple(() => + { + Assert.That(hashset.Contains(5), Is.True); + Assert.That(hashset.Contains(7), Is.False); + Assert.That(hashset.Contains(8), Is.False); + Assert.That(hashset.Contains(10), Is.True); + }); hashset.Add(0); hashset.Add(16); hashset.Add(32); hashset.Add(48); hashset.Add(64); - Assert.IsTrue(hashset.Contains(0)); - Assert.IsTrue(hashset.Contains(16)); - Assert.IsTrue(hashset.Contains(32)); - Assert.IsTrue(hashset.Contains(48)); - Assert.IsTrue(hashset.Contains(64)); - Assert.IsTrue(hashset.Check()); + Assert.Multiple(() => + { + Assert.That(hashset.Contains(0), Is.True); + Assert.That(hashset.Contains(16), Is.True); + Assert.That(hashset.Contains(32), Is.True); + Assert.That(hashset.Contains(48), Is.True); + Assert.That(hashset.Contains(64), Is.True); + Assert.That(hashset.Check(), Is.True); + }); int i = 0, j = i; - Assert.IsTrue(hashset.Find(ref i)); - Assert.AreEqual(j, i); + Assert.Multiple(() => + { + Assert.That(hashset.Find(ref i), Is.True); + Assert.That(i, Is.EqualTo(j)); + }); j = i = 16; - Assert.IsTrue(hashset.Find(ref i)); - Assert.AreEqual(j, i); + Assert.Multiple(() => + { + Assert.That(hashset.Find(ref i), Is.True); + Assert.That(i, Is.EqualTo(j)); + }); j = i = 32; - Assert.IsTrue(hashset.Find(ref i)); - Assert.AreEqual(j, i); + Assert.Multiple(() => + { + Assert.That(hashset.Find(ref i), Is.True); + Assert.That(i, Is.EqualTo(j)); + }); j = i = 48; - Assert.IsTrue(hashset.Find(ref i)); - Assert.AreEqual(j, i); + Assert.Multiple(() => + { + Assert.That(hashset.Find(ref i), Is.True); + Assert.That(i, Is.EqualTo(j)); + }); j = i = 64; - Assert.IsTrue(hashset.Find(ref i)); - Assert.AreEqual(j, i); + Assert.Multiple(() => + { + Assert.That(hashset.Find(ref i), Is.True); + Assert.That(i, Is.EqualTo(j)); + }); j = i = 80; - Assert.IsFalse(hashset.Find(ref i)); - Assert.AreEqual(j, i); + Assert.Multiple(() => + { + Assert.That(hashset.Find(ref i), Is.False); + Assert.That(i, Is.EqualTo(j)); + }); } @@ -570,25 +636,31 @@ public void Many() a[i] = 3 * i + 1; } - Assert.IsTrue(IC.SetEq(hashset, a)); + Assert.That(IC.SetEq(hashset, a), Is.True); } [Test] public void ContainsCount() { - Assert.AreEqual(0, hashset.ContainsCount(5)); + Assert.That(hashset.ContainsCount(5), Is.EqualTo(0)); hashset.Add(5); - Assert.AreEqual(1, hashset.ContainsCount(5)); - Assert.AreEqual(0, hashset.ContainsCount(7)); + Assert.Multiple(() => + { + Assert.That(hashset.ContainsCount(5), Is.EqualTo(1)); + Assert.That(hashset.ContainsCount(7), Is.EqualTo(0)); + }); hashset.Add(8); - Assert.AreEqual(1, hashset.ContainsCount(5)); - Assert.AreEqual(0, hashset.ContainsCount(7)); - Assert.AreEqual(1, hashset.ContainsCount(8)); + Assert.Multiple(() => + { + Assert.That(hashset.ContainsCount(5), Is.EqualTo(1)); + Assert.That(hashset.ContainsCount(7), Is.EqualTo(0)); + Assert.That(hashset.ContainsCount(8), Is.EqualTo(1)); + }); hashset.Add(5); - Assert.AreEqual(1, hashset.ContainsCount(5)); - Assert.AreEqual(0, hashset.ContainsCount(7)); - Assert.AreEqual(1, hashset.ContainsCount(8)); + Assert.That(hashset.ContainsCount(5), Is.EqualTo(1)); + Assert.That(hashset.ContainsCount(7), Is.EqualTo(0)); + Assert.That(hashset.ContainsCount(8), Is.EqualTo(1)); } @@ -596,50 +668,53 @@ public void ContainsCount() public void RemoveAllCopies() { hashset.Add(5); hashset.Add(7); hashset.Add(5); - Assert.AreEqual(1, hashset.ContainsCount(5)); - Assert.AreEqual(1, hashset.ContainsCount(7)); + Assert.Multiple(() => + { + Assert.That(hashset.ContainsCount(5), Is.EqualTo(1)); + Assert.That(hashset.ContainsCount(7), Is.EqualTo(1)); + }); hashset.RemoveAllCopies(5); - Assert.AreEqual(0, hashset.ContainsCount(5)); - Assert.AreEqual(1, hashset.ContainsCount(7)); + Assert.That(hashset.ContainsCount(5), Is.EqualTo(0)); + Assert.That(hashset.ContainsCount(7), Is.EqualTo(1)); hashset.Add(5); hashset.Add(8); hashset.Add(5); hashset.RemoveAllCopies(8); - Assert.IsTrue(IC.Eq(hashset, 7, 5)); + Assert.That(IC.Eq(hashset, 7, 5), Is.True); } [Test] public void ContainsAll() { - HashSet list2 = new HashSet(); + HashSet list2 = new(); - Assert.IsTrue(hashset.ContainsAll(list2)); + Assert.That(hashset.ContainsAll(list2), Is.True); list2.Add(4); - Assert.IsFalse(hashset.ContainsAll(list2)); + Assert.That(hashset.ContainsAll(list2), Is.False); hashset.Add(4); - Assert.IsTrue(hashset.ContainsAll(list2)); + Assert.That(hashset.ContainsAll(list2), Is.True); hashset.Add(5); - Assert.IsTrue(hashset.ContainsAll(list2)); + Assert.That(hashset.ContainsAll(list2), Is.True); list2.Add(20); - Assert.IsFalse(hashset.ContainsAll(list2)); + Assert.That(hashset.ContainsAll(list2), Is.False); hashset.Add(20); - Assert.IsTrue(hashset.ContainsAll(list2)); + Assert.That(hashset.ContainsAll(list2), Is.True); } [Test] public void RetainAll() { - HashSet list2 = new HashSet(); + HashSet list2 = new(); hashset.Add(4); hashset.Add(5); hashset.Add(6); list2.Add(5); list2.Add(4); list2.Add(7); hashset.RetainAll(list2); - Assert.IsTrue(IC.SetEq(hashset, 4, 5)); + Assert.That(IC.SetEq(hashset, 4, 5), Is.True); hashset.Add(6); list2.Clear(); list2.Add(7); list2.Add(8); list2.Add(9); hashset.RetainAll(list2); - Assert.IsTrue(IC.SetEq(hashset)); + Assert.That(IC.SetEq(hashset), Is.True); } //Bug in RetainAll reported by Chris Fesler @@ -657,40 +732,40 @@ public void RetainAll2() _largeArrayTwo[i] = "" + (i + LARGE_ARRAY_MID); } - HashSet setOne = new HashSet(); + HashSet setOne = new(); setOne.AddAll(_largeArrayOne); - HashSet setTwo = new HashSet(); + HashSet setTwo = new(); setTwo.AddAll(_largeArrayTwo); setOne.RetainAll(setTwo); - Assert.IsTrue(setOne.Check(), "setOne check fails"); + Assert.That(setOne.Check(), Is.True, "setOne check fails"); for (int i = LARGE_ARRAY_MID; i < LARGE_ARRAY_SIZE; i++) { - Assert.IsTrue(setOne.Contains(_largeArrayOne[i]), "missing " + i); + Assert.That(setOne.Contains(_largeArrayOne[i]), Is.True, "missing " + i); } } [Test] public void RemoveAll() { - HashSet list2 = new HashSet(); + HashSet list2 = new(); hashset.Add(4); hashset.Add(5); hashset.Add(6); list2.Add(5); list2.Add(7); list2.Add(4); hashset.RemoveAll(list2); - Assert.IsTrue(IC.Eq(hashset, 6)); + Assert.That(IC.Eq(hashset, 6), Is.True); hashset.Add(5); hashset.Add(4); list2.Clear(); list2.Add(6); list2.Add(5); hashset.RemoveAll(list2); - Assert.IsTrue(IC.Eq(hashset, 4)); + Assert.That(IC.Eq(hashset, 4), Is.True); list2.Clear(); list2.Add(7); list2.Add(8); list2.Add(9); hashset.RemoveAll(list2); - Assert.IsTrue(IC.Eq(hashset, 4)); + Assert.That(IC.Eq(hashset, 4), Is.True); } @@ -698,21 +773,27 @@ public void RemoveAll() public void Remove() { hashset.Add(4); hashset.Add(4); hashset.Add(5); hashset.Add(4); hashset.Add(6); - Assert.IsFalse(hashset.Remove(2)); - Assert.IsTrue(hashset.Remove(4)); - Assert.IsTrue(IC.SetEq(hashset, 5, 6)); + Assert.Multiple(() => + { + Assert.That(hashset.Remove(2), Is.False); + Assert.That(hashset.Remove(4), Is.True); + Assert.That(IC.SetEq(hashset, 5, 6), Is.True); + }); hashset.Add(7); hashset.Add(21); hashset.Add(37); hashset.Add(53); hashset.Add(69); hashset.Add(85); - Assert.IsTrue(hashset.Remove(5)); - Assert.IsTrue(IC.SetEq(hashset, 6, 7, 21, 37, 53, 69, 85)); - Assert.IsFalse(hashset.Remove(165)); - Assert.IsTrue(IC.SetEq(hashset, 6, 7, 21, 37, 53, 69, 85)); - Assert.IsTrue(hashset.Remove(53)); - Assert.IsTrue(IC.SetEq(hashset, 6, 7, 21, 37, 69, 85)); - Assert.IsTrue(hashset.Remove(37)); - Assert.IsTrue(IC.SetEq(hashset, 6, 7, 21, 69, 85)); - Assert.IsTrue(hashset.Remove(85)); - Assert.IsTrue(IC.SetEq(hashset, 6, 7, 21, 69)); + Assert.Multiple(() => + { + Assert.That(hashset.Remove(5), Is.True); + Assert.That(IC.SetEq(hashset, 6, 7, 21, 37, 53, 69, 85), Is.True); + Assert.That(hashset.Remove(165), Is.False); + }); + Assert.That(IC.SetEq(hashset, 6, 7, 21, 37, 53, 69, 85), Is.True); + Assert.That(hashset.Remove(53), Is.True); + Assert.That(IC.SetEq(hashset, 6, 7, 21, 37, 69, 85), Is.True); + Assert.That(hashset.Remove(37), Is.True); + Assert.That(IC.SetEq(hashset, 6, 7, 21, 69, 85), Is.True); + Assert.That(hashset.Remove(85), Is.True); + Assert.That(IC.SetEq(hashset, 6, 7, 21, 69), Is.True); } @@ -721,7 +802,7 @@ public void Clear() { hashset.Add(7); hashset.Add(7); hashset.Clear(); - Assert.IsTrue(hashset.IsEmpty); + Assert.That(hashset.IsEmpty, Is.True); } @@ -757,13 +838,16 @@ public void Init() [Test] public void Find() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + System.Collections.Generic.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Find(ref p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); + Assert.Multiple(() => + { + Assert.That(lst.Find(ref p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Find(ref p)); + Assert.That(lst.Find(ref p), Is.False); } @@ -773,15 +857,21 @@ public void FindOrAdd() var p = new SCG.KeyValuePair(3, 78); var q = new SCG.KeyValuePair(); - Assert.IsTrue(lst.FindOrAdd(ref p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); + Assert.Multiple(() => + { + Assert.That(lst.FindOrAdd(ref p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); p = new SCG.KeyValuePair(13, 79); - Assert.IsFalse(lst.FindOrAdd(ref p)); + Assert.That(lst.FindOrAdd(ref p), Is.False); q = new SCG.KeyValuePair(13, q.Value); - Assert.IsTrue(lst.Find(ref q)); - Assert.AreEqual(13, q.Key); - Assert.AreEqual(79, q.Value); + Assert.Multiple(() => + { + Assert.That(lst.Find(ref q), Is.True); + Assert.That(q.Key, Is.EqualTo(13)); + Assert.That(q.Value, Is.EqualTo(79)); + }); } @@ -791,13 +881,16 @@ public void Update() var p = new SCG.KeyValuePair(3, 78); var q = new SCG.KeyValuePair(); - Assert.IsTrue(lst.Update(p)); + Assert.That(lst.Update(p), Is.True); q = new SCG.KeyValuePair(3, q.Value); - Assert.IsTrue(lst.Find(ref q)); - Assert.AreEqual(3, q.Key); - Assert.AreEqual(78, q.Value); + Assert.Multiple(() => + { + Assert.That(lst.Find(ref q), Is.True); + Assert.That(q.Key, Is.EqualTo(3)); + Assert.That(q.Value, Is.EqualTo(78)); + }); p = new SCG.KeyValuePair(13, 78); - Assert.IsFalse(lst.Update(p)); + Assert.That(lst.Update(p), Is.False); } @@ -807,17 +900,23 @@ public void UpdateOrAdd1() var p = new SCG.KeyValuePair(3, 78); var q = new SCG.KeyValuePair(); - Assert.IsTrue(lst.UpdateOrAdd(p)); + Assert.That(lst.UpdateOrAdd(p), Is.True); q = new SCG.KeyValuePair(3, q.Value); - Assert.IsTrue(lst.Find(ref q)); - Assert.AreEqual(3, q.Key); - Assert.AreEqual(78, q.Value); + Assert.Multiple(() => + { + Assert.That(lst.Find(ref q), Is.True); + Assert.That(q.Key, Is.EqualTo(3)); + Assert.That(q.Value, Is.EqualTo(78)); + }); p = new SCG.KeyValuePair(13, 79); - Assert.IsFalse(lst.UpdateOrAdd(p)); + Assert.That(lst.UpdateOrAdd(p), Is.False); q = new SCG.KeyValuePair(13, q.Value); - Assert.IsTrue(lst.Find(ref q)); - Assert.AreEqual(13, q.Key); - Assert.AreEqual(79, q.Value); + Assert.Multiple(() => + { + Assert.That(lst.Find(ref q), Is.True); + Assert.That(q.Key, Is.EqualTo(13)); + Assert.That(q.Value, Is.EqualTo(79)); + }); } [Test] @@ -826,24 +925,30 @@ public void UpdateOrAdd2() ICollection coll = new HashSet(); // s1 and s2 are distinct objects but contain the same text: string s1 = "abc", s2 = ("def" + s1).Substring(3); - Assert.IsFalse(coll.UpdateOrAdd(s1, out string old)); - Assert.AreEqual(null, old); - Assert.IsTrue(coll.UpdateOrAdd(s2, out old)); - Assert.IsTrue(object.ReferenceEquals(s1, old)); - Assert.IsFalse(object.ReferenceEquals(s2, old)); + Assert.Multiple(() => + { + Assert.That(coll.UpdateOrAdd(s1, out string old), Is.False); + Assert.That(old, Is.EqualTo(null)); + Assert.That(coll.UpdateOrAdd(s2, out old), Is.True); + Assert.That(ReferenceEquals(s1, old), Is.True); + Assert.That(ReferenceEquals(s2, old), Is.False); + }); } [Test] public void RemoveWithReturn() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); - //System.Collections.Generic.KeyValuePair q = new System.Collections.Generic.KeyValuePair(); + System.Collections.Generic.KeyValuePair p = new(3, 78); + Assert.Multiple(() => + { + //System.Collections.Generic.KeyValuePair q = new System.Collections.Generic.KeyValuePair(); - Assert.IsTrue(lst.Remove(p, out p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); + Assert.That(lst.Remove(p, out p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Remove(p, out _)); + Assert.That(lst.Remove(p, out _), Is.False); } } @@ -873,7 +978,7 @@ public void Init() [Test] public void EmptyEmpty() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); + Assert.That(dit.UnsequencedEquals(dat), Is.True); } @@ -881,24 +986,30 @@ public void EmptyEmpty() public void EmptyNonEmpty() { dit.Add(3); - Assert.IsFalse(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.False); + Assert.That(dat.UnsequencedEquals(dit), Is.False); + }); } [Test] public void HashVal() { - Assert.AreEqual(CHC.UnsequencedHashCode(), dit.GetUnsequencedHashCode()); + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode())); dit.Add(3); - Assert.AreEqual(CHC.UnsequencedHashCode(3), dit.GetUnsequencedHashCode()); + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3))); dit.Add(7); - Assert.AreEqual(CHC.UnsequencedHashCode(3, 7), dit.GetUnsequencedHashCode()); - Assert.AreEqual(CHC.UnsequencedHashCode(), dut.GetUnsequencedHashCode()); + Assert.Multiple(() => + { + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3, 7))); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode())); + }); dut.Add(3); - Assert.AreEqual(CHC.UnsequencedHashCode(3), dut.GetUnsequencedHashCode()); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3))); dut.Add(7); - Assert.AreEqual(CHC.UnsequencedHashCode(7, 3), dut.GetUnsequencedHashCode()); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(7, 3))); } @@ -907,8 +1018,11 @@ public void EqualHashButDifferent() { dit.Add(-1657792980); dit.Add(-1570288808); dat.Add(1862883298); dat.Add(-272461342); - Assert.AreEqual(dit.GetUnsequencedHashCode(), dat.GetUnsequencedHashCode()); - Assert.IsFalse(dit.UnsequencedEquals(dat)); + Assert.Multiple(() => + { + Assert.That(dat.GetUnsequencedHashCode(), Is.EqualTo(dit.GetUnsequencedHashCode())); + Assert.That(dit.UnsequencedEquals(dat), Is.False); + }); } @@ -918,11 +1032,17 @@ public void Normal() dit.Add(3); dit.Add(7); dat.Add(3); - Assert.IsFalse(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.False); + Assert.That(dat.UnsequencedEquals(dit), Is.False); + }); dat.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsTrue(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dat.UnsequencedEquals(dit), Is.True); + }); } @@ -931,23 +1051,29 @@ public void WrongOrder() { dit.Add(3); dut.Add(3); - Assert.IsTrue(dit.UnsequencedEquals(dut)); - Assert.IsTrue(dut.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dut), Is.True); + Assert.That(dut.UnsequencedEquals(dit), Is.True); + }); dit.Add(7); dut.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dut)); - Assert.IsTrue(dut.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dut), Is.True); + Assert.That(dut.UnsequencedEquals(dit), Is.True); + }); } [Test] public void Reflexive() { - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); dit.Add(3); - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); dit.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); } @@ -988,8 +1114,11 @@ public void Init() [Test] public void Check() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dit.UnsequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dit.UnsequencedEquals(dut), Is.False); + }); } @@ -998,8 +1127,11 @@ public void Multi() { Dit.Add(dit); Dit.Add(dut); Dit.Add(dit); Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); - Assert.IsTrue(Dit.UnsequencedEquals(Dat)); - Assert.IsFalse(Dit.UnsequencedEquals(Dut)); + Assert.Multiple(() => + { + Assert.That(Dit.UnsequencedEquals(Dat), Is.True); + Assert.That(Dit.UnsequencedEquals(Dut), Is.False); + }); } @@ -1016,9 +1148,9 @@ public void Dispose() [TestFixture] public class MultiLevelOrderedOfUnOrdered { - private ICollection dit, dat, dut; + private HashSet dit, dat, dut; - private ISequenced> Dit, Dat, Dut; + private LinkedList> Dit, Dat, Dut; [SetUp] @@ -1039,8 +1171,11 @@ public void Init() [Test] public void Check() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dit.UnsequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dit.UnsequencedEquals(dut), Is.False); + }); } @@ -1050,8 +1185,11 @@ public void Multi() Dit.Add(dit); Dit.Add(dut); Dit.Add(dit); Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); Dut.Add(dit); Dut.Add(dut); Dut.Add(dat); - Assert.IsFalse(Dit.SequencedEquals(Dat)); - Assert.IsTrue(Dit.SequencedEquals(Dut)); + Assert.Multiple(() => + { + Assert.That(Dit.SequencedEquals(Dat), Is.False); + Assert.That(Dit.SequencedEquals(Dut), Is.True); + }); } @@ -1059,18 +1197,18 @@ public void Multi() public void Dispose() { dit = dat = dut = null; - Dit = Dat = Dut = null; + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); } } - - [TestFixture] public class MultiLevelUnOrderedOfOrdered { - private ISequenced dit, dat, dut, dot; + private LinkedList dit, dat, dut, dot; - private ICollection> Dit, Dat, Dut, Dot; + private HashSet> Dit, Dat, Dut, Dot; [SetUp] @@ -1094,9 +1232,12 @@ public void Init() [Test] public void Check() { - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsTrue(dit.SequencedEquals(dot)); - Assert.IsFalse(dit.SequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dit.SequencedEquals(dot), Is.True); + Assert.That(dit.SequencedEquals(dut), Is.False); + }); } @@ -1107,17 +1248,23 @@ public void Multi() Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); Dut.Add(dot); Dut.Add(dut);//Dut.Add(dit); Dot.Add(dit); Dot.Add(dit); Dot.Add(dut); - Assert.IsTrue(Dit.UnsequencedEquals(Dit)); - Assert.IsTrue(Dit.UnsequencedEquals(Dut)); - Assert.IsFalse(Dit.UnsequencedEquals(Dat)); - Assert.IsTrue(Dit.UnsequencedEquals(Dot)); + Assert.Multiple(() => + { + Assert.That(Dit.UnsequencedEquals(Dit), Is.True); + Assert.That(Dit.UnsequencedEquals(Dut), Is.True); + Assert.That(Dit.UnsequencedEquals(Dat), Is.False); + Assert.That(Dit.UnsequencedEquals(Dot), Is.True); + }); } [TearDown] public void Dispose() { - dit = dat = dut = dot = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + dot.Dispose(); Dit = Dat = Dut = Dot = null; } } diff --git a/C5.Tests/Hashing/TreeDictionaryTests.cs b/C5.Tests/Hashing/TreeDictionaryTests.cs index 42dbb82c..d173fa85 100644 --- a/C5.Tests/Hashing/TreeDictionaryTests.cs +++ b/C5.Tests/Hashing/TreeDictionaryTests.cs @@ -18,7 +18,7 @@ public void TreeDictionaryBug_no_42() tree.UpdateOrAdd(0, 0); var last = tree.Values.LastOrDefault(); - Assert.AreEqual(0, last); + Assert.That(last, Is.EqualTo(0)); } [TestCase(1, 10, Description = "Once")] @@ -39,7 +39,7 @@ public void Values_works_multiple_times(int numberOfIterations, int expectedResu } } - Assert.AreEqual(expectedResult, sum); + Assert.That(sum, Is.EqualTo(expectedResult)); } [TestCase(1, 10, Description = "Once")] @@ -60,7 +60,7 @@ public void Keys_works_multiple_times(int numberOfIterations, int expectedResult } } - Assert.AreEqual(expectedResult, sum); + Assert.That(sum, Is.EqualTo(expectedResult)); } [TestCase(1, 10, Description = "Once")] @@ -83,8 +83,11 @@ public void KeyValuePairs_works_multiple_times(int numberOfIterations, int expec } } - Assert.AreEqual(expectedResult, keys); - Assert.AreEqual(-expectedResult, values); + Assert.Multiple(() => + { + Assert.That(keys, Is.EqualTo(expectedResult)); + Assert.That(values, Is.EqualTo(-expectedResult)); + }); } } } diff --git a/C5.Tests/Heaps/HeapTests.cs b/C5.Tests/Heaps/HeapTests.cs index dd903432..0cb3810e 100644 --- a/C5.Tests/Heaps/HeapTests.cs +++ b/C5.Tests/Heaps/HeapTests.cs @@ -6,24 +6,15 @@ namespace C5.Tests.heaps { - using CollectionOfInt = IntervalHeap; - [TestFixture] public class GenericTesters { [Test] public void TestEvents() { - CollectionOfInt factory() { return new CollectionOfInt(TenEqualityComparer.Default); } - new C5.Tests.Templates.Events.PriorityQueueTester().Test(factory); + IntervalHeap factory() { return new IntervalHeap(TenEqualityComparer.Default); } + new C5.Tests.Templates.Events.PriorityQueueTester>().Test(factory); } - - //[Test] - //public void Extensible() - //{ - // C5.Tests.Templates.Extensible.Clone.Tester(); - // C5.Tests.Templates.Extensible.Serialization.Tester(); - //} } [TestFixture] @@ -42,12 +33,12 @@ public void Init() [TearDown] - public void Dispose() { queue = null; events = null; } + public void Dispose() { queue = null; events.Dispose(); } [Test] public void Listenable() { - Assert.AreEqual(EventType.Basic, queue.ListenableEvents); + Assert.That(queue.ListenableEvents, Is.EqualTo(EventType.Basic)); } private enum Acts @@ -61,37 +52,37 @@ public void Direct() CollectionChangedHandler cch; ItemsAddedHandler iah; ItemsRemovedHandler irh; - Assert.AreEqual(EventType.None, queue.ActiveEvents); + Assert.That(queue.ActiveEvents, Is.EqualTo(EventType.None)); queue.CollectionChanged += (cch = new CollectionChangedHandler(queue_CollectionChanged)); - Assert.AreEqual(EventType.Changed, queue.ActiveEvents); + Assert.That(queue.ActiveEvents, Is.EqualTo(EventType.Changed)); queue.ItemsAdded += (iah = new ItemsAddedHandler(queue_ItemAdded)); - Assert.AreEqual(EventType.Changed | EventType.Added, queue.ActiveEvents); + Assert.That(queue.ActiveEvents, Is.EqualTo(EventType.Changed | EventType.Added)); queue.ItemsRemoved += (irh = new ItemsRemovedHandler(queue_ItemRemoved)); - Assert.AreEqual(EventType.Changed | EventType.Added | EventType.Removed, queue.ActiveEvents); + Assert.That(queue.ActiveEvents, Is.EqualTo(EventType.Changed | EventType.Added | EventType.Removed)); queue.Add(34); queue.Add(56); - queue.AddAll(new int[] { }); + queue.AddAll([]); queue.Add(34); queue.Add(12); queue.DeleteMax(); queue.DeleteMin(); - queue.AddAll(new int[] { 4, 5, 6, 2 }); - Assert.AreEqual(17, events.Count); - int[] vals = { 34, 0, 56, 0, 34, 0, 12, 0, 56, 0, 12, 0, 4, 5, 6, 2, 0 }; - Acts[] acts = { Acts.Add, Acts.Changed, Acts.Add, Acts.Changed, Acts.Add, Acts.Changed, Acts.Add, Acts.Changed, - Acts.Remove, Acts.Changed, Acts.Remove, Acts.Changed, Acts.Add, Acts.Add, Acts.Add, Acts.Add, Acts.Changed }; + queue.AddAll([4, 5, 6, 2]); + Assert.That(events, Has.Count.EqualTo(17)); + int[] vals = [34, 0, 56, 0, 34, 0, 12, 0, 56, 0, 12, 0, 4, 5, 6, 2, 0]; + Acts[] acts = [ Acts.Add, Acts.Changed, Acts.Add, Acts.Changed, Acts.Add, Acts.Changed, Acts.Add, Acts.Changed, + Acts.Remove, Acts.Changed, Acts.Remove, Acts.Changed, Acts.Add, Acts.Add, Acts.Add, Acts.Add, Acts.Changed ]; for (int i = 0; i < vals.Length; i++) { //Console.WriteLine("{0}", events[cell]); - Assert.AreEqual(acts[i], events[i].Key, "Action " + i); - Assert.AreEqual(vals[i], events[i].Value, "Value " + i); + Assert.That(events[i].Key, Is.EqualTo(acts[i]), "Action " + i); + Assert.That(events[i].Value, Is.EqualTo(vals[i]), "Value " + i); } queue.CollectionChanged -= cch; - Assert.AreEqual(EventType.Added | EventType.Removed, queue.ActiveEvents); + Assert.That(queue.ActiveEvents, Is.EqualTo(EventType.Added | EventType.Removed)); queue.ItemsAdded -= iah; - Assert.AreEqual(EventType.Removed, queue.ActiveEvents); + Assert.That(queue.ActiveEvents, Is.EqualTo(EventType.Removed)); queue.ItemsRemoved -= irh; - Assert.AreEqual(EventType.None, queue.ActiveEvents); + Assert.That(queue.ActiveEvents, Is.EqualTo(EventType.None)); } [Test] @@ -107,16 +98,16 @@ public void Guarded() queue.Add(12); queue.DeleteMax(); queue.DeleteMin(); - queue.AddAll(new int[] { 4, 5, 6, 2 }); - Assert.AreEqual(17, events.Count); - int[] vals = { 34, 0, 56, 0, 34, 0, 12, 0, 56, 0, 12, 0, 4, 5, 6, 2, 0 }; - Acts[] acts = { Acts.Add, Acts.Changed, Acts.Add, Acts.Changed, Acts.Add, Acts.Changed, Acts.Add, Acts.Changed, - Acts.Remove, Acts.Changed, Acts.Remove, Acts.Changed, Acts.Add, Acts.Add, Acts.Add, Acts.Add, Acts.Changed }; + queue.AddAll([4, 5, 6, 2]); + Assert.That(events, Has.Count.EqualTo(17)); + int[] vals = [34, 0, 56, 0, 34, 0, 12, 0, 56, 0, 12, 0, 4, 5, 6, 2, 0]; + Acts[] acts = [ Acts.Add, Acts.Changed, Acts.Add, Acts.Changed, Acts.Add, Acts.Changed, Acts.Add, Acts.Changed, + Acts.Remove, Acts.Changed, Acts.Remove, Acts.Changed, Acts.Add, Acts.Add, Acts.Add, Acts.Add, Acts.Changed ]; for (int i = 0; i < vals.Length; i++) { //Console.WriteLine("{0}", events[cell]); - Assert.AreEqual(vals[i], events[i].Value); - Assert.AreEqual(acts[i], events[i].Key); + Assert.That(events[i].Value, Is.EqualTo(vals[i])); + Assert.That(events[i].Key, Is.EqualTo(acts[i])); } } @@ -148,12 +139,12 @@ public class Formatting [Test] public void Format() { - Assert.AreEqual("{ }", coll.ToString()); - coll.AddAll(new int[] { -4, 28, 129, 65530 }); - Assert.AreEqual("{ -4, 65530, 28, 129 }", coll.ToString()); - Assert.AreEqual("{ -4, FFFA, 1C, 81 }", coll.ToString(null, rad16)); - Assert.AreEqual("{ -4, 65530, ... }", coll.ToString("L14", null)); - Assert.AreEqual("{ -4, FFFA, ... }", coll.ToString("L14", rad16)); + Assert.That(coll.ToString(), Is.EqualTo("{ }")); + coll.AddAll([-4, 28, 129, 65530]); + Assert.That(coll.ToString(), Is.EqualTo("{ -4, 65530, 28, 129 }")); + Assert.That(coll.ToString(null, rad16), Is.EqualTo("{ -4, FFFA, 1C, 81 }")); + Assert.That(coll.ToString("L14", null), Is.EqualTo("{ -4, 65530, ... }")); + Assert.That(coll.ToString("L14", rad16), Is.EqualTo("{ -4, FFFA, ... }")); } } @@ -189,36 +180,36 @@ public void Handles() IPriorityQueueHandle[] handles = new IPriorityQueueHandle[10]; queue.Add(ref handles[0], 7); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); queue.Add(ref handles[1], 72); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); queue.Add(ref handles[2], 27); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); queue.Add(ref handles[3], 17); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); queue.Add(ref handles[4], 70); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); queue.Add(ref handles[5], 1); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); queue.Add(ref handles[6], 2); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); queue.Add(ref handles[7], 7); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); queue.Add(ref handles[8], 8); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); queue.Add(ref handles[9], 9); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); queue.Delete(handles[2]); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); queue.Delete(handles[0]); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); queue.Delete(handles[8]); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); queue.Delete(handles[4]); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); queue.Delete(handles[6]); - Assert.IsTrue(queue.Check()); - Assert.AreEqual(5, queue.Count); + Assert.That(queue.Check(), Is.True); + Assert.That(queue, Has.Count.EqualTo(5)); } [Test] @@ -229,17 +220,17 @@ public void Replace() queue.Add(10); queue.Add(ref handle, 7); queue.Add(21); - Assert.AreEqual(7, queue.Replace(handle, 12)); - Assert.AreEqual(21, queue.FindMax()); - Assert.AreEqual(12, queue.Replace(handle, 34)); - Assert.AreEqual(34, queue.FindMax()); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Replace(handle, 12), Is.EqualTo(7)); + Assert.That(queue.FindMax(), Is.EqualTo(21)); + Assert.That(queue.Replace(handle, 34), Is.EqualTo(12)); + Assert.That(queue.FindMax(), Is.EqualTo(34)); + Assert.That(queue.Check(), Is.True); //replace max - Assert.AreEqual(34, queue.Replace(handle, 60)); - Assert.AreEqual(60, queue.FindMax()); - Assert.AreEqual(60, queue.Replace(handle, queue[handle] + 80)); - Assert.AreEqual(140, queue.FindMax()); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Replace(handle, 60), Is.EqualTo(34)); + Assert.That(queue.FindMax(), Is.EqualTo(60)); + Assert.That(queue.Replace(handle, queue[handle] + 80), Is.EqualTo(60)); + Assert.That(queue.FindMax(), Is.EqualTo(140)); + Assert.That(queue.Check(), Is.True); } [Test] @@ -250,8 +241,8 @@ public void Replace2() queue.Add(10); queue.Add(ref handle, 7); //Replace last item in queue with something large - Assert.AreEqual(7, queue.Replace(handle, 12)); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Replace(handle, 12), Is.EqualTo(7)); + Assert.That(queue.Check(), Is.True); } /// @@ -262,8 +253,8 @@ public void Replace3() { IPriorityQueueHandle handle = null; queue.Add(ref handle, 10); - Assert.AreEqual(10, queue.Replace(handle, 12)); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Replace(handle, 12), Is.EqualTo(10)); + Assert.That(queue.Check(), Is.True); } /// @@ -274,11 +265,11 @@ public void Replace4a() { IPriorityQueueHandle handle1 = null; queue.Add(ref handle1, 4); - Assert.AreEqual(4, queue.FindMin()); + Assert.That(queue.FindMin(), Is.EqualTo(4)); queue.Add(3); - Assert.AreEqual(3, queue.FindMin()); - Assert.AreEqual(4, queue.Replace(handle1, 2)); - Assert.AreEqual(2, queue.FindMin()); + Assert.That(queue.FindMin(), Is.EqualTo(3)); + Assert.That(queue.Replace(handle1, 2), Is.EqualTo(4)); + Assert.That(queue.FindMin(), Is.EqualTo(2)); } [Test] @@ -286,11 +277,11 @@ public void Replace4b() { IPriorityQueueHandle handle1 = null; queue.Add(ref handle1, 2); - Assert.AreEqual(2, queue.FindMax()); + Assert.That(queue.FindMax(), Is.EqualTo(2)); queue.Add(3); - Assert.AreEqual(3, queue.FindMax()); - Assert.AreEqual(2, queue.Replace(handle1, 4)); - Assert.AreEqual(4, queue.FindMax()); + Assert.That(queue.FindMax(), Is.EqualTo(3)); + Assert.That(queue.Replace(handle1, 4), Is.EqualTo(2)); + Assert.That(queue.FindMax(), Is.EqualTo(4)); } [Test] @@ -301,25 +292,25 @@ public void Replace5a() IPriorityQueue q = new IntervalHeap(); IPriorityQueueHandle handle1 = null; q.Add(ref handle1, 3.0); - Assert.AreEqual(3.0, q.FindMin()); + Assert.That(q.FindMin(), Is.EqualTo(3.0)); for (int i = 1; i < size; i++) { q.Add(i + 3.0); } - Assert.AreEqual(3.0, q.FindMin()); + Assert.That(q.FindMin(), Is.EqualTo(3.0)); for (int min = 2; min >= -10; min--) { - Assert.AreEqual(min + 1.0, q.Replace(handle1, min)); - Assert.AreEqual(min, q.FindMin()); + Assert.That(q.Replace(handle1, min), Is.EqualTo(min + 1.0)); + Assert.That(q.FindMin(), Is.EqualTo(min)); } - Assert.AreEqual(-10.0, q.DeleteMin()); + Assert.That(q.DeleteMin(), Is.EqualTo(-10.0)); for (int i = 1; i < size; i++) { - Assert.AreEqual(i + 3.0, q.DeleteMin()); + Assert.That(q.DeleteMin(), Is.EqualTo(i + 3.0)); } - Assert.IsTrue(q.IsEmpty); + Assert.That(q.IsEmpty, Is.True); } } @@ -331,25 +322,25 @@ public void Replace5b() IPriorityQueue q = new IntervalHeap(); IPriorityQueueHandle handle1 = null; q.Add(ref handle1, -3.0); - Assert.AreEqual(-3.0, q.FindMax()); + Assert.That(q.FindMax(), Is.EqualTo(-3.0)); for (int i = 1; i < size; i++) { q.Add(-i - 3.0); } - Assert.AreEqual(-3.0, q.FindMax()); + Assert.That(q.FindMax(), Is.EqualTo(-3.0)); for (int max = -2; max <= 10; max++) { - Assert.AreEqual(max - 1.0, q.Replace(handle1, max)); - Assert.AreEqual(max, q.FindMax()); + Assert.That(q.Replace(handle1, max), Is.EqualTo(max - 1.0)); + Assert.That(q.FindMax(), Is.EqualTo(max)); } - Assert.AreEqual(10.0, q.DeleteMax()); + Assert.That(q.DeleteMax(), Is.EqualTo(10.0)); for (int i = 1; i < size; i++) { - Assert.AreEqual(-i - 3.0, q.DeleteMax()); + Assert.That(q.DeleteMax(), Is.EqualTo(-i - 3.0)); } - Assert.IsTrue(q.IsEmpty); + Assert.That(q.IsEmpty, Is.True); } } @@ -358,13 +349,13 @@ public void Delete1a() { IPriorityQueueHandle handle1 = null; queue.Add(ref handle1, 4); - Assert.AreEqual(4, queue.FindMin()); + Assert.That(queue.FindMin(), Is.EqualTo(4)); queue.Add(3); - Assert.AreEqual(3, queue.FindMin()); + Assert.That(queue.FindMin(), Is.EqualTo(3)); queue.Add(2); - Assert.AreEqual(4, queue.Delete(handle1)); - Assert.AreEqual(2, queue.FindMin()); - Assert.AreEqual(3, queue.FindMax()); + Assert.That(queue.Delete(handle1), Is.EqualTo(4)); + Assert.That(queue.FindMin(), Is.EqualTo(2)); + Assert.That(queue.FindMax(), Is.EqualTo(3)); } [Test] @@ -372,13 +363,13 @@ public void Delete1b() { IPriorityQueueHandle handle1 = null; queue.Add(ref handle1, 2); - Assert.AreEqual(2, queue.FindMax()); + Assert.That(queue.FindMax(), Is.EqualTo(2)); queue.Add(3); - Assert.AreEqual(3, queue.FindMax()); + Assert.That(queue.FindMax(), Is.EqualTo(3)); queue.Add(4); - Assert.AreEqual(2, queue.Delete(handle1)); - Assert.AreEqual(3, queue.FindMin()); - Assert.AreEqual(4, queue.FindMax()); + Assert.That(queue.Delete(handle1), Is.EqualTo(2)); + Assert.That(queue.FindMin(), Is.EqualTo(3)); + Assert.That(queue.FindMax(), Is.EqualTo(4)); } [Test] @@ -422,24 +413,23 @@ public void ErrorReplaceInvalidHandle() [Test] public void Simple() { - Assert.IsTrue(queue.AllowsDuplicates); - Assert.AreEqual(0, queue.Count); + Assert.That(queue.AllowsDuplicates, Is.True); + Assert.That(queue, Is.Empty); queue.Add(8); queue.Add(18); queue.Add(8); queue.Add(3); - Assert.AreEqual(4, queue.Count); - Assert.AreEqual(18, queue.DeleteMax()); - Assert.AreEqual(3, queue.Count); - Assert.AreEqual(3, queue.DeleteMin()); - Assert.AreEqual(2, queue.Count); - Assert.AreEqual(8, queue.FindMax()); - Assert.AreEqual(8, queue.DeleteMax()); - Assert.AreEqual(8, queue.FindMax()); + Assert.That(queue, Has.Count.EqualTo(4)); + Assert.That(queue.DeleteMax(), Is.EqualTo(18)); + Assert.That(queue, Has.Count.EqualTo(3)); + Assert.That(queue.DeleteMin(), Is.EqualTo(3)); + Assert.That(queue, Has.Count.EqualTo(2)); + Assert.That(queue.FindMax(), Is.EqualTo(8)); + Assert.That(queue.DeleteMax(), Is.EqualTo(8)); + Assert.That(queue.FindMax(), Is.EqualTo(8)); queue.Add(15); - Assert.AreEqual(15, queue.FindMax()); - Assert.AreEqual(8, queue.FindMin()); - Assert.IsTrue(queue.Comparer.Compare(2, 3) < 0); - Assert.IsTrue(queue.Comparer.Compare(4, 3) > 0); - Assert.IsTrue(queue.Comparer.Compare(3, 3) == 0); - + Assert.That(queue.FindMax(), Is.EqualTo(15)); + Assert.That(queue.FindMin(), Is.EqualTo(8)); + Assert.That(queue.Comparer.Compare(2, 3), Is.LessThan(0)); + Assert.That(queue.Comparer.Compare(4, 3), Is.GreaterThan(0)); + Assert.That(queue.Comparer.Compare(3, 3), Is.EqualTo(0)); } @@ -453,7 +443,7 @@ public void Enumerate() siz++; } - Assert.AreEqual(0, siz); + Assert.That(siz, Is.EqualTo(0)); queue.Add(8); queue.Add(18); queue.Add(8); queue.Add(3); @@ -462,47 +452,47 @@ public void Enumerate() a[siz++] = i; } - Assert.AreEqual(4, siz); + Assert.That(siz, Is.EqualTo(4)); Array.Sort(a, 0, siz); - Assert.AreEqual(3, a[0]); - Assert.AreEqual(8, a[1]); - Assert.AreEqual(8, a[2]); - Assert.AreEqual(18, a[3]); + Assert.That(a[0], Is.EqualTo(3)); + Assert.That(a[1], Is.EqualTo(8)); + Assert.That(a[2], Is.EqualTo(8)); + Assert.That(a[3], Is.EqualTo(18)); siz = 0; - Assert.AreEqual(18, queue.DeleteMax()); + Assert.That(queue.DeleteMax(), Is.EqualTo(18)); foreach (int i in queue) { a[siz++] = i; } - Assert.AreEqual(3, siz); + Assert.That(siz, Is.EqualTo(3)); Array.Sort(a, 0, siz); - Assert.AreEqual(3, a[0]); - Assert.AreEqual(8, a[1]); - Assert.AreEqual(8, a[2]); + Assert.That(a[0], Is.EqualTo(3)); + Assert.That(a[1], Is.EqualTo(8)); + Assert.That(a[2], Is.EqualTo(8)); siz = 0; - Assert.AreEqual(8, queue.DeleteMax()); + Assert.That(queue.DeleteMax(), Is.EqualTo(8)); foreach (int i in queue) { a[siz++] = i; } - Assert.AreEqual(2, siz); + Assert.That(siz, Is.EqualTo(2)); Array.Sort(a, 0, siz); - Assert.AreEqual(3, a[0]); - Assert.AreEqual(8, a[1]); + Assert.That(a[0], Is.EqualTo(3)); + Assert.That(a[1], Is.EqualTo(8)); siz = 0; - Assert.AreEqual(8, queue.DeleteMax()); + Assert.That(queue.DeleteMax(), Is.EqualTo(8)); foreach (int i in queue) { a[siz++] = i; } - Assert.AreEqual(1, siz); - Assert.AreEqual(3, a[0]); + Assert.That(siz, Is.EqualTo(1)); + Assert.That(a[0], Is.EqualTo(3)); } [Test] @@ -510,24 +500,24 @@ public void Random() { int length = 1000; int[] a = new int[length]; - Random ran = new Random(6754); + Random ran = new(6754); for (int i = 0; i < length; i++) { queue.Add(a[i] = ran.Next()); } - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); Array.Sort(a); for (int i = 0; i < length / 2; i++) { - Assert.AreEqual(a[length - i - 1], queue.DeleteMax()); - Assert.IsTrue(queue.Check()); - Assert.AreEqual(a[i], queue.DeleteMin()); - Assert.IsTrue(queue.Check()); + Assert.That(queue.DeleteMax(), Is.EqualTo(a[length - i - 1])); + Assert.That(queue.Check(), Is.True); + Assert.That(queue.DeleteMin(), Is.EqualTo(a[i])); + Assert.That(queue.Check(), Is.True); } - Assert.IsTrue(queue.IsEmpty); + Assert.That(queue.IsEmpty, Is.True); } [Test] @@ -535,64 +525,64 @@ public void RandomWithHandles() { int length = 1000; int[] a = new int[length]; - Random ran = new Random(6754); + Random ran = new(6754); for (int i = 0; i < length; i++) { IPriorityQueueHandle h = null; queue.Add(ref h, a[i] = ran.Next()); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); } - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); Array.Sort(a); for (int i = 0; i < length / 2; i++) { - Assert.AreEqual(a[length - i - 1], queue.DeleteMax()); - Assert.IsTrue(queue.Check()); - Assert.AreEqual(a[i], queue.DeleteMin()); - Assert.IsTrue(queue.Check()); + Assert.That(queue.DeleteMax(), Is.EqualTo(a[length - i - 1])); + Assert.That(queue.Check(), Is.True); + Assert.That(queue.DeleteMin(), Is.EqualTo(a[i])); + Assert.That(queue.Check(), Is.True); } - Assert.IsTrue(queue.IsEmpty); + Assert.That(queue.IsEmpty, Is.True); } [Test] public void RandomWithDeleteHandles() { - Random ran = new Random(6754); + Random ran = new(6754); int length = 1000; int[] a = new int[length]; - ArrayList shuffle = new ArrayList(length); + ArrayList shuffle = new(length); IPriorityQueueHandle[] h = new IPriorityQueueHandle[length]; for (int i = 0; i < length; i++) { shuffle.Add(i); queue.Add(ref h[i], a[i] = ran.Next()); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); } - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); shuffle.Shuffle(ran); for (int i = 0; i < length; i++) { int j = shuffle[i]; - Assert.AreEqual(a[j], queue.Delete(h[j])); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Delete(h[j]), Is.EqualTo(a[j])); + Assert.That(queue.Check(), Is.True); } - Assert.IsTrue(queue.IsEmpty); + Assert.That(queue.IsEmpty, Is.True); } [Test] public void RandomIndexing() { - Random ran = new Random(6754); + Random ran = new(6754); int length = 1000; int[] a = new int[length]; int[] b = new int[length]; - ArrayList shuffle = new ArrayList(length); + ArrayList shuffle = new(length); IPriorityQueueHandle[] h = new IPriorityQueueHandle[length]; for (int i = 0; i < length; i++) @@ -600,18 +590,18 @@ public void RandomIndexing() shuffle.Add(i); queue.Add(ref h[i], a[i] = ran.Next()); b[i] = ran.Next(); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); } - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); shuffle.Shuffle(ran); for (int i = 0; i < length; i++) { int j = shuffle[i]; - Assert.AreEqual(a[j], queue[h[j]]); + Assert.That(queue[h[j]], Is.EqualTo(a[j])); queue[h[j]] = b[j]; - Assert.AreEqual(b[j], queue[h[j]]); - Assert.IsTrue(queue.Check()); + Assert.That(queue[h[j]], Is.EqualTo(b[j])); + Assert.That(queue.Check(), Is.True); } } @@ -622,26 +612,26 @@ public void RandomDuplicates() { int length = 1000; int[] a = new int[length]; - Random ran = new Random(6754); + Random ran = new(6754); for (int i = 0; i < length; i++) { queue.Add(a[i] = ran.Next(3, 13)); } - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); Array.Sort(a); for (int i = 0; i < length / 2; i++) { - Assert.AreEqual(a[i], queue.DeleteMin()); - Assert.IsTrue(queue.Check()); - Assert.AreEqual(a[length - i - 1], _ = queue.DeleteMax()); - Assert.IsTrue(queue.Check()); + Assert.That(queue.DeleteMin(), Is.EqualTo(a[i])); + Assert.That(queue.Check(), Is.True); + Assert.That(_ = queue.DeleteMax(), Is.EqualTo(a[length - i - 1])); + Assert.That(queue.Check(), Is.True); } - Assert.IsTrue(queue.IsEmpty); + Assert.That(queue.IsEmpty, Is.True); } @@ -650,26 +640,26 @@ public void AddAll() { int length = 1000; int[] a = new int[length]; - Random ran = new Random(6754); + Random ran = new(6754); - LinkedList lst = new LinkedList(); + LinkedList lst = new(); for (int i = 0; i < length; i++) { lst.Add(a[i] = ran.Next()); } queue.AddAll(lst); - Assert.IsTrue(queue.Check()); + Assert.That(queue.Check(), Is.True); Array.Sort(a); for (int i = 0; i < length / 2; i++) { - Assert.AreEqual(a[length - i - 1], queue.DeleteMax()); - Assert.IsTrue(queue.Check()); - Assert.AreEqual(a[i], queue.DeleteMin()); - Assert.IsTrue(queue.Check()); + Assert.That(queue.DeleteMax(), Is.EqualTo(a[length - i - 1])); + Assert.That(queue.Check(), Is.True); + Assert.That(queue.DeleteMin(), Is.EqualTo(a[i])); + Assert.That(queue.Check(), Is.True); } - Assert.IsTrue(queue.IsEmpty); + Assert.That(queue.IsEmpty, Is.True); } @@ -687,21 +677,21 @@ public void Bug20130208() // Remove(); q.DeleteMin(); // XAddMaxReplace(9, 2); - q.Add(ref h2, Double.MaxValue); + q.Add(ref h2, double.MaxValue); q[h2] = 9; // XAddMaxReplace(32, 4); - q.Add(ref h4, Double.MaxValue); + q.Add(ref h4, double.MaxValue); q[h4] = 32; // XAddMaxReplace(44, 7); - q.Add(ref h7, Double.MaxValue); + q.Add(ref h7, double.MaxValue); q[h7] = 44; // Remove(); q.DeleteMin(); // XAddMaxReplace(0, 5); - q.Add(ref h5, Double.MaxValue); + q.Add(ref h5, double.MaxValue); q[h5] = 0; // Internally inconsistent data structure already now - Assert.IsTrue(q.Check()); + Assert.That(q.Check(), Is.True); } [Test] @@ -714,8 +704,8 @@ public void Bug20130208Case3() q.Add(ref topRight, 30); q.Add(25); q[topRight] = 10; - Assert.IsTrue(q.Check()); - Assert.IsTrue(q.FindMax() == 25); + Assert.That(q.Check(), Is.True); + Assert.That(q.FindMax(), Is.EqualTo(25)); } [Test] @@ -729,8 +719,8 @@ public void Bug20130208Case4() q.Add(24); q.Add(26); q[topRight] = 10; - Assert.IsTrue(q.Check()); - Assert.IsTrue(q.FindMax() == 26); + Assert.That(q.Check(), Is.True); + Assert.That(q.FindMax(), Is.EqualTo(26)); } [Test] @@ -745,8 +735,8 @@ public void Bug20130208Case5a() q.Add(26); q.Add(28); q[topRight] = 10; - Assert.IsTrue(q.Check()); - Assert.IsTrue(q.FindMax() == 28); + Assert.That(q.Check(), Is.True); + Assert.That(q.FindMax(), Is.EqualTo(28)); } [Test] @@ -761,8 +751,8 @@ public void Bug20130208Case5b() q.Add(28); q.Add(26); q[topRight] = 10; - Assert.IsTrue(q.Check()); - Assert.IsTrue(q.FindMax() == 28); + Assert.That(q.Check(), Is.True); + Assert.That(q.FindMax(), Is.EqualTo(28)); } [Test] @@ -778,8 +768,8 @@ public void Bug20130208Case6a() q.Add(23); q.Add(28); q[topRight] = 10; - Assert.IsTrue(q.Check()); - Assert.IsTrue(q.FindMax() == 28); + Assert.That(q.Check(), Is.True); + Assert.That(q.FindMax(), Is.EqualTo(28)); } [Test] @@ -795,8 +785,8 @@ public void Bug20130208Case6b() q.Add(23); q.Add(26); q[topRight] = 10; - Assert.IsTrue(q.Check()); - Assert.IsTrue(q.FindMax() == 28); + Assert.That(q.Check(), Is.True); + Assert.That(q.FindMax(), Is.EqualTo(28)); } } diff --git a/C5.Tests/IReadOnlyListTests.cs b/C5.Tests/IReadOnlyListTests.cs deleted file mode 100644 index 5fa847d8..00000000 --- a/C5.Tests/IReadOnlyListTests.cs +++ /dev/null @@ -1,21 +0,0 @@ -// This file is part of the C5 Generic Collection Library for C# and CLI -// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. - -using NUnit.Framework; -using System.Collections.Generic; - -namespace C5.Tests -{ - [TestFixture] - public class IReadOnlyListTests - { - [Test] - public void ArrayList_Implements_IReadOnlyList() - { - var list = new ArrayList { 0, 1, 2, 3, 4 } as IReadOnlyList; - - Assert.AreEqual(5, list.Count); - Assert.AreEqual(2, list[2]); - } - } -} diff --git a/C5.Tests/InterfacesTest.cs b/C5.Tests/InterfacesTest.cs index e42566c4..91abba2a 100644 --- a/C5.Tests/InterfacesTest.cs +++ b/C5.Tests/InterfacesTest.cs @@ -13,43 +13,49 @@ public class ICollectionsTests { public void TryC5Coll(ICollection coll) { - Assert.AreEqual(0, coll.Count); - double[] arr = { }; + Assert.That(coll, Is.Empty); + double[] arr = []; coll.CopyTo(arr, 0); - Assert.IsFalse(coll.IsReadOnly); + Assert.That(coll.IsReadOnly, Is.False); coll.Add(2.3); coll.Add(3.2); - Assert.AreEqual(2, coll.Count); - Assert.IsTrue(coll.Contains(2.3)); - Assert.IsFalse(coll.Contains(3.1)); - Assert.IsFalse(coll.Remove(3.1)); - Assert.IsTrue(coll.Remove(3.2)); - Assert.IsFalse(coll.Contains(3.1)); - Assert.AreEqual(1, coll.Count); + Assert.That(coll, Has.Count.EqualTo(2)); + Assert.Multiple(() => + { + Assert.That(coll.Contains(2.3), Is.True); + Assert.That(coll.Contains(3.1), Is.False); + Assert.That(coll.Remove(3.1), Is.False); + Assert.That(coll.Remove(3.2), Is.True); + }); + Assert.That(coll.Contains(3.1), Is.False); + Assert.That(coll, Has.Count.EqualTo(1)); coll.Clear(); - Assert.AreEqual(0, coll.Count); - Assert.IsFalse(coll.Remove(3.1)); + Assert.That(coll, Is.Empty); + Assert.That(coll.Remove(3.1), Is.False); } public void TrySCGColl(SCG.ICollection coll) { // All members of SCG.ICollection - Assert.AreEqual(0, coll.Count); - double[] arr = { }; + Assert.That(coll, Is.Empty); + double[] arr = []; coll.CopyTo(arr, 0); - Assert.IsFalse(coll.IsReadOnly); + Assert.That(coll.IsReadOnly, Is.False); coll.Add(2.3); coll.Add(3.2); - Assert.AreEqual(2, coll.Count); - Assert.IsTrue(coll.Contains(2.3)); - Assert.IsFalse(coll.Contains(3.1)); - Assert.IsFalse(coll.Remove(3.1)); - Assert.IsTrue(coll.Remove(3.2)); - Assert.IsFalse(coll.Contains(3.1)); - Assert.AreEqual(1, coll.Count); + Assert.That(coll, Has.Count.EqualTo(2)); + Assert.Multiple(() => + { + Assert.That(coll.Contains(2.3), Is.True); + Assert.That(coll.Contains(3.1), Is.False); + Assert.That(coll.Remove(3.1), Is.False); + Assert.That(coll.Remove(3.2), Is.True); + }); + Assert.That(coll.Contains(3.1), Is.False); + Assert.That(coll, Has.Count.EqualTo(1)); coll.Clear(); - Assert.AreEqual(0, coll.Count); - Assert.IsFalse(coll.Remove(3.1)); + Assert.That(coll, Is.Empty); + Assert.That(coll.Remove(3.1), Is.False); } public void TryBothColl(ICollection coll) @@ -86,51 +92,75 @@ private class C : B { } public void TrySCIList(System.Collections.IList list) { // Should be called with a C5.IList which is not a WrappedArray - Assert.AreEqual(0, list.Count); - list.CopyTo(new A[0], 0); - list.CopyTo(new B[0], 0); - list.CopyTo(new C[0], 0); - Assert.IsTrue(!list.IsFixedSize); - Assert.IsFalse(list.IsReadOnly); - Assert.IsFalse(list.IsSynchronized); - Assert.AreNotEqual(null, list.SyncRoot); - Object b1 = new B(), b2 = new B(), c1 = new C(), c2 = new C(); - Assert.AreEqual(0, list.Add(b1)); - Assert.AreEqual(1, list.Add(c1)); - Assert.AreEqual(2, list.Count); - Assert.IsTrue(list.Contains(c1)); - Assert.IsFalse(list.Contains(b2)); + Assert.That(list, Is.Empty); + list.CopyTo(Array.Empty(), 0); + list.CopyTo(Array.Empty(), 0); + list.CopyTo(Array.Empty(), 0); + Assert.Multiple(() => + { + Assert.That(!list.IsFixedSize, Is.True); + Assert.That(list.IsReadOnly, Is.False); + Assert.That(list.IsSynchronized, Is.False); + Assert.That(list.SyncRoot, Is.Not.EqualTo(null)); + }); + object b1 = new B(), b2 = new B(), c1 = new C(), c2 = new C(); + Assert.Multiple(() => + { + Assert.That(list.Add(b1), Is.EqualTo(0)); + Assert.That(list.Add(c1), Is.EqualTo(1)); + Assert.That(list, Has.Count.EqualTo(2)); + }); + Assert.Multiple(() => + { + Assert.That(list.Contains(c1), Is.True); + Assert.That(list.Contains(b2), Is.False); + }); list[0] = b2; - Assert.AreEqual(b2, list[0]); + Assert.That(list[0], Is.EqualTo(b2)); list[1] = c2; - Assert.AreEqual(c2, list[1]); - Assert.IsTrue(list.Contains(b2)); - Assert.IsTrue(list.Contains(c2)); + Assert.Multiple(() => + { + Assert.That(list[1], Is.EqualTo(c2)); + Assert.That(list.Contains(b2), Is.True); + Assert.That(list.Contains(c2), Is.True); + }); Array arrA = new A[2], arrB = new B[2]; list.CopyTo(arrA, 0); list.CopyTo(arrB, 0); - Assert.AreEqual(b2, arrA.GetValue(0)); - Assert.AreEqual(b2, arrB.GetValue(0)); - Assert.AreEqual(c2, arrA.GetValue(1)); - Assert.AreEqual(c2, arrB.GetValue(1)); - Assert.AreEqual(0, list.IndexOf(b2)); - Assert.AreEqual(-1, list.IndexOf(b1)); + Assert.Multiple(() => + { + Assert.That(arrA.GetValue(0), Is.EqualTo(b2)); + Assert.That(arrB.GetValue(0), Is.EqualTo(b2)); + Assert.That(arrA.GetValue(1), Is.EqualTo(c2)); + Assert.That(arrB.GetValue(1), Is.EqualTo(c2)); + Assert.That(list.IndexOf(b2), Is.EqualTo(0)); + Assert.That(list.IndexOf(b1), Is.EqualTo(-1)); + }); list.Remove(b1); list.Remove(b2); - Assert.IsFalse(list.Contains(b2)); - Assert.AreEqual(1, list.Count); // Contains c2 only + Assert.Multiple(() => + { + Assert.That(list.Contains(b2), Is.False); + Assert.That(list, Has.Count.EqualTo(1)); // Contains c2 only + }); list.Insert(0, b2); list.Insert(2, b1); - Assert.AreEqual(b2, list[0]); - Assert.AreEqual(c2, list[1]); - Assert.AreEqual(b1, list[2]); + Assert.Multiple(() => + { + Assert.That(list[0], Is.EqualTo(b2)); + Assert.That(list[1], Is.EqualTo(c2)); + Assert.That(list[2], Is.EqualTo(b1)); + }); list.Remove(c2); - Assert.AreEqual(b2, list[0]); - Assert.AreEqual(b1, list[1]); + Assert.Multiple(() => + { + Assert.That(list[0], Is.EqualTo(b2)); + Assert.That(list[1], Is.EqualTo(b1)); + }); list.RemoveAt(1); - Assert.AreEqual(b2, list[0]); + Assert.That(list[0], Is.EqualTo(b2)); list.Clear(); - Assert.AreEqual(0, list.Count); + Assert.That(list, Is.Empty); list.Remove(b1); } @@ -146,83 +176,104 @@ public void Test1() [Test] public void TryWrappedArrayAsSCIList1() { - B[] myarray = new B[] { new B(), new B(), new C() }; + B[] myarray = [new B(), new B(), new C()]; System.Collections.IList list = new WrappedArray(myarray); // Should be called with a three-element WrappedArray - Assert.AreEqual(3, list.Count); - Assert.IsTrue(list.IsFixedSize); - Assert.IsFalse(list.IsSynchronized); - Assert.AreNotEqual(null, list.SyncRoot); - Assert.AreEqual(myarray.SyncRoot, list.SyncRoot); - Object b1 = new B(), b2 = new B(), c1 = new C(), c2 = new C(); + Assert.That(list, Has.Count.EqualTo(3)); + Assert.Multiple(() => + { + Assert.That(list.IsFixedSize, Is.True); + Assert.That(list.IsSynchronized, Is.False); + Assert.That(list.SyncRoot, Is.Not.EqualTo(null)); + }); + Assert.That(list.SyncRoot, Is.EqualTo(myarray.SyncRoot)); + object b1 = new B(), b2 = new B(), c1 = new C(), c2 = new C(); list[0] = b2; - Assert.AreEqual(b2, list[0]); + Assert.That(list[0], Is.EqualTo(b2)); list[1] = c2; - Assert.AreEqual(c2, list[1]); - Assert.IsTrue(list.Contains(b2)); - Assert.IsTrue(list.Contains(c2)); + Assert.Multiple(() => + { + Assert.That(list[1], Is.EqualTo(c2)); + Assert.That(list.Contains(b2), Is.True); + Assert.That(list.Contains(c2), Is.True); + }); Array arrA = new A[3], arrB = new B[3]; list.CopyTo(arrA, 0); list.CopyTo(arrB, 0); - Assert.AreEqual(b2, arrA.GetValue(0)); - Assert.AreEqual(b2, arrB.GetValue(0)); - Assert.AreEqual(c2, arrA.GetValue(1)); - Assert.AreEqual(c2, arrB.GetValue(1)); - Assert.AreEqual(0, list.IndexOf(b2)); - Assert.AreEqual(-1, list.IndexOf(b1)); - Assert.AreEqual(-1, list.IndexOf(c1)); - Assert.IsFalse(list.Contains(b1)); - Assert.IsFalse(list.Contains(c1)); + Assert.Multiple(() => + { + Assert.That(arrA.GetValue(0), Is.EqualTo(b2)); + Assert.That(arrB.GetValue(0), Is.EqualTo(b2)); + Assert.That(arrA.GetValue(1), Is.EqualTo(c2)); + Assert.That(arrB.GetValue(1), Is.EqualTo(c2)); + Assert.That(list.IndexOf(b2), Is.EqualTo(0)); + Assert.That(list.IndexOf(b1), Is.EqualTo(-1)); + Assert.That(list.IndexOf(c1), Is.EqualTo(-1)); + Assert.That(list.Contains(b1), Is.False); + Assert.That(list.Contains(c1), Is.False); + }); } [Test] public void TryWrappedArrayAsSCIList2() { - B[] myarray = new B[] { }; + B[] myarray = []; System.Collections.IList list = new WrappedArray(myarray); // Should be called with an empty WrappedArray - Assert.AreEqual(0, list.Count); - list.CopyTo(new A[0], 0); - list.CopyTo(new B[0], 0); - list.CopyTo(new C[0], 0); - Assert.IsFalse(list.IsSynchronized); - Assert.AreNotEqual(null, list.SyncRoot); - Object b1 = new B(), b2 = new B(), c1 = new C(), c2 = new C(); - Assert.IsFalse(list.Contains(b2)); - Assert.IsFalse(list.Contains(c2)); - Assert.AreEqual(-1, list.IndexOf(b1)); - Assert.AreEqual(-1, list.IndexOf(c1)); + Assert.That(list, Is.Empty); + list.CopyTo(Array.Empty(), 0); + list.CopyTo(Array.Empty(), 0); + list.CopyTo(Array.Empty(), 0); + Assert.Multiple(() => + { + Assert.That(list.IsSynchronized, Is.False); + Assert.That(list.SyncRoot, Is.Not.EqualTo(null)); + }); + object b1 = new B(), b2 = new B(), c1 = new C(), c2 = new C(); + Assert.Multiple(() => + { + Assert.That(list.Contains(b2), Is.False); + Assert.That(list.Contains(c2), Is.False); + Assert.That(list.IndexOf(b1), Is.EqualTo(-1)); + Assert.That(list.IndexOf(c1), Is.EqualTo(-1)); + }); } [Test] public void TryGuardedListAsSCIList1() { - B b1_ = new B(), b2_ = new B(); - C c1_ = new C(), c2_ = new C(); - ArrayList mylist = new ArrayList(); - mylist.AddAll(new B[] { b1_, b2_, c1_ }); + B b1_ = new(), b2_ = new(); + C c1_ = new(), c2_ = new(); + ArrayList mylist = new(); + mylist.AddAll([b1_, b2_, c1_]); System.Collections.IList list = new GuardedList(mylist); - Object b1 = b1_, b2 = b2_, c1 = c1_, c2 = c2_; + object b1 = b1_, b2 = b2_, c1 = c1_, c2 = c2_; // Should be called with a three-element GuardedList - Assert.AreEqual(3, list.Count); - Assert.IsTrue(list.IsFixedSize); - Assert.IsTrue(list.IsReadOnly); - Assert.IsFalse(list.IsSynchronized); - Assert.AreNotEqual(null, list.SyncRoot); - Assert.AreEqual(list.SyncRoot, ((System.Collections.IList)mylist).SyncRoot); - Assert.IsTrue(list.Contains(b1)); - Assert.IsTrue(list.Contains(b2)); - Assert.IsTrue(list.Contains(c1)); - Assert.IsFalse(list.Contains(c2)); + Assert.That(list, Has.Count.EqualTo(3)); + Assert.Multiple(() => + { + Assert.That(list.IsFixedSize, Is.True); + Assert.That(list.IsReadOnly, Is.True); + Assert.That(list.IsSynchronized, Is.False); + Assert.That(list.SyncRoot, Is.Not.EqualTo(null)); + Assert.That(((System.Collections.IList)mylist).SyncRoot, Is.EqualTo(list.SyncRoot)); + Assert.That(list.Contains(b1), Is.True); + Assert.That(list.Contains(b2), Is.True); + Assert.That(list.Contains(c1), Is.True); + Assert.That(list.Contains(c2), Is.False); + }); Array arrA = new A[3], arrB = new B[3]; list.CopyTo(arrA, 0); list.CopyTo(arrB, 0); - Assert.AreEqual(b1, arrA.GetValue(0)); - Assert.AreEqual(b1, arrB.GetValue(0)); - Assert.AreEqual(b2, arrA.GetValue(1)); - Assert.AreEqual(b2, arrB.GetValue(1)); - Assert.AreEqual(0, list.IndexOf(b1)); - Assert.AreEqual(-1, list.IndexOf(c2)); + Assert.Multiple(() => + { + Assert.That(arrA.GetValue(0), Is.EqualTo(b1)); + Assert.That(arrB.GetValue(0), Is.EqualTo(b1)); + Assert.That(arrA.GetValue(1), Is.EqualTo(b2)); + Assert.That(arrB.GetValue(1), Is.EqualTo(b2)); + Assert.That(list.IndexOf(b1), Is.EqualTo(0)); + Assert.That(list.IndexOf(c2), Is.EqualTo(-1)); + }); } [Test] @@ -230,109 +281,139 @@ public void TryGuardedListAsSCIList2() { System.Collections.IList list = new GuardedList(new ArrayList()); // Should be called with an empty GuardedList - Assert.AreEqual(0, list.Count); - list.CopyTo(new A[0], 0); - list.CopyTo(new B[0], 0); - list.CopyTo(new C[0], 0); - Assert.IsFalse(list.IsSynchronized); - Assert.AreNotEqual(null, list.SyncRoot); - Object b1 = new B(), b2 = new B(), c1 = new C(), c2 = new C(); - Assert.IsFalse(list.Contains(b2)); - Assert.IsFalse(list.Contains(c2)); - Assert.AreEqual(-1, list.IndexOf(b1)); - Assert.AreEqual(-1, list.IndexOf(c1)); + Assert.That(list, Is.Empty); + list.CopyTo(Array.Empty(), 0); + list.CopyTo(Array.Empty(), 0); + list.CopyTo(Array.Empty(), 0); + Assert.Multiple(() => + { + Assert.That(list.IsSynchronized, Is.False); + Assert.That(list.SyncRoot, Is.Not.EqualTo(null)); + }); + object b1 = new B(), b2 = new B(), c1 = new C(), c2 = new C(); + Assert.Multiple(() => + { + Assert.That(list.Contains(b2), Is.False); + Assert.That(list.Contains(c2), Is.False); + Assert.That(list.IndexOf(b1), Is.EqualTo(-1)); + Assert.That(list.IndexOf(c1), Is.EqualTo(-1)); + }); } [Test] public void TryViewOfGuardedListAsSCIList1() { - B b1_ = new B(), b2_ = new B(); - C c1_ = new C(), c2_ = new C(); - ArrayList mylist = new ArrayList(); - mylist.AddAll(new B[] { new B(), b1_, b2_, c1_, new B() }); + B b1_ = new(), b2_ = new(); + C c1_ = new(), c2_ = new(); + ArrayList mylist = new(); + mylist.AddAll([new B(), b1_, b2_, c1_, new B()]); System.Collections.IList list = new GuardedList(mylist).View(1, 3); - Object b1 = b1_, b2 = b2_, c1 = c1_, c2 = c2_; + object b1 = b1_, b2 = b2_, c1 = c1_, c2 = c2_; // Should be called with a three-element view of a GuardedList - Assert.AreEqual(3, list.Count); - Assert.IsTrue(list.IsFixedSize); - Assert.IsTrue(list.IsReadOnly); - Assert.IsFalse(list.IsSynchronized); - Assert.AreNotEqual(null, list.SyncRoot); - Assert.AreEqual(list.SyncRoot, ((System.Collections.IList)mylist).SyncRoot); - Assert.IsTrue(list.Contains(b1)); - Assert.IsTrue(list.Contains(b2)); - Assert.IsTrue(list.Contains(c1)); - Assert.IsFalse(list.Contains(c2)); + Assert.That(list, Has.Count.EqualTo(3)); + Assert.Multiple(() => + { + Assert.That(list.IsFixedSize, Is.True); + Assert.That(list.IsReadOnly, Is.True); + Assert.That(list.IsSynchronized, Is.False); + Assert.That(list.SyncRoot, Is.Not.EqualTo(null)); + Assert.That(((System.Collections.IList)mylist).SyncRoot, Is.EqualTo(list.SyncRoot)); + Assert.That(list.Contains(b1), Is.True); + Assert.That(list.Contains(b2), Is.True); + Assert.That(list.Contains(c1), Is.True); + Assert.That(list.Contains(c2), Is.False); + }); Array arrA = new A[3], arrB = new B[3]; list.CopyTo(arrA, 0); list.CopyTo(arrB, 0); - Assert.AreEqual(b1, arrA.GetValue(0)); - Assert.AreEqual(b1, arrB.GetValue(0)); - Assert.AreEqual(b2, arrA.GetValue(1)); - Assert.AreEqual(b2, arrB.GetValue(1)); - Assert.AreEqual(0, list.IndexOf(b1)); - Assert.AreEqual(-1, list.IndexOf(c2)); + Assert.Multiple(() => + { + Assert.That(arrA.GetValue(0), Is.EqualTo(b1)); + Assert.That(arrB.GetValue(0), Is.EqualTo(b1)); + Assert.That(arrA.GetValue(1), Is.EqualTo(b2)); + Assert.That(arrB.GetValue(1), Is.EqualTo(b2)); + Assert.That(list.IndexOf(b1), Is.EqualTo(0)); + Assert.That(list.IndexOf(c2), Is.EqualTo(-1)); + }); } [Test] public void TryViewOfGuardedListAsSCIList2() { System.Collections.IList list = new GuardedList(new ArrayList()).View(0, 0); - Assert.AreEqual(0, list.Count); - list.CopyTo(new A[0], 0); - list.CopyTo(new B[0], 0); - list.CopyTo(new C[0], 0); - Assert.IsFalse(list.IsSynchronized); - Assert.AreNotEqual(null, list.SyncRoot); - Object b1 = new B(), b2 = new B(), c1 = new C(), c2 = new C(); - Assert.IsFalse(list.Contains(b2)); - Assert.IsFalse(list.Contains(c2)); - Assert.AreEqual(-1, list.IndexOf(b1)); - Assert.AreEqual(-1, list.IndexOf(c1)); + Assert.That(list, Is.Empty); + list.CopyTo(Array.Empty(), 0); + list.CopyTo(Array.Empty(), 0); + list.CopyTo(Array.Empty(), 0); + Assert.Multiple(() => + { + Assert.That(list.IsSynchronized, Is.False); + Assert.That(list.SyncRoot, Is.Not.EqualTo(null)); + }); + object b1 = new B(), b2 = new B(), c1 = new C(), c2 = new C(); + Assert.Multiple(() => + { + Assert.That(list.Contains(b2), Is.False); + Assert.That(list.Contains(c2), Is.False); + Assert.That(list.IndexOf(b1), Is.EqualTo(-1)); + Assert.That(list.IndexOf(c1), Is.EqualTo(-1)); + }); } private void TryListViewAsSCIList1(IList mylist) { - B b1_ = new B(), b2_ = new B(); - C c1_ = new C(), c2_ = new C(); - mylist.AddAll(new B[] { new B(), b1_, b2_, c1_, new B() }); + B b1_ = new(), b2_ = new(); + C c1_ = new(), c2_ = new(); + mylist.AddAll([new B(), b1_, b2_, c1_, new B()]); System.Collections.IList list = mylist.View(1, 3); - Object b1 = b1_, b2 = b2_, c1 = c1_, c2 = c2_; + object b1 = b1_, b2 = b2_, c1 = c1_, c2 = c2_; // Should be called with a three-element view on ArrayList - Assert.AreEqual(3, list.Count); - Assert.IsFalse(list.IsSynchronized); - Assert.AreNotEqual(null, list.SyncRoot); - Assert.AreEqual(list.SyncRoot, mylist.SyncRoot); - Assert.IsTrue(list.Contains(b1)); - Assert.IsTrue(list.Contains(b2)); - Assert.IsTrue(list.Contains(c1)); - Assert.IsFalse(list.Contains(c2)); + Assert.That(list, Has.Count.EqualTo(3)); + Assert.Multiple(() => + { + Assert.That(list.IsSynchronized, Is.False); + Assert.That(list.SyncRoot, Is.Not.EqualTo(null)); + Assert.That(mylist.SyncRoot, Is.EqualTo(list.SyncRoot)); + Assert.That(list.Contains(b1), Is.True); + Assert.That(list.Contains(b2), Is.True); + Assert.That(list.Contains(c1), Is.True); + Assert.That(list.Contains(c2), Is.False); + }); Array arrA = new A[3], arrB = new B[3]; list.CopyTo(arrA, 0); list.CopyTo(arrB, 0); - Assert.AreEqual(b1, arrA.GetValue(0)); - Assert.AreEqual(b1, arrB.GetValue(0)); - Assert.AreEqual(b2, arrA.GetValue(1)); - Assert.AreEqual(b2, arrB.GetValue(1)); - Assert.AreEqual(0, list.IndexOf(b1)); - Assert.AreEqual(-1, list.IndexOf(c2)); + Assert.Multiple(() => + { + Assert.That(arrA.GetValue(0), Is.EqualTo(b1)); + Assert.That(arrB.GetValue(0), Is.EqualTo(b1)); + Assert.That(arrA.GetValue(1), Is.EqualTo(b2)); + Assert.That(arrB.GetValue(1), Is.EqualTo(b2)); + Assert.That(list.IndexOf(b1), Is.EqualTo(0)); + Assert.That(list.IndexOf(c2), Is.EqualTo(-1)); + }); } private void TryListViewAsSCIList2(IList mylist) { System.Collections.IList list = mylist.View(0, 0); - Assert.AreEqual(0, list.Count); - list.CopyTo(new A[0], 0); - list.CopyTo(new B[0], 0); - list.CopyTo(new C[0], 0); - Assert.IsFalse(list.IsSynchronized); - Assert.AreNotEqual(null, list.SyncRoot); - Assert.AreEqual(list.SyncRoot, mylist.SyncRoot); - Object b1 = new B(), b2 = new B(), c1 = new C(), c2 = new C(); - Assert.IsFalse(list.Contains(b2)); - Assert.IsFalse(list.Contains(c2)); - Assert.AreEqual(-1, list.IndexOf(b1)); - Assert.AreEqual(-1, list.IndexOf(c1)); + Assert.That(list, Is.Empty); + list.CopyTo(Array.Empty(), 0); + list.CopyTo(Array.Empty(), 0); + list.CopyTo(Array.Empty(), 0); + Assert.Multiple(() => + { + Assert.That(list.IsSynchronized, Is.False); + Assert.That(list.SyncRoot, Is.Not.EqualTo(null)); + Assert.That(mylist.SyncRoot, Is.EqualTo(list.SyncRoot)); + }); + object b1 = new B(), b2 = new B(), c1 = new C(), c2 = new C(); + Assert.Multiple(() => + { + Assert.That(list.Contains(b2), Is.False); + Assert.That(list.Contains(c2), Is.False); + Assert.That(list.IndexOf(b1), Is.EqualTo(-1)); + Assert.That(list.IndexOf(c1), Is.EqualTo(-1)); + }); } [Test] @@ -366,7 +447,7 @@ public void TryHashedLinkedListViewAsSCIList() [Test] public void TryGuardedViewAsSCIList() { - ArrayList mylist = new ArrayList(); + ArrayList mylist = new(); TryListViewAsSCIList2(new GuardedList(mylist)); } } @@ -376,48 +457,54 @@ public class IDictionaryTests { public void TryDictionary(IDictionary dict) { - Assert.AreEqual(0, dict.Count); - Assert.IsTrue(dict.IsEmpty); - Assert.IsFalse(dict.IsReadOnly); - System.Collections.Generic.KeyValuePair[] arr = { }; + Assert.That(dict, Is.Empty); + Assert.Multiple(() => + { + Assert.That(dict.IsEmpty, Is.True); + Assert.That(dict.IsReadOnly, Is.False); + }); + System.Collections.Generic.KeyValuePair[] arr = []; dict.CopyTo(arr, 0); dict["R"] = "A"; dict["S"] = "B"; dict["T"] = "C"; - Assert.IsTrue(dict.Update("R", "A1")); - Assert.AreEqual("A1", dict["R"]); - - Assert.IsFalse(dict.Update("U", "D1")); - Assert.IsFalse(dict.Contains("U")); - - Assert.IsTrue(dict.Update("R", "A2", out string old)); - Assert.AreEqual("A2", dict["R"]); - Assert.AreEqual("A1", old); - - Assert.IsFalse(dict.Update("U", "D2", out old)); - Assert.AreEqual(null, old); - Assert.IsFalse(dict.Contains("U")); - - Assert.IsTrue(dict.UpdateOrAdd("R", "A3")); - Assert.AreEqual("A3", dict["R"]); - - Assert.IsFalse(dict.UpdateOrAdd("U", "D3")); - Assert.IsTrue(dict.Contains("U")); - Assert.AreEqual("D3", dict["U"]); - - Assert.IsTrue(dict.UpdateOrAdd("R", "A4", out old)); - Assert.AreEqual("A4", dict["R"]); - Assert.AreEqual("A3", old); - - Assert.IsTrue(dict.UpdateOrAdd("U", "D4", out old)); - Assert.IsTrue(dict.Contains("U")); - Assert.AreEqual("D4", dict["U"]); - Assert.AreEqual("D3", old); - - Assert.IsFalse(dict.UpdateOrAdd("V", "E1", out old)); - Assert.IsTrue(dict.Contains("V")); - Assert.AreEqual("E1", dict["V"]); - Assert.AreEqual(null, old); + Assert.Multiple(() => + { + Assert.That(dict.Update("R", "A1"), Is.True); + Assert.That(dict["R"], Is.EqualTo("A1")); + + Assert.That(dict.Update("U", "D1"), Is.False); + Assert.That(dict.Contains("U"), Is.False); + + Assert.That(dict.Update("R", "A2", out string old), Is.True); + Assert.That(dict["R"], Is.EqualTo("A2")); + Assert.That(old, Is.EqualTo("A1")); + + Assert.That(dict.Update("U", "D2", out old), Is.False); + Assert.That(old, Is.EqualTo(null)); + Assert.That(dict.Contains("U"), Is.False); + + Assert.That(dict.UpdateOrAdd("R", "A3"), Is.True); + Assert.That(dict["R"], Is.EqualTo("A3")); + + Assert.That(dict.UpdateOrAdd("U", "D3"), Is.False); + Assert.That(dict.Contains("U"), Is.True); + Assert.That(dict["U"], Is.EqualTo("D3")); + + Assert.That(dict.UpdateOrAdd("R", "A4", out old), Is.True); + Assert.That(dict["R"], Is.EqualTo("A4")); + Assert.That(old, Is.EqualTo("A3")); + + Assert.That(dict.UpdateOrAdd("U", "D4", out old), Is.True); + Assert.That(dict.Contains("U"), Is.True); + Assert.That(dict["U"], Is.EqualTo("D4")); + Assert.That(old, Is.EqualTo("D3")); + + Assert.That(dict.UpdateOrAdd("V", "E1", out old), Is.False); + Assert.That(dict.Contains("V"), Is.True); + Assert.That(dict["V"], Is.EqualTo("E1")); + Assert.That(old, Is.EqualTo(null)); + }); } [Test] diff --git a/C5.Tests/KeyValuePairTests.cs b/C5.Tests/KeyValuePairTests.cs deleted file mode 100644 index a03e5e99..00000000 --- a/C5.Tests/KeyValuePairTests.cs +++ /dev/null @@ -1,20 +0,0 @@ -// This file is part of the C5 Generic Collection Library for C# and CLI -// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. - -using NUnit.Framework; - -namespace C5.Tests -{ - [TestFixture] - public class KeyValuePairTests - { - [Test] - public void Create() - { - var p1 = new System.Collections.Generic.KeyValuePair(42, "The answer"); - var p2 = System.Collections.Generic.KeyValuePair.Create(42, "The answer"); - - Assert.AreEqual(p1, p2); - } - } -} diff --git a/C5.Tests/LinkedLists/HashedLinkedListTest.cs b/C5.Tests/LinkedLists/HashedLinkedListTest.cs index 83846855..7fffb4cb 100644 --- a/C5.Tests/LinkedLists/HashedLinkedListTest.cs +++ b/C5.Tests/LinkedLists/HashedLinkedListTest.cs @@ -8,32 +8,21 @@ namespace C5.Tests.linkedlists.hashed { - using CollectionOfInt = HashedLinkedList; - [TestFixture] public class GenericTesters { [Test] public void TestEvents() { - CollectionOfInt factory() { return new CollectionOfInt(TenEqualityComparer.Default); } - new C5.Tests.Templates.Events.ListTester().Test(factory); + HashedLinkedList factory() { return new HashedLinkedList(TenEqualityComparer.Default); } + new C5.Tests.Templates.Events.ListTester>().Test(factory); } - //[Test] - //public void Extensible() - //{ - // C5.Tests.Templates.Extensible.Clone.Tester(); - // C5.Tests.Templates.Extensible.Clone.ViewTester(); - // C5.Tests.Templates.Extensible.Serialization.Tester(); - // C5.Tests.Templates.Extensible.Serialization.ViewTester(); - //} - [Test] public void List() { - C5.Tests.Templates.List.Dispose.Tester(); - C5.Tests.Templates.List.SCG_IList.Tester(); + Templates.List.Dispose.Tester>(); + Templates.List.SCG_IList.Tester>(); } } @@ -66,34 +55,52 @@ public void Init() [Test] public void All() { - Assert.IsTrue(list.All(always)); - Assert.IsTrue(list.All(never)); - Assert.IsTrue(list.All(even)); + Assert.Multiple(() => + { + Assert.That(list.All(always), Is.True); + Assert.That(list.All(never), Is.True); + Assert.That(list.All(even), Is.True); + }); list.Add(8); - Assert.IsTrue(list.All(always)); - Assert.IsFalse(list.All(never)); - Assert.IsTrue(list.All(even)); + Assert.Multiple(() => + { + Assert.That(list.All(always), Is.True); + Assert.That(list.All(never), Is.False); + Assert.That(list.All(even), Is.True); + }); list.Add(5); - Assert.IsTrue(list.All(always)); - Assert.IsFalse(list.All(never)); - Assert.IsFalse(list.All(even)); + Assert.Multiple(() => + { + Assert.That(list.All(always), Is.True); + Assert.That(list.All(never), Is.False); + Assert.That(list.All(even), Is.False); + }); } [Test] public void Exists() { - Assert.IsFalse(list.Exists(always)); - Assert.IsFalse(list.Exists(never)); - Assert.IsFalse(list.Exists(even)); + Assert.Multiple(() => + { + Assert.That(list.Exists(always), Is.False); + Assert.That(list.Exists(never), Is.False); + Assert.That(list.Exists(even), Is.False); + }); list.Add(5); - Assert.IsTrue(list.Exists(always)); - Assert.IsFalse(list.Exists(never)); - Assert.IsFalse(list.Exists(even)); + Assert.Multiple(() => + { + Assert.That(list.Exists(always), Is.True); + Assert.That(list.Exists(never), Is.False); + Assert.That(list.Exists(even), Is.False); + }); list.Add(8); - Assert.IsTrue(list.Exists(always)); - Assert.IsFalse(list.Exists(never)); - Assert.IsTrue(list.Exists(even)); + Assert.Multiple(() => + { + Assert.That(list.Exists(always), Is.True); + Assert.That(list.Exists(never), Is.False); + Assert.That(list.Exists(even), Is.True); + }); } @@ -104,16 +111,16 @@ public void Apply() void a(int i) { sum = i + 10 * sum; } list.Apply(a); - Assert.AreEqual(0, sum); + Assert.That(sum, Is.EqualTo(0)); sum = 0; list.Add(5); list.Add(8); list.Add(7); list.Add(5); list.Apply(a); - Assert.AreEqual(587, sum); + Assert.That(sum, Is.EqualTo(587)); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } @@ -133,7 +140,7 @@ public void Empty() { SCG.IEnumerator e = list.GetEnumerator(); - Assert.IsFalse(e.MoveNext()); + Assert.That(e.MoveNext(), Is.False); } @@ -149,15 +156,18 @@ public void Normal() SCG.IEnumerator e = list.GetEnumerator(); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(5, e.Current); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(8, e.Current); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(10, e.Current); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(1, e.Current); - Assert.IsFalse(e.MoveNext()); + Assert.Multiple(() => + { + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(5)); + }); + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(8)); + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(10)); + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(1)); + Assert.That(e.MoveNext(), Is.False); } @@ -191,7 +201,7 @@ public void MoveNextAfterUpdate() } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } } @@ -209,12 +219,15 @@ public class Formatting [Test] public void Format() { - Assert.AreEqual("[ ]", coll.ToString()); - coll.AddAll(new int[] { -4, 28, 129, 65530 }); - Assert.AreEqual("[ -4, 28, 129, 65530 ]", coll.ToString()); - Assert.AreEqual("[ -4, 1C, 81, FFFA ]", coll.ToString(null, rad16)); - Assert.AreEqual("[ -4, 28, 129... ]", coll.ToString("L14", null)); - Assert.AreEqual("[ -4, 1C, 81... ]", coll.ToString("L14", rad16)); + Assert.That(coll.ToString(), Is.EqualTo("[ ]")); + coll.AddAll([-4, 28, 129, 65530]); + Assert.Multiple(() => + { + Assert.That(coll.ToString(), Is.EqualTo("[ -4, 28, 129, 65530 ]")); + Assert.That(coll.ToString(null, rad16), Is.EqualTo("[ -4, 1C, 81, FFFA ]")); + Assert.That(coll.ToString("L14", null), Is.EqualTo("[ -4, 28, 129... ]")); + Assert.That(coll.ToString("L14", rad16), Is.EqualTo("[ -4, 1C, 81... ]")); + }); } } @@ -237,7 +250,7 @@ public void NullEqualityComparerinConstructor1() public void Choose() { list.Add(7); - Assert.AreEqual(7, list.Choose()); + Assert.That(list.Choose(), Is.EqualTo(7)); } [Test] @@ -249,17 +262,26 @@ public void BadChoose() [Test] public void CountEtAl() { - Assert.AreEqual(0, list.Count); - Assert.IsTrue(list.IsEmpty); - Assert.IsFalse(list.AllowsDuplicates); - Assert.IsTrue(list.Add(5)); - Assert.AreEqual(1, list.Count); - Assert.IsFalse(list.IsEmpty); - Assert.IsFalse(list.Add(5)); - Assert.AreEqual(1, list.Count); - Assert.IsFalse(list.IsEmpty); - Assert.IsTrue(list.Add(8)); - Assert.AreEqual(2, list.Count); + Assert.That(list, Is.Empty); + Assert.Multiple(() => + { + Assert.That(list.IsEmpty, Is.True); + Assert.That(list.AllowsDuplicates, Is.False); + Assert.That(list.Add(5), Is.True); + Assert.That(list, Has.Count.EqualTo(1)); + }); + Assert.Multiple(() => + { + Assert.That(list.IsEmpty, Is.False); + Assert.That(list.Add(5), Is.False); + Assert.That(list, Has.Count.EqualTo(1)); + }); + Assert.Multiple(() => + { + Assert.That(list.IsEmpty, Is.False); + Assert.That(list.Add(8), Is.True); + Assert.That(list, Has.Count.EqualTo(2)); + }); } @@ -268,18 +290,21 @@ public void AddAll() { list.Add(3); list.Add(4); list.Add(5); - HashedLinkedList list2 = new HashedLinkedList(); + HashedLinkedList list2 = new(); list2.AddAll(list); - Assert.IsTrue(IC.Eq(list2, 3, 4, 5)); + Assert.That(IC.Eq(list2, 3, 4, 5), Is.True); list.AddAll(list2); - Assert.IsTrue(IC.Eq(list2, 3, 4, 5)); - Assert.IsTrue(IC.Eq(list, 3, 4, 5)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list2, 3, 4, 5), Is.True); + Assert.That(IC.Eq(list, 3, 4, 5), Is.True); + }); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } [TestFixture] @@ -296,48 +321,54 @@ public void Init() } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } [Test] public void Find() { - Assert.IsFalse(list.Find(pred, out int i)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(list.Find(pred, out i)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.IsTrue(list.Find(pred, out i)); - Assert.AreEqual(45, i); + Assert.That(list.Find(pred, out int i), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(list.Find(pred, out i), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.Multiple(() => + { + Assert.That(list.Find(pred, out i), Is.True); + Assert.That(i, Is.EqualTo(45)); + }); } [Test] public void FindLast() { - Assert.IsFalse(list.FindLast(pred, out int i)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(list.FindLast(pred, out i)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.IsTrue(list.FindLast(pred, out i)); - Assert.AreEqual(675, i); + Assert.That(list.FindLast(pred, out int i), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(list.FindLast(pred, out i), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.Multiple(() => + { + Assert.That(list.FindLast(pred, out i), Is.True); + Assert.That(i, Is.EqualTo(675)); + }); } [Test] public void FindIndex() { - Assert.IsFalse(0 <= list.FindIndex(pred)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(0 <= list.FindIndex(pred)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.AreEqual(4, list.FindIndex(pred)); + Assert.That(0 <= list.FindIndex(pred), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(0 <= list.FindIndex(pred), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.That(list.FindIndex(pred), Is.EqualTo(4)); } [Test] public void FindLastIndex() { - Assert.IsFalse(0 <= list.FindLastIndex(pred)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(0 <= list.FindLastIndex(pred)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.AreEqual(6, list.FindLastIndex(pred)); + Assert.That(0 <= list.FindLastIndex(pred), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(0 <= list.FindLastIndex(pred), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.That(list.FindLastIndex(pred), Is.EqualTo(6)); } } @@ -350,16 +381,22 @@ public class UniqueItems public void Init() { list = new HashedLinkedList(); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } [Test] public void Test() { - Assert.IsTrue(IC.SetEq(list.UniqueItems())); - Assert.IsTrue(IC.SetEq(list.ItemMultiplicities())); - list.AddAll(new int[] { 7, 9, 7 }); - Assert.IsTrue(IC.SetEq(list.UniqueItems(), 7, 9)); - Assert.IsTrue(IC.SetEq(list.ItemMultiplicities(), 7, 1, 9, 1)); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(list.UniqueItems()), Is.True); + Assert.That(IC.SetEq(list.ItemMultiplicities()), Is.True); + }); + list.AddAll([7, 9, 7]); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(list.UniqueItems(), 7, 9), Is.True); + Assert.That(IC.SetEq(list.ItemMultiplicities(), 7, 1, 9, 1), Is.True); + }); } } @@ -385,7 +422,7 @@ public void Init() [TearDown] public void Dispose() { - list = null; + list.Dispose(); } @@ -411,10 +448,10 @@ private string aeq(int[] a, params int[] b) [Test] public void ToArray() { - Assert.AreEqual("Alles klar", aeq(list.ToArray())); + Assert.That(aeq(list.ToArray()), Is.EqualTo("Alles klar")); list.Add(7); list.Add(8); - Assert.AreEqual("Alles klar", aeq(list.ToArray(), 7, 8)); + Assert.That(aeq(list.ToArray(), 7, 8), Is.EqualTo("Alles klar")); } @@ -422,19 +459,19 @@ public void ToArray() public void CopyTo() { list.CopyTo(a, 1); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009), Is.EqualTo("Alles klar")); list.Add(6); list.CopyTo(a, 2); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009), Is.EqualTo("Alles klar")); list.Add(4); list.Add(5); list.Add(9); list.CopyTo(a, 4); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 4, 5, 9, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 6, 4, 5, 9, 1008, 1009), Is.EqualTo("Alles klar")); list.Clear(); list.Add(7); list.CopyTo(a, 9); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 4, 5, 9, 1008, 7)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 6, 4, 5, 9, 1008, 7), Is.EqualTo("Alles klar")); } [Test] @@ -462,24 +499,12 @@ public void CopyToTooFar() [TestFixture] public class Sync { - private HashedLinkedList list; - - - [SetUp] - public void Init() - { - list = new HashedLinkedList(); - } - - - [TearDown] - public void Dispose() { list = null; } - - [Test] - public void Get() + public void HashedLinkedList_has_SyncRoot() { - Assert.IsNotNull(((System.Collections.IList)list).SyncRoot); + var list = new HashedLinkedList(); + + Assert.That(((System.Collections.IList)list).SyncRoot, Is.Not.Null); } } } @@ -502,43 +527,61 @@ public class Searching [Test] public void Contains() { - Assert.IsFalse(list.Contains(5)); + Assert.That(list.Contains(5), Is.False); list.Add(5); - Assert.IsTrue(list.Contains(5)); - Assert.IsFalse(list.Contains(7)); + Assert.Multiple(() => + { + Assert.That(list.Contains(5), Is.True); + Assert.That(list.Contains(7), Is.False); + }); list.Add(8); list.Add(10); - Assert.IsTrue(list.Contains(5)); - Assert.IsFalse(list.Contains(7)); - Assert.IsTrue(list.Contains(8)); - Assert.IsTrue(list.Contains(10)); + Assert.Multiple(() => + { + Assert.That(list.Contains(5), Is.True); + Assert.That(list.Contains(7), Is.False); + Assert.That(list.Contains(8), Is.True); + Assert.That(list.Contains(10), Is.True); + }); list.Remove(8); - Assert.IsTrue(list.Contains(5)); - Assert.IsFalse(list.Contains(7)); - Assert.IsFalse(list.Contains(8)); - Assert.IsTrue(list.Contains(10)); + Assert.Multiple(() => + { + Assert.That(list.Contains(5), Is.True); + Assert.That(list.Contains(7), Is.False); + Assert.That(list.Contains(8), Is.False); + Assert.That(list.Contains(10), Is.True); + }); } [Test] public void BadAdd() { - Assert.IsTrue(list.Add(5)); - Assert.IsTrue(list.Add(8)); - Assert.IsFalse(list.Add(5)); + Assert.Multiple(() => + { + Assert.That(list.Add(5), Is.True); + Assert.That(list.Add(8), Is.True); + }); + Assert.That(list.Add(5), Is.False); } [Test] public void ContainsCount() { - Assert.AreEqual(0, list.ContainsCount(5)); + Assert.That(list.ContainsCount(5), Is.EqualTo(0)); list.Add(5); - Assert.AreEqual(1, list.ContainsCount(5)); - Assert.AreEqual(0, list.ContainsCount(7)); + Assert.Multiple(() => + { + Assert.That(list.ContainsCount(5), Is.EqualTo(1)); + Assert.That(list.ContainsCount(7), Is.EqualTo(0)); + }); list.Add(8); - Assert.AreEqual(1, list.ContainsCount(5)); - Assert.AreEqual(0, list.ContainsCount(7)); - Assert.AreEqual(1, list.ContainsCount(8)); + Assert.Multiple(() => + { + Assert.That(list.ContainsCount(5), Is.EqualTo(1)); + Assert.That(list.ContainsCount(7), Is.EqualTo(0)); + Assert.That(list.ContainsCount(8), Is.EqualTo(1)); + }); } @@ -546,15 +589,21 @@ public void ContainsCount() public void RemoveAllCopies() { list.Add(5); list.Add(7); - Assert.AreEqual(1, list.ContainsCount(5)); - Assert.AreEqual(1, list.ContainsCount(7)); + Assert.Multiple(() => + { + Assert.That(list.ContainsCount(5), Is.EqualTo(1)); + Assert.That(list.ContainsCount(7), Is.EqualTo(1)); + }); list.RemoveAllCopies(5); - Assert.IsTrue(list.Check()); - Assert.AreEqual(0, list.ContainsCount(5)); - Assert.AreEqual(1, list.ContainsCount(7)); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(list.ContainsCount(5), Is.EqualTo(0)); + Assert.That(list.ContainsCount(7), Is.EqualTo(1)); + }); list.Add(5); list.Add(8); list.RemoveAllCopies(8); - Assert.IsTrue(IC.Eq(list, 7, 5)); + Assert.That(IC.Eq(list, 7, 5), Is.True); } @@ -563,73 +612,88 @@ public void FindAll() { bool f(int i) { return i % 2 == 0; } - Assert.IsTrue(list.FindAll(f).IsEmpty); + Assert.That(list.FindAll(f).IsEmpty, Is.True); list.Add(5); list.Add(8); list.Add(10); - Assert.IsTrue(((HashedLinkedList)list.FindAll(f)).Check()); - Assert.IsTrue(IC.Eq(list.FindAll(f), 8, 10)); + Assert.Multiple(() => + { + Assert.That(((HashedLinkedList)list.FindAll(f)).Check(), Is.True); + Assert.That(IC.Eq(list.FindAll(f), 8, 10), Is.True); + }); } [Test] public void ContainsAll() { - HashedLinkedList list2 = new HashedLinkedList(); + HashedLinkedList list2 = new(); - Assert.IsTrue(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.True); list2.Add(4); - Assert.IsFalse(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.False); list.Add(4); - Assert.IsTrue(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.True); list.Add(5); - Assert.IsTrue(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.True); } [Test] public void RetainAll() { - HashedLinkedList list2 = new HashedLinkedList(); + HashedLinkedList list2 = new(); list.Add(4); list.Add(5); list.Add(6); list2.Add(5); list2.Add(4); list2.Add(7); list.RetainAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 5)); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 5), Is.True); + }); list.Add(5); list.Add(4); list.Add(6); list2.Clear(); list2.Add(5); list2.Add(5); list2.Add(6); list.RetainAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 5, 6)); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 5, 6), Is.True); + }); list2.Clear(); list2.Add(7); list2.Add(8); list2.Add(9); list.RetainAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list), Is.True); } [Test] public void RemoveAll() { - HashedLinkedList list2 = new HashedLinkedList(); + HashedLinkedList list2 = new(); list.Add(4); list.Add(5); list.Add(6); list2.Add(5); list2.Add(4); list2.Add(7); list.RemoveAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 6)); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 6), Is.True); + }); list.Add(5); list.Add(4); list.Add(6); list2.Clear(); list2.Add(6); list2.Add(5); list.RemoveAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4)); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4), Is.True); + }); list2.Clear(); list2.Add(7); list2.Add(8); list2.Add(9); list.RemoveAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4), Is.True); } @@ -637,18 +701,24 @@ public void RemoveAll() public void Remove() { list.Add(4); list.Add(5); list.Add(6); - Assert.IsFalse(list.Remove(2)); - Assert.IsTrue(list.Check()); - Assert.IsTrue(list.Remove(4)); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 5, 6)); - Assert.AreEqual(6, list.RemoveLast()); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 5)); + Assert.Multiple(() => + { + Assert.That(list.Remove(2), Is.False); + Assert.That(list.Check(), Is.True); + Assert.That(list.Remove(4), Is.True); + }); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 5, 6), Is.True); + Assert.That(list.RemoveLast(), Is.EqualTo(6)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 5), Is.True); list.Add(7); - Assert.AreEqual(5, list.RemoveFirst()); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 7)); + Assert.Multiple(() => + { + Assert.That(list.RemoveFirst(), Is.EqualTo(5)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 7), Is.True); + }); } @@ -657,12 +727,12 @@ public void Clear() { list.Add(7); list.Add(6); list.Clear(); - Assert.IsTrue(list.IsEmpty); + Assert.That(list.IsEmpty, Is.True); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } } @@ -674,7 +744,7 @@ namespace IIndexed [TestFixture] public class Searching { - private IIndexed dit; + private HashedLinkedList dit; [SetUp] @@ -687,30 +757,38 @@ public void Init() [Test] public void IndexOf() { - Assert.AreEqual(~0, dit.IndexOf(6)); + Assert.That(dit.IndexOf(6), Is.EqualTo(~0)); dit.Add(7); - Assert.AreEqual(~1, dit.IndexOf(6)); - Assert.AreEqual(~1, dit.LastIndexOf(6)); - Assert.AreEqual(0, dit.IndexOf(7)); + Assert.Multiple(() => + { + Assert.That(dit.IndexOf(6), Is.EqualTo(~1)); + Assert.That(dit.LastIndexOf(6), Is.EqualTo(~1)); + Assert.That(dit.IndexOf(7), Is.EqualTo(0)); + }); dit.Add(5); dit.Add(7); dit.Add(8); dit.Add(7); - Assert.AreEqual(~3, dit.IndexOf(6)); - Assert.AreEqual(0, dit.IndexOf(7)); - Assert.AreEqual(0, dit.LastIndexOf(7)); - Assert.AreEqual(2, dit.IndexOf(8)); - Assert.AreEqual(1, dit.LastIndexOf(5)); + Assert.Multiple(() => + { + Assert.That(dit.IndexOf(6), Is.EqualTo(~3)); + Assert.That(dit.IndexOf(7), Is.EqualTo(0)); + Assert.That(dit.LastIndexOf(7), Is.EqualTo(0)); + Assert.That(dit.IndexOf(8), Is.EqualTo(2)); + Assert.That(dit.LastIndexOf(5), Is.EqualTo(1)); + }); } [TearDown] public void Dispose() { - dit = null; + dit.Dispose(); } } [TestFixture] public class Removing { - private IIndexed dit; +#pragma warning disable NUnit1032 // TODO: Breaks tests + private HashedLinkedList dit; +#pragma warning restore NUnit1032 // An IDisposable field/property should be Disposed in a TearDown method [SetUp] public void Init() @@ -722,15 +800,18 @@ public void Init() public void RemoveAt() { dit.Add(5); dit.Add(7); dit.Add(9); dit.Add(1); dit.Add(2); - Assert.AreEqual(7, dit.RemoveAt(1)); - Assert.IsTrue(((HashedLinkedList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 5, 9, 1, 2)); - Assert.AreEqual(5, dit.RemoveAt(0)); - Assert.IsTrue(((HashedLinkedList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 9, 1, 2)); - Assert.AreEqual(2, dit.RemoveAt(2)); - Assert.IsTrue(((HashedLinkedList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 9, 1)); + Assert.Multiple(() => + { + Assert.That(dit.RemoveAt(1), Is.EqualTo(7)); + Assert.That(((HashedLinkedList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 5, 9, 1, 2), Is.True); + Assert.That(dit.RemoveAt(0), Is.EqualTo(5)); + }); + Assert.That(((HashedLinkedList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 9, 1, 2), Is.True); + Assert.That(dit.RemoveAt(2), Is.EqualTo(2)); + Assert.That(((HashedLinkedList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 9, 1), Is.True); } @@ -760,30 +841,49 @@ public void RemoveInterval() dit.RemoveInterval(0, 0); dit.Add(10); dit.Add(20); dit.Add(30); dit.Add(40); dit.Add(50); dit.Add(60); dit.RemoveInterval(3, 0); - Assert.IsTrue(((HashedLinkedList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 10, 20, 30, 40, 50, 60)); + Assert.Multiple(() => + { + Assert.That(((HashedLinkedList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 10, 20, 30, 40, 50, 60), Is.True); + }); dit.RemoveInterval(3, 1); - Assert.IsTrue(((HashedLinkedList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 10, 20, 30, 50, 60)); + Assert.Multiple(() => + { + Assert.That(((HashedLinkedList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 10, 20, 30, 50, 60), Is.True); + }); dit.RemoveInterval(1, 3); - Assert.IsTrue(((HashedLinkedList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 10, 60)); + Assert.Multiple(() => + { + Assert.That(((HashedLinkedList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 10, 60), Is.True); + }); dit.RemoveInterval(0, 2); - Assert.IsTrue(((HashedLinkedList)dit).Check()); - Assert.IsTrue(IC.Eq(dit)); + Assert.Multiple(() => + { + Assert.That(((HashedLinkedList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit), Is.True); + }); dit.Add(10); dit.Add(20); dit.Add(30); dit.Add(40); dit.Add(50); dit.Add(60); dit.RemoveInterval(0, 2); - Assert.IsTrue(((HashedLinkedList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 30, 40, 50, 60)); + Assert.Multiple(() => + { + Assert.That(((HashedLinkedList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 30, 40, 50, 60), Is.True); + }); dit.RemoveInterval(2, 2); - Assert.IsTrue(((HashedLinkedList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 30, 40)); + Assert.Multiple(() => + { + Assert.That(((HashedLinkedList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 30, 40), Is.True); + }); } [TearDown] public void Dispose() { dit = null; + // not working: dit.Dispose(); } } } @@ -793,7 +893,7 @@ namespace IList_ [TestFixture] public class Searching { - private IList lst; + private HashedLinkedList lst; [SetUp] @@ -801,7 +901,7 @@ public class Searching [TearDown] - public void Dispose() { lst = null; } + public void Dispose() { lst.Dispose(); } [Test] public void FirstBad() @@ -825,11 +925,17 @@ public void LastBad() public void FirstLast() { lst.Add(19); - Assert.AreEqual(19, lst.First); - Assert.AreEqual(19, lst.Last); + Assert.Multiple(() => + { + Assert.That(lst.First, Is.EqualTo(19)); + Assert.That(lst.Last, Is.EqualTo(19)); + }); lst.Add(34); lst.InsertFirst(12); - Assert.AreEqual(12, lst.First); - Assert.AreEqual(34, lst.Last); + Assert.Multiple(() => + { + Assert.That(lst.First, Is.EqualTo(12)); + Assert.That(lst.Last, Is.EqualTo(34)); + }); } @@ -837,48 +943,57 @@ public void FirstLast() public void This() { lst.Add(34); - Assert.AreEqual(34, lst[0]); + Assert.That(lst[0], Is.EqualTo(34)); lst[0] = 56; - Assert.AreEqual(56, lst.First); + Assert.That(lst.First, Is.EqualTo(56)); lst.Add(7); lst.Add(77); lst.Add(777); lst.Add(7777); lst[0] = 45; lst[2] = 78; lst[4] = 101; - Assert.IsTrue(IC.Eq(lst, 45, 7, 78, 777, 101)); + Assert.That(IC.Eq(lst, 45, 7, 78, 777, 101), Is.True); } [Test] public void ThisWithUpdates() { - HashedLinkedList> pairlist = new HashedLinkedList>(new KeyValuePairEqualityComparer()) + HashedLinkedList> pairlist = new(new KeyValuePairEqualityComparer()) { - new System.Collections.Generic.KeyValuePair(10, 50), - new System.Collections.Generic.KeyValuePair(11, 51), - new System.Collections.Generic.KeyValuePair(12, 52), - new System.Collections.Generic.KeyValuePair(13, 53) + new SCG.KeyValuePair(10, 50), + new SCG.KeyValuePair(11, 51), + new SCG.KeyValuePair(12, 52), + new SCG.KeyValuePair(13, 53) }; - pairlist[2] = new System.Collections.Generic.KeyValuePair(12, 102); - Assert.IsTrue(pairlist.Check()); - Assert.AreEqual(new System.Collections.Generic.KeyValuePair(12, 102), pairlist[2]); - pairlist[2] = new System.Collections.Generic.KeyValuePair(22, 202); - Assert.IsTrue(pairlist.Check()); - Assert.AreEqual(new System.Collections.Generic.KeyValuePair(22, 202), pairlist[2]); - pairlist[1] = new System.Collections.Generic.KeyValuePair(12, 303); - Assert.IsTrue(pairlist.Check()); - Assert.AreEqual(new System.Collections.Generic.KeyValuePair(12, 303), pairlist[1]); - Assert.AreEqual(new System.Collections.Generic.KeyValuePair(22, 202), pairlist[2]); + pairlist[2] = new SCG.KeyValuePair(12, 102); + Assert.Multiple(() => + { + Assert.That(pairlist.Check(), Is.True); + Assert.That(pairlist[2], Is.EqualTo(new SCG.KeyValuePair(12, 102))); + }); + pairlist[2] = new SCG.KeyValuePair(22, 202); + Assert.Multiple(() => + { + Assert.That(pairlist.Check(), Is.True); + Assert.That(pairlist[2], Is.EqualTo(new SCG.KeyValuePair(22, 202))); + }); + pairlist[1] = new SCG.KeyValuePair(12, 303); + Assert.Multiple(() => + { + Assert.That(pairlist.Check(), Is.True); + Assert.That(pairlist[1], Is.EqualTo(new SCG.KeyValuePair(12, 303))); + Assert.That(pairlist[2], Is.EqualTo(new SCG.KeyValuePair(22, 202))); + }); } [Test] public void ThisWithUpdatesBad() { - HashedLinkedList> pairlist = new HashedLinkedList>(new KeyValuePairEqualityComparer()) + HashedLinkedList> pairlist = new(new KeyValuePairEqualityComparer()) { - new System.Collections.Generic.KeyValuePair(10, 50), - new System.Collections.Generic.KeyValuePair(11, 51), - new System.Collections.Generic.KeyValuePair(12, 52), - new System.Collections.Generic.KeyValuePair(13, 53) + new SCG.KeyValuePair(10, 50), + new SCG.KeyValuePair(11, 51), + new SCG.KeyValuePair(12, 52), + new SCG.KeyValuePair(13, 53) }; - Assert.Throws(() => pairlist[2] = new System.Collections.Generic.KeyValuePair(11, 102)); + Assert.Throws(() => pairlist[2] = new SCG.KeyValuePair(11, 102)); } [Test] @@ -937,15 +1052,15 @@ public void ThisBadHiSet() [TestFixture] public class Combined { - private IList> lst; + private HashedLinkedList> lst; [SetUp] public void Init() { - lst = new HashedLinkedList>(new KeyValuePairEqualityComparer()); + lst = new HashedLinkedList>(new KeyValuePairEqualityComparer()); for (int i = 0; i < 10; i++) { - lst.Add(new System.Collections.Generic.KeyValuePair(i, i + 30)); + lst.Add(new SCG.KeyValuePair(i, i + 30)); } } @@ -953,89 +1068,113 @@ public void Init() [TearDown] public void Dispose() { - lst = null; + lst.Dispose(); } [Test] public void Find() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Find(ref p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); - p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Find(ref p)); + Assert.Multiple(() => + { + Assert.That(lst.Find(ref p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); + p = new SCG.KeyValuePair(13, 78); + Assert.That(lst.Find(ref p), Is.False); } [Test] public void FindOrAdd() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.FindOrAdd(ref p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); - p = new System.Collections.Generic.KeyValuePair(13, 79); - Assert.IsFalse(lst.FindOrAdd(ref p)); - Assert.AreEqual(13, lst[10].Key); - Assert.AreEqual(79, lst[10].Value); + Assert.Multiple(() => + { + Assert.That(lst.FindOrAdd(ref p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); + p = new SCG.KeyValuePair(13, 79); + Assert.Multiple(() => + { + Assert.That(lst.FindOrAdd(ref p), Is.False); + Assert.That(lst[10].Key, Is.EqualTo(13)); + Assert.That(lst[10].Value, Is.EqualTo(79)); + }); } [Test] public void Update() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Update(p)); - Assert.AreEqual(3, lst[3].Key); - Assert.AreEqual(78, lst[3].Value); - p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Update(p)); + Assert.Multiple(() => + { + Assert.That(lst.Update(p), Is.True); + Assert.That(lst[3].Key, Is.EqualTo(3)); + Assert.That(lst[3].Value, Is.EqualTo(78)); + }); + p = new SCG.KeyValuePair(13, 78); + Assert.That(lst.Update(p), Is.False); } [Test] public void UpdateOrAdd1() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.UpdateOrAdd(p)); - Assert.AreEqual(3, lst[3].Key); - Assert.AreEqual(78, lst[3].Value); - p = new System.Collections.Generic.KeyValuePair(13, 79); - Assert.IsFalse(lst.UpdateOrAdd(p)); - Assert.AreEqual(13, lst[10].Key); - Assert.AreEqual(79, lst[10].Value); + Assert.Multiple(() => + { + Assert.That(lst.UpdateOrAdd(p), Is.True); + Assert.That(lst[3].Key, Is.EqualTo(3)); + Assert.That(lst[3].Value, Is.EqualTo(78)); + }); + p = new SCG.KeyValuePair(13, 79); + Assert.Multiple(() => + { + Assert.That(lst.UpdateOrAdd(p), Is.False); + Assert.That(lst[10].Key, Is.EqualTo(13)); + Assert.That(lst[10].Value, Is.EqualTo(79)); + }); } [Test] public void UpdateOrAdd2() { - ICollection coll = new HashedLinkedList(); + ICollection coll = new HashedLinkedList(); // s1 and s2 are distinct objects but contain the same text: - String s1 = "abc", s2 = ("def" + s1).Substring(3); - Assert.IsFalse(coll.UpdateOrAdd(s1, out string old)); - Assert.AreEqual(null, old); - Assert.IsTrue(coll.UpdateOrAdd(s2, out old)); - Assert.IsTrue(Object.ReferenceEquals(s1, old)); - Assert.IsFalse(Object.ReferenceEquals(s2, old)); + string s1 = "abc", s2 = ("def" + s1).Substring(3); + Assert.Multiple(() => + { + Assert.That(coll.UpdateOrAdd(s1, out string old), Is.False); + Assert.That(old, Is.EqualTo(null)); + Assert.That(coll.UpdateOrAdd(s2, out old), Is.True); + Assert.That(ReferenceEquals(s1, old), Is.True); + Assert.That(ReferenceEquals(s2, old), Is.False); + }); } [Test] public void RemoveWithReturn() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Remove(p, out p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); - Assert.AreEqual(4, lst[3].Key); - Assert.AreEqual(34, lst[3].Value); - p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Remove(p, out _)); + Assert.Multiple(() => + { + Assert.That(lst.Remove(p, out p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + Assert.That(lst[3].Key, Is.EqualTo(4)); + Assert.That(lst[3].Value, Is.EqualTo(34)); + }); + p = new SCG.KeyValuePair(13, 78); + Assert.That(lst.Remove(p, out _), Is.False); } } @@ -1043,7 +1182,9 @@ public void RemoveWithReturn() [TestFixture] public class Inserting { +#pragma warning disable NUnit1032 // TODO: Breaks tests private IList lst; +#pragma warning restore NUnit1032 // An IDisposable field/property should be Disposed in a TearDown method [SetUp] @@ -1051,29 +1192,32 @@ public class Inserting [TearDown] - public void Dispose() { lst = null; } + public void Dispose() + { + // lst.Dispose(); + } [Test] public void Insert() { lst.Insert(0, 5); - Assert.IsTrue(IC.Eq(lst, 5)); + Assert.That(IC.Eq(lst, 5), Is.True); lst.Insert(0, 7); - Assert.IsTrue(IC.Eq(lst, 7, 5)); + Assert.That(IC.Eq(lst, 7, 5), Is.True); lst.Insert(1, 4); - Assert.IsTrue(IC.Eq(lst, 7, 4, 5)); + Assert.That(IC.Eq(lst, 7, 4, 5), Is.True); lst.Insert(3, 2); - Assert.IsTrue(IC.Eq(lst, 7, 4, 5, 2)); + Assert.That(IC.Eq(lst, 7, 4, 5, 2), Is.True); } [Test] public void InsertDuplicate() { lst.Insert(0, 5); - Assert.IsTrue(IC.Eq(lst, 5)); + Assert.That(IC.Eq(lst, 5), Is.True); lst.Insert(0, 7); - Assert.IsTrue(IC.Eq(lst, 7, 5)); + Assert.That(IC.Eq(lst, 7, 5), Is.True); Assert.Throws(() => lst.Insert(1, 5)); } @@ -1082,36 +1226,44 @@ public void InsertDuplicate() public void InsertAllDuplicate1() { lst.Insert(0, 3); - Assert.IsTrue(IC.Eq(lst, 3)); + Assert.That(IC.Eq(lst, 3), Is.True); lst.Insert(0, 7); - Assert.IsTrue(IC.Eq(lst, 7, 3)); + Assert.That(IC.Eq(lst, 7, 3), Is.True); try { - lst.InsertAll(1, new int[] { 1, 2, 3, 4 }); + lst.InsertAll(1, [1, 2, 3, 4]); } catch (DuplicateNotAllowedException) { } - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 1, 2, 3)); + + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 1, 2, 3), Is.True); + }); } [Test] public void InsertAllDuplicate2() { lst.Insert(0, 3); - Assert.IsTrue(IC.Eq(lst, 3)); + Assert.That(IC.Eq(lst, 3), Is.True); lst.Insert(0, 7); - Assert.IsTrue(IC.Eq(lst, 7, 3)); + Assert.That(IC.Eq(lst, 7, 3), Is.True); try { - lst.InsertAll(1, new int[] { 5, 6, 5, 8 }); + lst.InsertAll(1, [5, 6, 5, 8]); } catch (DuplicateNotAllowedException) { } - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 5, 6, 3)); + + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 5, 6, 3), Is.True); + }); } [Test] @@ -1139,15 +1291,18 @@ public void FIFO() lst.Add(2 * i); } - Assert.IsTrue(lst.FIFO); - Assert.AreEqual(0, lst.Remove()); - Assert.AreEqual(2, lst.Remove()); + Assert.Multiple(() => + { + Assert.That(lst.FIFO, Is.True); + Assert.That(lst.Remove(), Is.EqualTo(0)); + }); + Assert.That(lst.Remove(), Is.EqualTo(2)); lst.FIFO = false; - Assert.AreEqual(12, lst.Remove()); - Assert.AreEqual(10, lst.Remove()); + Assert.That(lst.Remove(), Is.EqualTo(12)); + Assert.That(lst.Remove(), Is.EqualTo(10)); lst.FIFO = true; - Assert.AreEqual(4, lst.Remove()); - Assert.AreEqual(6, lst.Remove()); + Assert.That(lst.Remove(), Is.EqualTo(4)); + Assert.That(lst.Remove(), Is.EqualTo(6)); } @@ -1162,7 +1317,7 @@ public void InsertFirstLast() lst.InsertLast(25); lst.InsertFirst(34); lst.InsertLast(55); - Assert.IsTrue(IC.Eq(lst, 34, 24, 14, 4, 5, 15, 25, 55)); + Assert.That(IC.Eq(lst, 34, 24, 14, 4, 5, 15, 25, 55), Is.True); } @@ -1174,14 +1329,23 @@ public void InsertFirst() lst.Add(4); lst.Add(5); lst.ViewOf(2).InsertFirst(7); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 2, 3, 4, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 2, 3, 4, 5), Is.True); + }); lst.ViewOf(3).InsertFirst(8); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 2, 8, 3, 4, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 2, 8, 3, 4, 5), Is.True); + }); lst.ViewOf(5).InsertFirst(9); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 2, 8, 3, 4, 9, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 2, 8, 3, 4, 9, 5), Is.True); + }); } [Test] @@ -1191,7 +1355,7 @@ public void BadViewOf() lst.Add(3); lst.Add(2); lst.Add(5); - Assert.IsNull(lst.ViewOf(4)); + Assert.That(lst.ViewOf(4), Is.Null); } [Test] @@ -1203,14 +1367,23 @@ public void InsertAfter() lst.Add(4); lst.Add(5); lst.LastViewOf(2).InsertLast(7); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 1, 2, 7, 3, 4, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 1, 2, 7, 3, 4, 5), Is.True); + }); lst.LastViewOf(1).InsertLast(8); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 1, 8, 2, 7, 3, 4, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 1, 8, 2, 7, 3, 4, 5), Is.True); + }); lst.LastViewOf(5).InsertLast(9); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 1, 8, 2, 7, 3, 4, 5, 9)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 1, 8, 2, 7, 3, 4, 5, 9), Is.True); + }); } [Test] @@ -1220,7 +1393,7 @@ public void BadInsertAfter() lst.Add(3); lst.Add(6); lst.Add(5); - Assert.IsNull(lst.ViewOf(4)); + Assert.That(lst.ViewOf(4), Is.Null); } [Test] @@ -1233,16 +1406,25 @@ public void InsertAll() IList lst2 = new HashedLinkedList() { 7, 8, 9 }; lst.InsertAll(0, lst2); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 1, 2, 3, 4)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 1, 2, 3, 4), Is.True); + }); lst.RemoveAll(lst2); lst.InsertAll(4, lst2); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 1, 2, 3, 4, 7, 8, 9)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 1, 2, 3, 4, 7, 8, 9), Is.True); + }); lst.RemoveAll(lst2); lst.InsertAll(2, lst2); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 1, 2, 7, 8, 9, 3, 4)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 1, 2, 7, 8, 9, 3, 4), Is.True); + }); } [Test] @@ -1264,18 +1446,24 @@ public void Map() string m(int i) { return "<<" + i + ">>"; } IList r = lst.Map(m); - Assert.IsTrue(((HashedLinkedList)r).Check()); - Assert.IsTrue(r.IsEmpty); + Assert.Multiple(() => + { + Assert.That(((HashedLinkedList)r).Check(), Is.True); + Assert.That(r.IsEmpty, Is.True); + }); lst.Add(1); lst.Add(2); lst.Add(3); lst.Add(4); r = lst.Map(m); - Assert.IsTrue(((HashedLinkedList)r).Check()); - Assert.AreEqual(4, r.Count); + Assert.Multiple(() => + { + Assert.That(((HashedLinkedList)r).Check(), Is.True); + Assert.That(r, Has.Count.EqualTo(4)); + }); for (int i = 0; i < 4; i++) { - Assert.AreEqual("<<" + (i + 1) + ">>", r[i]); + Assert.That(r[i], Is.EqualTo("<<" + (i + 1) + ">>")); } } [Test] @@ -1350,11 +1538,14 @@ public void RemoveFirstLast() lst.Add(2); lst.Add(3); lst.Add(4); - Assert.AreEqual(1, lst.RemoveFirst()); - Assert.AreEqual(4, lst.RemoveLast()); - Assert.AreEqual(2, lst.RemoveFirst()); - Assert.AreEqual(3, lst.RemoveLast()); - Assert.IsTrue(lst.IsEmpty); + Assert.Multiple(() => + { + Assert.That(lst.RemoveFirst(), Is.EqualTo(1)); + Assert.That(lst.RemoveLast(), Is.EqualTo(4)); + }); + Assert.That(lst.RemoveFirst(), Is.EqualTo(2)); + Assert.That(lst.RemoveLast(), Is.EqualTo(3)); + Assert.That(lst.IsEmpty, Is.True); } @@ -1367,20 +1558,35 @@ public void Reverse() } lst.Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0), Is.True); + }); lst.View(0, 3).Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0), Is.True); + }); lst.View(7, 0).Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0), Is.True); + }); lst.View(7, 3).Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2), Is.True); + }); lst.View(5, 1).Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2), Is.True); + }); } @@ -1411,26 +1617,29 @@ public void Init() [TearDown] public void Dispose() { - lst = null; + lst.Dispose(); } [Test] public void Sort() { lst.Add(5); lst.Add(6); lst.Add(55); lst.Add(7); lst.Add(3); - Assert.IsFalse(lst.IsSorted(new IC())); + Assert.That(lst.IsSorted(new IC()), Is.False); lst.Sort(new IC()); - Assert.IsTrue(lst.Check(), "Check "); - Assert.IsTrue(lst.IsSorted()); - Assert.IsTrue(lst.IsSorted(new IC())); - Assert.IsTrue(IC.Eq(lst, 3, 5, 6, 7, 55)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True, "Check "); + Assert.That(lst.IsSorted(), Is.True); + Assert.That(lst.IsSorted(new IC()), Is.True); + Assert.That(IC.Eq(lst, 3, 5, 6, 7, 55), Is.True); + }); } } [TestFixture] public class ShuffleTests { - private IList lst; + private HashedLinkedList lst; [SetUp] @@ -1438,7 +1647,7 @@ public class ShuffleTests [TearDown] - public void Dispose() { lst = null; } + public void Dispose() { lst.Dispose(); } [Test] @@ -1448,10 +1657,10 @@ public void Shuffle() for (int i = 0; i < 100; i++) { lst.Shuffle(new C5Random(i + 1)); - Assert.IsTrue(lst.Check(), "Check " + i); + Assert.That(lst.Check(), Is.True, "Check " + i); int[] lst2 = lst.ToArray(); Sorting.IntroSort(lst2); - Assert.IsTrue(IC.Eq(lst2, 3, 5, 6, 7), "Contents " + i); + Assert.That(IC.Eq(lst2, 3, 5, 6, 7), Is.True, "Contents " + i); } } } @@ -1463,7 +1672,7 @@ public class AddingThenRemoving public void AddingThenRemovingTest1() { // bug20070911: - HashedLinkedList test = new HashedLinkedList(); + HashedLinkedList test = new(); for (int i = 0; i < 33; i++) { test.Add(i); @@ -1473,20 +1682,20 @@ public void AddingThenRemovingTest1() { test.Remove(i); } // for - Assert.IsTrue(test.IsEmpty); + Assert.That(test.IsEmpty, Is.True); for (int count = 0; count < 520; count++) { - HashedLinkedList hll = new HashedLinkedList(); + HashedLinkedList hll = new(); for (int i = 1; i <= count; i++) { hll.Add(i); } - Assert.AreEqual(count, hll.Count); + Assert.That(hll, Has.Count.EqualTo(count)); for (int i = 1; i <= count; i++) { hll.Remove(i); } - Assert.IsTrue(hll.IsEmpty); + Assert.That(hll.IsEmpty, Is.True); } } @@ -1494,7 +1703,7 @@ public void AddingThenRemovingTest1() public void AddingThenRemovingTest2() { // bug20070911: - HashedLinkedList test = new HashedLinkedList(); + HashedLinkedList test = new(); for (int i = 0; i < 33; i++) { test.Add(i); @@ -1504,20 +1713,20 @@ public void AddingThenRemovingTest2() { test.Remove(i); } // for - Assert.IsTrue(test.IsEmpty); + Assert.That(test.IsEmpty, Is.True); for (int count = 0; count < 520; count++) { - HashedLinkedList hll = new HashedLinkedList(); + HashedLinkedList hll = new(); for (int i = 1; i <= count; i++) { hll.Add(i); } - Assert.AreEqual(count, hll.Count); + Assert.That(hll, Has.Count.EqualTo(count)); for (int i = count; i >= 1; i--) { hll.Remove(i); } - Assert.IsTrue(hll.IsEmpty); + Assert.That(hll.IsEmpty, Is.True); } } } @@ -1536,7 +1745,7 @@ public class Range [TearDown] - public void Dispose() { lst = null; } + public void Dispose() { lst.Dispose(); } [Test] @@ -1548,10 +1757,13 @@ public void GetRange() lst.Add(i); } - Assert.IsTrue(IC.Eq(lst[0, 3], 0, 1, 2)); - Assert.IsTrue(IC.Eq(lst[3, 3], 3, 4, 5)); - Assert.IsTrue(IC.Eq(lst[6, 3], 6, 7, 8)); - Assert.IsTrue(IC.Eq(lst[6, 4], 6, 7, 8, 9)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(lst[0, 3], 0, 1, 2), Is.True); + Assert.That(IC.Eq(lst[3, 3], 3, 4, 5), Is.True); + Assert.That(IC.Eq(lst[6, 3], 6, 7, 8), Is.True); + Assert.That(IC.Eq(lst[6, 4], 6, 7, 8, 9), Is.True); + }); } @@ -1563,10 +1775,13 @@ public void Backwards() lst.Add(i); } - Assert.IsTrue(IC.Eq(lst.Backwards(), 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); - Assert.IsTrue(IC.Eq(lst[0, 3].Backwards(), 2, 1, 0)); - Assert.IsTrue(IC.Eq(lst[3, 3].Backwards(), 5, 4, 3)); - Assert.IsTrue(IC.Eq(lst[6, 4].Backwards(), 9, 8, 7, 6)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(lst.Backwards(), 9, 8, 7, 6, 5, 4, 3, 2, 1, 0), Is.True); + Assert.That(IC.Eq(lst[0, 3].Backwards(), 2, 1, 0), Is.True); + Assert.That(IC.Eq(lst[3, 3].Backwards(), 5, 4, 3), Is.True); + Assert.That(IC.Eq(lst[6, 4].Backwards(), 9, 8, 7, 6), Is.True); + }); } @@ -1578,13 +1793,19 @@ public void DirectionAndCount() lst.Add(i); } - Assert.AreEqual(Direction.Forwards, lst.Direction); - Assert.AreEqual(Direction.Forwards, lst[3, 7].Direction); - Assert.AreEqual(Direction.Backwards, lst[3, 7].Backwards().Direction); - Assert.AreEqual(Direction.Backwards, lst.Backwards().Direction); - Assert.AreEqual(4, lst[3, 4].Count); - Assert.AreEqual(4, lst[3, 4].Backwards().Count); - Assert.AreEqual(10, lst.Backwards().Count); + Assert.Multiple(() => + { + Assert.That(lst.Direction, Is.EqualTo(Direction.Forwards)); + Assert.That(lst[3, 7].Direction, Is.EqualTo(Direction.Forwards)); + Assert.That(lst[3, 7].Backwards().Direction, Is.EqualTo(Direction.Backwards)); + Assert.That(lst.Backwards().Direction, Is.EqualTo(Direction.Backwards)); + Assert.That(lst[3, 4], Has.Count.EqualTo(4)); + }); + Assert.Multiple(() => + { + Assert.That(lst[3, 4].Backwards(), Has.Count.EqualTo(4)); + Assert.That(lst.Backwards(), Has.Count.EqualTo(10)); + }); } [Test] @@ -1611,8 +1832,10 @@ namespace View [TestFixture] public class Simple { +#pragma warning disable NUnit1032 // TODO: Breaks tests private HashedLinkedList list; private HashedLinkedList view; +#pragma warning restore NUnit1032 // An IDisposable field/property should be Disposed in a TearDown method [SetUp] public void Init() @@ -1624,14 +1847,17 @@ public void Init() [TearDown] public void Dispose() { - list = null; - view = null; + //list.Dispose(); + //view.Dispose(); } private void check() { - Assert.IsTrue(list.Check()); - Assert.IsTrue(view.Check()); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(view.Check(), Is.True); + }); } [Test] @@ -1648,8 +1874,11 @@ public void InsertPointer() check(); view.Insert(list.ViewOf(0), 11); check(); - Assert.IsTrue(IC.Eq(list, 0, 11, 1, 9, 7, 2, 10, 3, 8)); - Assert.IsTrue(IC.Eq(view, 11, 1, 9, 7, 2, 10)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 11, 1, 9, 7, 2, 10, 3, 8), Is.True); + Assert.That(IC.Eq(view, 11, 1, 9, 7, 2, 10), Is.True); + }); } [Test] @@ -1680,15 +1909,21 @@ public void InsertPointerBad4() public void Span() { IList span = list.View(1, 0).Span(list.View(2, 0)); - Assert.IsTrue(span.Check()); - Assert.AreEqual(1, span.Offset); - Assert.AreEqual(1, span.Count); + Assert.Multiple(() => + { + Assert.That(span.Check(), Is.True); + Assert.That(span.Offset, Is.EqualTo(1)); + Assert.That(span, Has.Count.EqualTo(1)); + }); span = list.View(0, 2).Span(list.View(2, 2)); - Assert.IsTrue(span.Check()); - Assert.AreEqual(0, span.Offset); - Assert.AreEqual(4, span.Count); + Assert.Multiple(() => + { + Assert.That(span.Check(), Is.True); + Assert.That(span.Offset, Is.EqualTo(0)); + Assert.That(span, Has.Count.EqualTo(4)); + }); span = list.View(3, 1).Span(list.View(1, 1)); - Assert.IsNull(span); + Assert.That(span, Is.Null); } [Test] @@ -1700,119 +1935,170 @@ public void ViewOf() } IList v = view.ViewOf(2); - Assert.IsTrue(v.Check()); - Assert.IsTrue(IC.Eq(v, 2)); - Assert.AreEqual(2, v.Offset); + Assert.Multiple(() => + { + Assert.That(v.Check(), Is.True); + Assert.That(IC.Eq(v, 2), Is.True); + Assert.That(v.Offset, Is.EqualTo(2)); + }); v = list.ViewOf(2); - Assert.IsTrue(v.Check()); - Assert.IsTrue(IC.Eq(v, 2)); - Assert.AreEqual(2, v.Offset); + Assert.Multiple(() => + { + Assert.That(v.Check(), Is.True); + Assert.That(IC.Eq(v, 2), Is.True); + Assert.That(v.Offset, Is.EqualTo(2)); + }); v = list.LastViewOf(2); - Assert.IsTrue(v.Check()); - Assert.IsTrue(IC.Eq(v, 2)); - Assert.AreEqual(2, v.Offset); + Assert.Multiple(() => + { + Assert.That(v.Check(), Is.True); + Assert.That(IC.Eq(v, 2), Is.True); + Assert.That(v.Offset, Is.EqualTo(2)); + }); } [Test] public void BadViewOf() { - Assert.IsNull(view.ViewOf(5)); - Assert.IsNull(view.LastViewOf(5)); - Assert.IsNull(view.ViewOf(3)); - Assert.IsNull(view.LastViewOf(3)); - Assert.IsNull(view.ViewOf(0)); - Assert.IsNull(view.LastViewOf(0)); + Assert.Multiple(() => + { + Assert.That(view.ViewOf(5), Is.Null); + Assert.That(view.LastViewOf(5), Is.Null); + Assert.That(view.ViewOf(3), Is.Null); + Assert.That(view.LastViewOf(3), Is.Null); + Assert.That(view.ViewOf(0), Is.Null); + Assert.That(view.LastViewOf(0), Is.Null); + }); } [Test] public void ArrayStuff() { - Assert.IsTrue(IC.Eq(view.ToArray(), 1, 2)); + Assert.That(IC.Eq(view.ToArray(), 1, 2), Is.True); int[] extarray = new int[5]; view.CopyTo(extarray, 2); - Assert.IsTrue(IC.Eq(extarray, 0, 0, 1, 2, 0)); + Assert.That(IC.Eq(extarray, 0, 0, 1, 2, 0), Is.True); } [Test] public void Add() { check(); - Assert.IsTrue(IC.Eq(list, 0, 1, 2, 3)); - Assert.IsTrue(IC.Eq(view, 1, 2)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 1, 2, 3), Is.True); + Assert.That(IC.Eq(view, 1, 2), Is.True); + }); view.InsertFirst(10); check(); - Assert.IsTrue(IC.Eq(list, 0, 10, 1, 2, 3)); - Assert.IsTrue(IC.Eq(view, 10, 1, 2)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 10, 1, 2, 3), Is.True); + Assert.That(IC.Eq(view, 10, 1, 2), Is.True); + }); view.Clear(); - Assert.IsFalse(view.IsReadOnly); - Assert.IsFalse(view.AllowsDuplicates); - Assert.IsTrue(view.IsEmpty); + Assert.Multiple(() => + { + Assert.That(view.IsReadOnly, Is.False); + Assert.That(view.AllowsDuplicates, Is.False); + Assert.That(view.IsEmpty, Is.True); + }); check(); - Assert.IsTrue(IC.Eq(list, 0, 3)); - Assert.IsTrue(IC.Eq(view)); + Assert.That(IC.Eq(list, 0, 3), Is.True); + Assert.That(IC.Eq(view), Is.True); view.Add(8); - Assert.IsFalse(view.IsEmpty); - Assert.IsFalse(view.AllowsDuplicates); - Assert.IsFalse(view.IsReadOnly); + Assert.That(view.IsEmpty, Is.False); + Assert.That(view.AllowsDuplicates, Is.False); + Assert.That(view.IsReadOnly, Is.False); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 3)); - Assert.IsTrue(IC.Eq(view, 8)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 3), Is.True); + Assert.That(IC.Eq(view, 8), Is.True); + }); view.Add(12); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 12, 3)); - Assert.IsTrue(IC.Eq(view, 8, 12)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 12, 3), Is.True); + Assert.That(IC.Eq(view, 8, 12), Is.True); + }); view./*ViewOf(12).*/InsertLast(15); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 12, 15, 3)); - Assert.IsTrue(IC.Eq(view, 8, 12, 15)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 12, 15, 3), Is.True); + Assert.That(IC.Eq(view, 8, 12, 15), Is.True); + }); view.ViewOf(12).InsertFirst(18); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 18, 12, 15, 3)); - Assert.IsTrue(IC.Eq(view, 8, 18, 12, 15)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 18, 12, 15, 3), Is.True); + Assert.That(IC.Eq(view, 8, 18, 12, 15), Is.True); + }); - HashedLinkedList lst2 = new HashedLinkedList() { 90, 92 }; + HashedLinkedList lst2 = new() { 90, 92 }; view.AddAll(lst2); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 18, 12, 15, 90, 92, 3)); - Assert.IsTrue(IC.Eq(view, 8, 18, 12, 15, 90, 92)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 18, 12, 15, 90, 92, 3), Is.True); + Assert.That(IC.Eq(view, 8, 18, 12, 15, 90, 92), Is.True); + }); view.InsertLast(66); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 18, 12, 15, 90, 92, 66, 3)); - Assert.IsTrue(IC.Eq(view, 8, 18, 12, 15, 90, 92, 66)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 18, 12, 15, 90, 92, 66, 3), Is.True); + Assert.That(IC.Eq(view, 8, 18, 12, 15, 90, 92, 66), Is.True); + }); } [Test] public void Bxxx() { - Assert.IsTrue(IC.Eq(view.Backwards(), 2, 1)); - Assert.AreSame(list, view.Underlying); - Assert.IsNull(list.Underlying); - Assert.AreEqual(Direction.Forwards, view.Direction); - Assert.AreEqual(Direction.Backwards, view.Backwards().Direction); - Assert.AreEqual(0, list.Offset); - Assert.AreEqual(1, view.Offset); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view.Backwards(), 2, 1), Is.True); + Assert.That(view.Underlying, Is.SameAs(list)); + Assert.That(list.Underlying, Is.Null); + Assert.That(view.Direction, Is.EqualTo(Direction.Forwards)); + Assert.That(view.Backwards().Direction, Is.EqualTo(Direction.Backwards)); + Assert.That(list.Offset, Is.EqualTo(0)); + Assert.That(view.Offset, Is.EqualTo(1)); + }); } [Test] public void Contains() { - Assert.IsTrue(view.Contains(1)); - Assert.IsFalse(view.Contains(0)); + Assert.Multiple(() => + { + Assert.That(view.Contains(1), Is.True); + Assert.That(view.Contains(0), Is.False); + }); - HashedLinkedList lst2 = new HashedLinkedList() { 2 }; - Assert.IsTrue(view.ContainsAll(lst2)); + HashedLinkedList lst2 = new() { 2 }; + Assert.That(view.ContainsAll(lst2), Is.True); lst2.Add(3); - Assert.IsFalse(view.ContainsAll(lst2)); - Assert.AreEqual(Speed.Constant, view.ContainsSpeed); - Assert.AreEqual(2, view.Count); + Assert.Multiple(() => + { + Assert.That(view.ContainsAll(lst2), Is.False); + Assert.That(view.ContainsSpeed, Is.EqualTo(Speed.Constant)); + Assert.That(view, Has.Count.EqualTo(2)); + }); view.Add(1); - Assert.AreEqual(1, view.ContainsCount(2)); - Assert.AreEqual(1, view.ContainsCount(1)); - Assert.AreEqual(2, view.Count); + Assert.Multiple(() => + { + Assert.That(view.ContainsCount(2), Is.EqualTo(1)); + Assert.That(view.ContainsCount(1), Is.EqualTo(1)); + Assert.That(view, Has.Count.EqualTo(2)); + }); } @@ -1821,25 +2107,31 @@ public void CreateView() { HashedLinkedList view2 = (HashedLinkedList)view.View(1, 0); - Assert.AreSame(list, view2.Underlying); + Assert.That(view2.Underlying, Is.SameAs(list)); } [Test] public void FIFO() { - Assert.IsTrue(view.FIFO); + Assert.That(view.FIFO, Is.True); view.Add(23); view.Add(24); view.Add(25); check(); - Assert.IsTrue(IC.Eq(view, 1, 2, 23, 24, 25)); - Assert.AreEqual(1, view.Remove()); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 1, 2, 23, 24, 25), Is.True); + Assert.That(view.Remove(), Is.EqualTo(1)); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 23, 24, 25)); + Assert.That(IC.Eq(view, 2, 23, 24, 25), Is.True); view.FIFO = false; - Assert.IsFalse(view.FIFO); - Assert.AreEqual(25, view.Remove()); + Assert.Multiple(() => + { + Assert.That(view.FIFO, Is.False); + Assert.That(view.Remove(), Is.EqualTo(25)); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 23, 24)); + Assert.That(IC.Eq(view, 2, 23, 24), Is.True); } @@ -1848,9 +2140,12 @@ public void MapEtc() { HashedLinkedList dbl = (HashedLinkedList)view.Map(new Func(delegate (int i) { return i / 10.0; })); - Assert.IsTrue(dbl.Check()); - Assert.AreEqual(0.1, dbl[0]); - Assert.AreEqual(0.2, dbl[1]); + Assert.Multiple(() => + { + Assert.That(dbl.Check(), Is.True); + Assert.That(dbl[0], Is.EqualTo(0.1)); + Assert.That(dbl[1], Is.EqualTo(0.2)); + }); for (int i = 0; i < 10; i++) { view.Add(i); @@ -1858,16 +2153,22 @@ public void MapEtc() HashedLinkedList list2 = (HashedLinkedList)view.FindAll(new Func(delegate (int i) { return i % 4 == 1; })); - Assert.IsTrue(list2.Check()); - Assert.IsTrue(IC.Eq(list2, 1, 5, 9)); + Assert.Multiple(() => + { + Assert.That(list2.Check(), Is.True); + Assert.That(IC.Eq(list2, 1, 5, 9), Is.True); + }); } [Test] public void FL() { - Assert.AreEqual(1, view.First); - Assert.AreEqual(2, view.Last); + Assert.Multiple(() => + { + Assert.That(view.First, Is.EqualTo(1)); + Assert.That(view.Last, Is.EqualTo(2)); + }); } @@ -1883,17 +2184,17 @@ public void Indexing() view = (HashedLinkedList)list.View(5, 7); for (int i = 0; i < 7; i++) { - Assert.AreEqual(i + 5, view[i]); + Assert.That(view[i], Is.EqualTo(i + 5)); } for (int i = 0; i < 7; i++) { - Assert.AreEqual(i, view.IndexOf(i + 5)); + Assert.That(view.IndexOf(i + 5), Is.EqualTo(i)); } for (int i = 0; i < 7; i++) { - Assert.AreEqual(i, view.LastIndexOf(i + 5)); + Assert.That(view.LastIndexOf(i + 5), Is.EqualTo(i)); } } @@ -1904,13 +2205,19 @@ public void Insert() view.Insert(0, 34); view.Insert(1, 35); view.Insert(4, 36); - Assert.IsTrue(view.Check()); - Assert.IsTrue(IC.Eq(view, 34, 35, 1, 2, 36)); + Assert.Multiple(() => + { + Assert.That(view.Check(), Is.True); + Assert.That(IC.Eq(view, 34, 35, 1, 2, 36), Is.True); + }); IList list2 = new HashedLinkedList() { 40, 41 }; view.InsertAll(3, list2); - Assert.IsTrue(view.Check()); - Assert.IsTrue(IC.Eq(view, 34, 35, 1, 40, 41, 2, 36)); + Assert.Multiple(() => + { + Assert.That(view.Check(), Is.True); + Assert.That(IC.Eq(view, 34, 35, 1, 40, 41, 2, 36), Is.True); + }); } @@ -1918,11 +2225,14 @@ public void Insert() public void Sort() { view.Add(45); view.Add(47); view.Add(46); view.Add(48); - Assert.IsFalse(view.IsSorted(new IC())); + Assert.That(view.IsSorted(new IC()), Is.False); view.Sort(new IC()); check(); - Assert.IsTrue(IC.Eq(list, 0, 1, 2, 45, 46, 47, 48, 3)); - Assert.IsTrue(IC.Eq(view, 1, 2, 45, 46, 47, 48)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 1, 2, 45, 46, 47, 48, 3), Is.True); + Assert.That(IC.Eq(view, 1, 2, 45, 46, 47, 48), Is.True); + }); } @@ -1930,44 +2240,62 @@ public void Sort() public void Remove() { view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0); - Assert.IsTrue(IC.Eq(view, 1, 2, 5)); - Assert.IsTrue(view.Remove(1)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 1, 2, 5), Is.True); + Assert.That(view.Remove(1), Is.True); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 5)); - Assert.IsFalse(view.Remove(1)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 2, 5), Is.True); + Assert.That(view.Remove(1), Is.False); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 5)); - Assert.IsFalse(view.Remove(0)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 2, 5), Is.True); + Assert.That(view.Remove(0), Is.False); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 5)); + Assert.That(IC.Eq(view, 2, 5), Is.True); view.RemoveAllCopies(3); check(); - Assert.IsTrue(IC.Eq(view, 2, 5)); - Assert.IsTrue(IC.Eq(list, 0, 2, 5, 3)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 2, 5), Is.True); + Assert.That(IC.Eq(list, 0, 2, 5, 3), Is.True); + }); view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0); - Assert.IsTrue(IC.Eq(view, 2, 5, 1)); + Assert.That(IC.Eq(view, 2, 5, 1), Is.True); - HashedLinkedList l2 = new HashedLinkedList() { 1, 2, 2, 3, 1 }; + HashedLinkedList l2 = new() { 1, 2, 2, 3, 1 }; view.RemoveAll(l2); check(); - Assert.IsTrue(IC.Eq(view, 5)); + Assert.That(IC.Eq(view, 5), Is.True); view.RetainAll(l2); check(); - Assert.IsTrue(IC.Eq(view)); + Assert.That(IC.Eq(view), Is.True); view.Add(2); view.Add(4); view.Add(5); - Assert.AreEqual(2, view.RemoveAt(0)); - Assert.AreEqual(5, view.RemoveAt(1)); - Assert.AreEqual(4, view.RemoveAt(0)); + Assert.Multiple(() => + { + Assert.That(view.RemoveAt(0), Is.EqualTo(2)); + Assert.That(view.RemoveAt(1), Is.EqualTo(5)); + }); + Assert.That(view.RemoveAt(0), Is.EqualTo(4)); check(); - Assert.IsTrue(IC.Eq(view)); + Assert.That(IC.Eq(view), Is.True); view.Add(8); view.Add(6); view.Add(78); - Assert.AreEqual(8, view.RemoveFirst()); - Assert.AreEqual(78, view.RemoveLast()); + Assert.Multiple(() => + { + Assert.That(view.RemoveFirst(), Is.EqualTo(8)); + Assert.That(view.RemoveLast(), Is.EqualTo(78)); + }); view.Add(2); view.Add(5); view.Add(3); view.Add(1); view.RemoveInterval(1, 2); check(); - Assert.IsTrue(IC.Eq(view, 6, 1)); + Assert.That(IC.Eq(view, 6, 1), Is.True); } @@ -1982,10 +2310,13 @@ public void Reverse() view.View(3, 4).Reverse(); check(); - Assert.IsTrue(IC.Eq(view, 10, 11, 12, 16, 15, 14, 13, 17, 18, 19)); + Assert.That(IC.Eq(view, 10, 11, 12, 16, 15, 14, 13, 17, 18, 19), Is.True); view.Reverse(); - Assert.IsTrue(IC.Eq(view, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10)); - Assert.IsTrue(IC.Eq(list, 0, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10, 3)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10), Is.True); + Assert.That(IC.Eq(list, 0, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10, 3), Is.True); + }); } @@ -1994,21 +2325,21 @@ public void Slide() { view.Slide(1); check(); - Assert.IsTrue(IC.Eq(view, 2, 3)); + Assert.That(IC.Eq(view, 2, 3), Is.True); view.Slide(-2); check(); - Assert.IsTrue(IC.Eq(view, 0, 1)); + Assert.That(IC.Eq(view, 0, 1), Is.True); view.Slide(0, 3); check(); - Assert.IsTrue(IC.Eq(view, 0, 1, 2)); + Assert.That(IC.Eq(view, 0, 1, 2), Is.True); view.Slide(2, 1); check(); - Assert.IsTrue(IC.Eq(view, 2)); + Assert.That(IC.Eq(view, 2), Is.True); view.Slide(-1, 0); check(); - Assert.IsTrue(IC.Eq(view)); + Assert.That(IC.Eq(view), Is.True); view.Add(28); - Assert.IsTrue(IC.Eq(list, 0, 28, 1, 2, 3)); + Assert.That(IC.Eq(list, 0, 28, 1, 2, 3), Is.True); } [Test] public void Iterate() @@ -2044,21 +2375,23 @@ public void Iterate() } //foreach (int cell in list) Console.Write(" " + cell); //Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 2, 4, 8, 668, 13, 6, 1, 667, 10, 666, 11)); + Assert.That(IC.Eq(list, 2, 4, 8, 668, 13, 6, 1, 667, 10, 666, 11), Is.True); } [Test] public void SyncRoot() { - Assert.AreSame(((System.Collections.IList)view).SyncRoot, ((System.Collections.IList)list).SyncRoot); + Assert.That(((System.Collections.IList)list).SyncRoot, Is.SameAs(((System.Collections.IList)view).SyncRoot)); } } [TestFixture] public class MultipleViews { +#pragma warning disable NUnit1032 // TODO: Breaks tests private IList list; +#pragma warning restore NUnit1032 // An IDisposable field/property should be Disposed in a TearDown method private IList[][] views; [SetUp] public void Init() @@ -2082,36 +2415,42 @@ public void Init() [TearDown] public void Dispose() { - list = null; + //list.Dispose(); views = null; } [Test] public void Insert() { - Assert.IsTrue(list.Check(), "list check before insert"); + Assert.That(list.Check(), Is.True, "list check before insert"); list.Insert(3, 777); - Assert.IsTrue(list.Check(), "list check after insert"); + Assert.That(list.Check(), Is.True, "list check after insert"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i < 3 && i + j > 3 ? j + 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i < 3 || (i == 3 && j == 0) ? i : i + 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i < 3 && i + j > 3 ? j + 1 : j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void RemoveAt() { - Assert.IsTrue(list.Check(), "list check before remove"); + Assert.That(list.Check(), Is.True, "list check before remove"); list.RemoveAt(3); - Assert.IsTrue(list.Check(), "list check after remove"); + Assert.That(list.Check(), Is.True, "list check after remove"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i <= 3 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i <= 3 && i + j > 3 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i <= 3 ? i : i - 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i <= 3 && i + j > 3 ? j - 1 : j), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2119,15 +2458,18 @@ public void RemoveAt() [Test] public void RemoveInterval() { - Assert.IsTrue(list.Check(), "list check before remove"); + Assert.That(list.Check(), Is.True, "list check before remove"); list.RemoveInterval(3, 2); - Assert.IsTrue(list.Check(), "list check after remove"); + Assert.That(list.Check(), Is.True, "list check after remove"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i <= 3 ? i : i <= 5 ? 3 : i - 2, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(j == 0 ? 0 : i <= 3 && i + j > 4 ? j - 2 : i > 4 || i + j <= 3 ? j : j - 1, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i <= 3 ? i : i <= 5 ? 3 : i - 2), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(j == 0 ? 0 : i <= 3 && i + j > 4 ? j - 2 : i > 4 || i + j <= 3 ? j : j - 1), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2135,78 +2477,93 @@ public void RemoveInterval() [Test] public void InsertAtEnd() { - Assert.IsTrue(list.Check(), "list check before insert"); + Assert.That(list.Check(), Is.True, "list check before insert"); list.InsertLast(777); - Assert.IsTrue(list.Check(), "list check after insert"); + Assert.That(list.Check(), Is.True, "list check after insert"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void RemoveAtEnd() { - Assert.IsTrue(list.Check(), "list check before remove"); + Assert.That(list.Check(), Is.True, "list check before remove"); list.RemoveAt(5); - Assert.IsTrue(list.Check(), "list check after remove"); + Assert.That(list.Check(), Is.True, "list check after remove"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i <= 5 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i <= 5 && i + j > 5 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i <= 5 ? i : i - 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i <= 5 && i + j > 5 ? j - 1 : j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void InsertAtStart() { - Assert.IsTrue(list.Check(), "list check before insert"); + Assert.That(list.Check(), Is.True, "list check before insert"); list.Insert(0, 777); - Assert.IsTrue(list.Check(), "list check after insert"); + Assert.That(list.Check(), Is.True, "list check after insert"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i == 0 && j == 0 ? 0 : i + 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i == 0 && j == 0 ? 0 : i + 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void RemoveAtStart() { - Assert.IsTrue(list.Check(), "list check before remove"); + Assert.That(list.Check(), Is.True, "list check before remove"); list.RemoveAt(0); - Assert.IsTrue(list.Check(), "list check after remove"); + Assert.That(list.Check(), Is.True, "list check after remove"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i == 0 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i == 0 && j > 0 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i == 0 ? i : i - 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i == 0 && j > 0 ? j - 1 : j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void Clear() { - Assert.IsTrue(list.Check(), "list check before clear"); + Assert.That(list.Check(), Is.True, "list check before clear"); //for (int i = 0; i < 7; i++) //for (int j = 0; j < 7 - i; j++) //Console.WriteLine("// view[{0}][{1}] : {2}", i, j, ((HashedLinkedList) views[i][j]).GetHashCode()); views[2][3].Clear(); - Assert.IsTrue(list.Check(), "list check after clear"); + Assert.That(list.Check(), Is.True, "list check after clear"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i < 2 ? i : i < 6 ? 2 : i - 3, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(s(i, j), views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i < 2 ? i : i < 6 ? 2 : i - 3), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(s(i, j)), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2241,15 +2598,18 @@ public void InsertAll() { IList list2 = new HashedLinkedList(); for (int i = 0; i < 5; i++) { list2.Add(100 + i); } - Assert.IsTrue(list.Check(), "list check before insertAll"); + Assert.That(list.Check(), Is.True, "list check before insertAll"); list.InsertAll(3, list2); - Assert.IsTrue(list.Check(), "list check after insertAll"); + Assert.That(list.Check(), Is.True, "list check after insertAll"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 5, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i < 3 && i + j > 3 ? j + 5 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i < 3 || (i == 3 && j == 0) ? i : i + 5), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i < 3 && i + j > 3 ? j + 5 : j), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2259,15 +2619,18 @@ public void AddAll() { IList list2 = new HashedLinkedList(); for (int i = 0; i < 5; i++) { list2.Add(100 + i); } - Assert.IsTrue(list.Check(), "list check before AddAll"); + Assert.That(list.Check(), Is.True, "list check before AddAll"); list.View(1, 2).AddAll(list2); - Assert.IsTrue(list.Check(), "list check after AddAll"); + Assert.That(list.Check(), Is.True, "list check after AddAll"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 5, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i < 3 && i + j > 3 ? j + 5 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i < 3 || (i == 3 && j == 0) ? i : i + 5), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i < 3 && i + j > 3 ? j + 5 : j), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2287,7 +2650,7 @@ public void Remove() _ = (HashedLinkedList)list.View(i, j); list.Remove(3); - Assert.IsTrue(list.Check(), "list check after Remove, i=" + i + ", j=" + j); + Assert.That(list.Check(), Is.True, "list check after Remove, i=" + i + ", j=" + j); } } } @@ -2308,7 +2671,7 @@ public void RemoveAll1() _ = (HashedLinkedList)list.View(i, j); list.RemoveAll(list2); - Assert.IsTrue(list.Check(), "list check after RemoveAll, i=" + i + ", j=" + j); + Assert.That(list.Check(), Is.True, "list check after RemoveAll, i=" + i + ", j=" + j); } } } @@ -2316,136 +2679,142 @@ public void RemoveAll1() public void RemoveAll2() { IList list2 = new HashedLinkedList() { 1, 3, 4 }; - Assert.IsTrue(list.Check(), "list check before RemoveAll"); + Assert.That(list.Check(), Is.True, "list check before RemoveAll"); list.RemoveAll(list2); - Assert.AreEqual(0, views[0][0].Offset, "view [0][0] offset"); - Assert.AreEqual(0, views[0][1].Offset, "view [0][1] offset"); - Assert.AreEqual(0, views[0][2].Offset, "view [0][2] offset"); - Assert.AreEqual(0, views[0][3].Offset, "view [0][3] offset"); - Assert.AreEqual(0, views[0][4].Offset, "view [0][4] offset"); - Assert.AreEqual(0, views[0][5].Offset, "view [0][5] offset"); - Assert.AreEqual(0, views[0][6].Offset, "view [0][6] offset"); - Assert.AreEqual(1, views[1][0].Offset, "view [1][0] offset"); - Assert.AreEqual(1, views[1][1].Offset, "view [1][1] offset"); - Assert.AreEqual(1, views[1][2].Offset, "view [1][2] offset"); - Assert.AreEqual(1, views[1][3].Offset, "view [1][3] offset"); - Assert.AreEqual(1, views[1][4].Offset, "view [1][4] offset"); - Assert.AreEqual(1, views[1][5].Offset, "view [1][5] offset"); - Assert.AreEqual(1, views[2][0].Offset, "view [2][0] offset"); - Assert.AreEqual(1, views[2][1].Offset, "view [2][1] offset"); - Assert.AreEqual(1, views[2][2].Offset, "view [2][2] offset"); - Assert.AreEqual(1, views[2][3].Offset, "view [2][3] offset"); - Assert.AreEqual(1, views[2][4].Offset, "view [2][4] offset"); - Assert.AreEqual(2, views[3][0].Offset, "view [3][0] offset"); - Assert.AreEqual(2, views[3][1].Offset, "view [3][1] offset"); - Assert.AreEqual(2, views[3][2].Offset, "view [3][2] offset"); - Assert.AreEqual(2, views[3][3].Offset, "view [3][3] offset"); - Assert.AreEqual(2, views[4][0].Offset, "view [4][0] offset"); - Assert.AreEqual(2, views[4][1].Offset, "view [4][1] offset"); - Assert.AreEqual(2, views[4][2].Offset, "view [4][2] offset"); - Assert.AreEqual(2, views[5][0].Offset, "view [5][0] offset"); - Assert.AreEqual(2, views[5][1].Offset, "view [5][1] offset"); - Assert.AreEqual(3, views[6][0].Offset, "view [6][0] offset"); - - Assert.AreEqual(0, views[0][0].Count, "view [0][0] count"); - Assert.AreEqual(1, views[0][1].Count, "view [0][1] count"); - Assert.AreEqual(1, views[0][2].Count, "view [0][2] count"); - Assert.AreEqual(2, views[0][3].Count, "view [0][3] count"); - Assert.AreEqual(2, views[0][4].Count, "view [0][4] count"); - Assert.AreEqual(2, views[0][5].Count, "view [0][5] count"); - Assert.AreEqual(3, views[0][6].Count, "view [0][6] count"); - Assert.AreEqual(0, views[1][0].Count, "view [1][0] count"); - Assert.AreEqual(0, views[1][1].Count, "view [1][1] count"); - Assert.AreEqual(1, views[1][2].Count, "view [1][2] count"); - Assert.AreEqual(1, views[1][3].Count, "view [1][3] count"); - Assert.AreEqual(1, views[1][4].Count, "view [1][4] count"); - Assert.AreEqual(2, views[1][5].Count, "view [1][5] count"); - Assert.AreEqual(0, views[2][0].Count, "view [2][0] count"); - Assert.AreEqual(1, views[2][1].Count, "view [2][1] count"); - Assert.AreEqual(1, views[2][2].Count, "view [2][2] count"); - Assert.AreEqual(1, views[2][3].Count, "view [2][3] count"); - Assert.AreEqual(2, views[2][4].Count, "view [2][4] count"); - Assert.AreEqual(0, views[3][0].Count, "view [3][0] count"); - Assert.AreEqual(0, views[3][1].Count, "view [3][1] count"); - Assert.AreEqual(0, views[3][2].Count, "view [3][2] count"); - Assert.AreEqual(1, views[3][3].Count, "view [3][3] count"); - Assert.AreEqual(0, views[4][0].Count, "view [4][0] count"); - Assert.AreEqual(0, views[4][1].Count, "view [4][1] count"); - Assert.AreEqual(1, views[4][2].Count, "view [4][2] count"); - Assert.AreEqual(0, views[5][0].Count, "view [5][0] count"); - Assert.AreEqual(1, views[5][1].Count, "view [5][1] count"); - Assert.AreEqual(0, views[6][0].Count, "view [6][0] count"); - - Assert.IsTrue(list.Check(), "list check after RemoveAll"); + Assert.Multiple(() => + { + Assert.That(views[0][0].Offset, Is.EqualTo(0), "view [0][0] offset"); + Assert.That(views[0][1].Offset, Is.EqualTo(0), "view [0][1] offset"); + Assert.That(views[0][2].Offset, Is.EqualTo(0), "view [0][2] offset"); + Assert.That(views[0][3].Offset, Is.EqualTo(0), "view [0][3] offset"); + Assert.That(views[0][4].Offset, Is.EqualTo(0), "view [0][4] offset"); + Assert.That(views[0][5].Offset, Is.EqualTo(0), "view [0][5] offset"); + Assert.That(views[0][6].Offset, Is.EqualTo(0), "view [0][6] offset"); + Assert.That(views[1][0].Offset, Is.EqualTo(1), "view [1][0] offset"); + Assert.That(views[1][1].Offset, Is.EqualTo(1), "view [1][1] offset"); + Assert.That(views[1][2].Offset, Is.EqualTo(1), "view [1][2] offset"); + Assert.That(views[1][3].Offset, Is.EqualTo(1), "view [1][3] offset"); + Assert.That(views[1][4].Offset, Is.EqualTo(1), "view [1][4] offset"); + Assert.That(views[1][5].Offset, Is.EqualTo(1), "view [1][5] offset"); + Assert.That(views[2][0].Offset, Is.EqualTo(1), "view [2][0] offset"); + Assert.That(views[2][1].Offset, Is.EqualTo(1), "view [2][1] offset"); + Assert.That(views[2][2].Offset, Is.EqualTo(1), "view [2][2] offset"); + Assert.That(views[2][3].Offset, Is.EqualTo(1), "view [2][3] offset"); + Assert.That(views[2][4].Offset, Is.EqualTo(1), "view [2][4] offset"); + Assert.That(views[3][0].Offset, Is.EqualTo(2), "view [3][0] offset"); + Assert.That(views[3][1].Offset, Is.EqualTo(2), "view [3][1] offset"); + Assert.That(views[3][2].Offset, Is.EqualTo(2), "view [3][2] offset"); + Assert.That(views[3][3].Offset, Is.EqualTo(2), "view [3][3] offset"); + Assert.That(views[4][0].Offset, Is.EqualTo(2), "view [4][0] offset"); + Assert.That(views[4][1].Offset, Is.EqualTo(2), "view [4][1] offset"); + Assert.That(views[4][2].Offset, Is.EqualTo(2), "view [4][2] offset"); + Assert.That(views[5][0].Offset, Is.EqualTo(2), "view [5][0] offset"); + Assert.That(views[5][1].Offset, Is.EqualTo(2), "view [5][1] offset"); + Assert.That(views[6][0].Offset, Is.EqualTo(3), "view [6][0] offset"); + + Assert.That(views[0][0], Is.Empty, "view [0][0] count"); + Assert.That(views[0][1], Has.Count.EqualTo(1), "view [0][1] count"); + Assert.That(views[0][2], Has.Count.EqualTo(1), "view [0][2] count"); + Assert.That(views[0][3], Has.Count.EqualTo(2), "view [0][3] count"); + Assert.That(views[0][4], Has.Count.EqualTo(2), "view [0][4] count"); + Assert.That(views[0][5], Has.Count.EqualTo(2), "view [0][5] count"); + Assert.That(views[0][6], Has.Count.EqualTo(3), "view [0][6] count"); + Assert.That(views[1][0], Is.Empty, "view [1][0] count"); + Assert.That(views[1][1], Is.Empty, "view [1][1] count"); + Assert.That(views[1][2], Has.Count.EqualTo(1), "view [1][2] count"); + Assert.That(views[1][3], Has.Count.EqualTo(1), "view [1][3] count"); + Assert.That(views[1][4], Has.Count.EqualTo(1), "view [1][4] count"); + Assert.That(views[1][5], Has.Count.EqualTo(2), "view [1][5] count"); + Assert.That(views[2][0], Is.Empty, "view [2][0] count"); + Assert.That(views[2][1], Has.Count.EqualTo(1), "view [2][1] count"); + Assert.That(views[2][2], Has.Count.EqualTo(1), "view [2][2] count"); + Assert.That(views[2][3], Has.Count.EqualTo(1), "view [2][3] count"); + Assert.That(views[2][4], Has.Count.EqualTo(2), "view [2][4] count"); + Assert.That(views[3][0], Is.Empty, "view [3][0] count"); + Assert.That(views[3][1], Is.Empty, "view [3][1] count"); + Assert.That(views[3][2], Is.Empty, "view [3][2] count"); + Assert.That(views[3][3], Has.Count.EqualTo(1), "view [3][3] count"); + Assert.That(views[4][0], Is.Empty, "view [4][0] count"); + Assert.That(views[4][1], Is.Empty, "view [4][1] count"); + Assert.That(views[4][2], Has.Count.EqualTo(1), "view [4][2] count"); + Assert.That(views[5][0], Is.Empty, "view [5][0] count"); + Assert.That(views[5][1], Has.Count.EqualTo(1), "view [5][1] count"); + Assert.That(views[6][0], Is.Empty, "view [6][0] count"); + + Assert.That(list.Check(), Is.True, "list check after RemoveAll"); + }); } [Test] public void RetainAll() { IList list2 = new HashedLinkedList() { 2, 4, 5 }; - Assert.IsTrue(list.Check(), "list check before RetainAll"); + Assert.That(list.Check(), Is.True, "list check before RetainAll"); list.RetainAll(list2); - Assert.AreEqual(0, views[0][0].Offset, "view [0][0] offset"); - Assert.AreEqual(0, views[0][1].Offset, "view [0][1] offset"); - Assert.AreEqual(0, views[0][2].Offset, "view [0][2] offset"); - Assert.AreEqual(0, views[0][3].Offset, "view [0][3] offset"); - Assert.AreEqual(0, views[0][4].Offset, "view [0][4] offset"); - Assert.AreEqual(0, views[0][5].Offset, "view [0][5] offset"); - Assert.AreEqual(0, views[0][6].Offset, "view [0][6] offset"); - Assert.AreEqual(0, views[1][0].Offset, "view [1][0] offset"); - Assert.AreEqual(0, views[1][1].Offset, "view [1][1] offset"); - Assert.AreEqual(0, views[1][2].Offset, "view [1][2] offset"); - Assert.AreEqual(0, views[1][3].Offset, "view [1][3] offset"); - Assert.AreEqual(0, views[1][4].Offset, "view [1][4] offset"); - Assert.AreEqual(0, views[1][5].Offset, "view [1][5] offset"); - Assert.AreEqual(0, views[2][0].Offset, "view [2][0] offset"); - Assert.AreEqual(0, views[2][1].Offset, "view [2][1] offset"); - Assert.AreEqual(0, views[2][2].Offset, "view [2][2] offset"); - Assert.AreEqual(0, views[2][3].Offset, "view [2][3] offset"); - Assert.AreEqual(0, views[2][4].Offset, "view [2][4] offset"); - Assert.AreEqual(1, views[3][0].Offset, "view [3][0] offset"); - Assert.AreEqual(1, views[3][1].Offset, "view [3][1] offset"); - Assert.AreEqual(1, views[3][2].Offset, "view [3][2] offset"); - Assert.AreEqual(1, views[3][3].Offset, "view [3][3] offset"); - Assert.AreEqual(1, views[4][0].Offset, "view [4][0] offset"); - Assert.AreEqual(1, views[4][1].Offset, "view [4][1] offset"); - Assert.AreEqual(1, views[4][2].Offset, "view [4][2] offset"); - Assert.AreEqual(2, views[5][0].Offset, "view [5][0] offset"); - Assert.AreEqual(2, views[5][1].Offset, "view [5][1] offset"); - Assert.AreEqual(3, views[6][0].Offset, "view [6][0] offset"); - - Assert.AreEqual(0, views[0][0].Count, "view [0][0] count"); - Assert.AreEqual(0, views[0][1].Count, "view [0][1] count"); - Assert.AreEqual(0, views[0][2].Count, "view [0][2] count"); - Assert.AreEqual(1, views[0][3].Count, "view [0][3] count"); - Assert.AreEqual(1, views[0][4].Count, "view [0][4] count"); - Assert.AreEqual(2, views[0][5].Count, "view [0][5] count"); - Assert.AreEqual(3, views[0][6].Count, "view [0][6] count"); - Assert.AreEqual(0, views[1][0].Count, "view [1][0] count"); - Assert.AreEqual(0, views[1][1].Count, "view [1][1] count"); - Assert.AreEqual(1, views[1][2].Count, "view [1][2] count"); - Assert.AreEqual(1, views[1][3].Count, "view [1][3] count"); - Assert.AreEqual(2, views[1][4].Count, "view [1][4] count"); - Assert.AreEqual(3, views[1][5].Count, "view [1][5] count"); - Assert.AreEqual(0, views[2][0].Count, "view [2][0] count"); - Assert.AreEqual(1, views[2][1].Count, "view [2][1] count"); - Assert.AreEqual(1, views[2][2].Count, "view [2][2] count"); - Assert.AreEqual(2, views[2][3].Count, "view [2][3] count"); - Assert.AreEqual(3, views[2][4].Count, "view [2][4] count"); - Assert.AreEqual(0, views[3][0].Count, "view [3][0] count"); - Assert.AreEqual(0, views[3][1].Count, "view [3][1] count"); - Assert.AreEqual(1, views[3][2].Count, "view [3][2] count"); - Assert.AreEqual(2, views[3][3].Count, "view [3][3] count"); - Assert.AreEqual(0, views[4][0].Count, "view [4][0] count"); - Assert.AreEqual(1, views[4][1].Count, "view [4][1] count"); - Assert.AreEqual(2, views[4][2].Count, "view [4][2] count"); - Assert.AreEqual(0, views[5][0].Count, "view [5][0] count"); - Assert.AreEqual(1, views[5][1].Count, "view [5][1] count"); - Assert.AreEqual(0, views[6][0].Count, "view [6][0] count"); - - - Assert.IsTrue(list.Check(), "list check after RetainAll"); + Assert.Multiple(() => + { + Assert.That(views[0][0].Offset, Is.EqualTo(0), "view [0][0] offset"); + Assert.That(views[0][1].Offset, Is.EqualTo(0), "view [0][1] offset"); + Assert.That(views[0][2].Offset, Is.EqualTo(0), "view [0][2] offset"); + Assert.That(views[0][3].Offset, Is.EqualTo(0), "view [0][3] offset"); + Assert.That(views[0][4].Offset, Is.EqualTo(0), "view [0][4] offset"); + Assert.That(views[0][5].Offset, Is.EqualTo(0), "view [0][5] offset"); + Assert.That(views[0][6].Offset, Is.EqualTo(0), "view [0][6] offset"); + Assert.That(views[1][0].Offset, Is.EqualTo(0), "view [1][0] offset"); + Assert.That(views[1][1].Offset, Is.EqualTo(0), "view [1][1] offset"); + Assert.That(views[1][2].Offset, Is.EqualTo(0), "view [1][2] offset"); + Assert.That(views[1][3].Offset, Is.EqualTo(0), "view [1][3] offset"); + Assert.That(views[1][4].Offset, Is.EqualTo(0), "view [1][4] offset"); + Assert.That(views[1][5].Offset, Is.EqualTo(0), "view [1][5] offset"); + Assert.That(views[2][0].Offset, Is.EqualTo(0), "view [2][0] offset"); + Assert.That(views[2][1].Offset, Is.EqualTo(0), "view [2][1] offset"); + Assert.That(views[2][2].Offset, Is.EqualTo(0), "view [2][2] offset"); + Assert.That(views[2][3].Offset, Is.EqualTo(0), "view [2][3] offset"); + Assert.That(views[2][4].Offset, Is.EqualTo(0), "view [2][4] offset"); + Assert.That(views[3][0].Offset, Is.EqualTo(1), "view [3][0] offset"); + Assert.That(views[3][1].Offset, Is.EqualTo(1), "view [3][1] offset"); + Assert.That(views[3][2].Offset, Is.EqualTo(1), "view [3][2] offset"); + Assert.That(views[3][3].Offset, Is.EqualTo(1), "view [3][3] offset"); + Assert.That(views[4][0].Offset, Is.EqualTo(1), "view [4][0] offset"); + Assert.That(views[4][1].Offset, Is.EqualTo(1), "view [4][1] offset"); + Assert.That(views[4][2].Offset, Is.EqualTo(1), "view [4][2] offset"); + Assert.That(views[5][0].Offset, Is.EqualTo(2), "view [5][0] offset"); + Assert.That(views[5][1].Offset, Is.EqualTo(2), "view [5][1] offset"); + Assert.That(views[6][0].Offset, Is.EqualTo(3), "view [6][0] offset"); + + Assert.That(views[0][0], Is.Empty, "view [0][0] count"); + Assert.That(views[0][1], Is.Empty, "view [0][1] count"); + Assert.That(views[0][2], Is.Empty, "view [0][2] count"); + Assert.That(views[0][3], Has.Count.EqualTo(1), "view [0][3] count"); + Assert.That(views[0][4], Has.Count.EqualTo(1), "view [0][4] count"); + Assert.That(views[0][5], Has.Count.EqualTo(2), "view [0][5] count"); + Assert.That(views[0][6], Has.Count.EqualTo(3), "view [0][6] count"); + Assert.That(views[1][0], Is.Empty, "view [1][0] count"); + Assert.That(views[1][1], Is.Empty, "view [1][1] count"); + Assert.That(views[1][2], Has.Count.EqualTo(1), "view [1][2] count"); + Assert.That(views[1][3], Has.Count.EqualTo(1), "view [1][3] count"); + Assert.That(views[1][4], Has.Count.EqualTo(2), "view [1][4] count"); + Assert.That(views[1][5], Has.Count.EqualTo(3), "view [1][5] count"); + Assert.That(views[2][0], Is.Empty, "view [2][0] count"); + Assert.That(views[2][1], Has.Count.EqualTo(1), "view [2][1] count"); + Assert.That(views[2][2], Has.Count.EqualTo(1), "view [2][2] count"); + Assert.That(views[2][3], Has.Count.EqualTo(2), "view [2][3] count"); + Assert.That(views[2][4], Has.Count.EqualTo(3), "view [2][4] count"); + Assert.That(views[3][0], Is.Empty, "view [3][0] count"); + Assert.That(views[3][1], Is.Empty, "view [3][1] count"); + Assert.That(views[3][2], Has.Count.EqualTo(1), "view [3][2] count"); + Assert.That(views[3][3], Has.Count.EqualTo(2), "view [3][3] count"); + Assert.That(views[4][0], Is.Empty, "view [4][0] count"); + Assert.That(views[4][1], Has.Count.EqualTo(1), "view [4][1] count"); + Assert.That(views[4][2], Has.Count.EqualTo(2), "view [4][2] count"); + Assert.That(views[5][0], Is.Empty, "view [5][0] count"); + Assert.That(views[5][1], Has.Count.EqualTo(1), "view [5][1] count"); + Assert.That(views[6][0], Is.Empty, "view [6][0] count"); + + + Assert.That(list.Check(), Is.True, "list check after RetainAll"); + }); } [Test] @@ -2460,7 +2829,7 @@ public void RemoveAllCopies() list.AddAll(list2); _ = (HashedLinkedList)list.View(i, j); list.RemoveAllCopies(2); - Assert.IsTrue(list.Check(), "list check after RemoveAllCopies, i=" + i + ", j=" + j); + Assert.That(list.Check(), Is.True, "list check after RemoveAllCopies, i=" + i + ", j=" + j); } } } @@ -2482,14 +2851,14 @@ private void checkDisposed(bool reverse, int start, int count) { Assert.Fail("view[" + i + "][" + j + "] threw"); } - Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] size"); + Assert.That(views[i][j], Has.Count.EqualTo(j), "view[" + i + "][" + j + "] size"); if (reverse && ((j > 0 && start <= i && start + count >= i + j) || (j == 0 && start < i && start + count > i))) { - Assert.AreEqual(start + (start + count - i - j), views[i][j].Offset, "view[" + i + "][" + j + "] offset (mirrored)"); + Assert.That(views[i][j].Offset, Is.EqualTo(start + (start + count - i - j)), "view[" + i + "][" + j + "] offset (mirrored)"); } else { - Assert.AreEqual(i, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j].Offset, Is.EqualTo(i), "view[" + i + "][" + j + "] offset"); } } else @@ -2510,9 +2879,9 @@ public void Reverse() { int start = 2, count = 3; IList list2 = list.View(start, count); - Assert.IsTrue(list.Check(), "list check before Reverse"); + Assert.That(list.Check(), Is.True, "list check before Reverse"); list2.Reverse(); - Assert.IsTrue(list.Check(), "list check after Reverse"); + Assert.That(list.Check(), Is.True, "list check after Reverse"); checkDisposed(true, start, count); } @@ -2521,9 +2890,9 @@ public void Sort() { int start = 2, count = 3; IList list2 = list.View(start, count); - Assert.IsTrue(list.Check(), "list check before Sort"); + Assert.That(list.Check(), Is.True, "list check before Sort"); list2.Sort(); - Assert.IsTrue(list.Check(), "list check after Sort"); + Assert.That(list.Check(), Is.True, "list check after Sort"); checkDisposed(false, start, count); } [Test] @@ -2531,9 +2900,9 @@ public void Shuffle() { int start = 2, count = 3; IList list2 = list.View(start, count); - Assert.IsTrue(list.Check(), "list check before Shuffle"); + Assert.That(list.Check(), Is.True, "list check before Shuffle"); list2.Shuffle(); - Assert.IsTrue(list.Check(), "list check after Shuffle"); + Assert.That(list.Check(), Is.True, "list check after Shuffle"); checkDisposed(false, start, count); } @@ -2547,7 +2916,7 @@ namespace HashingAndEquals [TestFixture] public class ISequenced { - private ISequenced dit, dat, dut; + private HashedLinkedList dit, dat, dut; [SetUp] @@ -2562,7 +2931,7 @@ public void Init() [Test] public void EmptyEmpty() { - Assert.IsTrue(dit.SequencedEquals(dat)); + Assert.That(dit.SequencedEquals(dat), Is.True); } @@ -2570,23 +2939,29 @@ public void EmptyEmpty() public void EmptyNonEmpty() { dit.Add(3); - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsFalse(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dat.SequencedEquals(dit), Is.False); + }); } [Test] public void HashVal() { - Assert.AreEqual(CHC.SequencedHashCode(), dit.GetSequencedHashCode()); + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode())); dit.Add(3); - Assert.AreEqual(CHC.SequencedHashCode(3), dit.GetSequencedHashCode()); + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(3))); dit.Add(7); - Assert.AreEqual(CHC.SequencedHashCode(3, 7), dit.GetSequencedHashCode()); - Assert.AreEqual(CHC.SequencedHashCode(), dut.GetSequencedHashCode()); + Assert.Multiple(() => + { + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(3, 7))); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode())); + }); dut.Add(7); - Assert.AreEqual(CHC.SequencedHashCode(7), dut.GetSequencedHashCode()); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(7))); dut.Add(3); - Assert.AreEqual(CHC.SequencedHashCode(7, 3), dut.GetSequencedHashCode()); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(7, 3))); } @@ -2595,8 +2970,11 @@ public void EqualHashButDifferent() { dit.Add(0); dit.Add(31); dat.Add(1); dat.Add(0); - Assert.AreEqual(dit.GetSequencedHashCode(), dat.GetSequencedHashCode()); - Assert.IsFalse(dit.SequencedEquals(dat)); + Assert.Multiple(() => + { + Assert.That(dat.GetSequencedHashCode(), Is.EqualTo(dit.GetSequencedHashCode())); + Assert.That(dit.SequencedEquals(dat), Is.False); + }); } @@ -2606,11 +2984,17 @@ public void Normal() dit.Add(3); dit.Add(7); dat.Add(3); - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsFalse(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dat.SequencedEquals(dit), Is.False); + }); dat.Add(7); - Assert.IsTrue(dit.SequencedEquals(dat)); - Assert.IsTrue(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.True); + Assert.That(dat.SequencedEquals(dit), Is.True); + }); } @@ -2619,32 +3003,38 @@ public void WrongOrder() { dit.Add(3); dut.Add(3); - Assert.IsTrue(dit.SequencedEquals(dut)); - Assert.IsTrue(dut.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dut), Is.True); + Assert.That(dut.SequencedEquals(dit), Is.True); + }); dit.Add(7); ((HashedLinkedList)dut).InsertFirst(7); - Assert.IsFalse(dit.SequencedEquals(dut)); - Assert.IsFalse(dut.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dut), Is.False); + Assert.That(dut.SequencedEquals(dit), Is.False); + }); } [Test] public void Reflexive() { - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); dit.Add(3); - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); dit.Add(7); - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); } [TearDown] public void Dispose() { - dit = null; - dat = null; - dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); } } @@ -2653,7 +3043,7 @@ public void Dispose() [TestFixture] public class IEditableCollection { - private ICollection dit, dat, dut; + private HashedLinkedList dit, dat, dut; [SetUp] @@ -2668,7 +3058,7 @@ public void Init() [Test] public void EmptyEmpty() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); + Assert.That(dit.UnsequencedEquals(dat), Is.True); } @@ -2676,24 +3066,30 @@ public void EmptyEmpty() public void EmptyNonEmpty() { dit.Add(3); - Assert.IsFalse(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.False); + Assert.That(dat.UnsequencedEquals(dit), Is.False); + }); } [Test] public void HashVal() { - Assert.AreEqual(CHC.UnsequencedHashCode(), dit.GetUnsequencedHashCode()); + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode())); dit.Add(3); - Assert.AreEqual(CHC.UnsequencedHashCode(3), dit.GetUnsequencedHashCode()); + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3))); dit.Add(7); - Assert.AreEqual(CHC.UnsequencedHashCode(3, 7), dit.GetUnsequencedHashCode()); - Assert.AreEqual(CHC.UnsequencedHashCode(), dut.GetUnsequencedHashCode()); + Assert.Multiple(() => + { + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3, 7))); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode())); + }); dut.Add(3); - Assert.AreEqual(CHC.UnsequencedHashCode(3), dut.GetUnsequencedHashCode()); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3))); dut.Add(7); - Assert.AreEqual(CHC.UnsequencedHashCode(7, 3), dut.GetUnsequencedHashCode()); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(7, 3))); } @@ -2702,8 +3098,11 @@ public void EqualHashButDifferent() { dit.Add(-1657792980); dit.Add(-1570288808); dat.Add(1862883298); dat.Add(-272461342); - Assert.AreEqual(dit.GetUnsequencedHashCode(), dat.GetUnsequencedHashCode()); - Assert.IsFalse(dit.UnsequencedEquals(dat)); + Assert.Multiple(() => + { + Assert.That(dat.GetUnsequencedHashCode(), Is.EqualTo(dit.GetUnsequencedHashCode())); + Assert.That(dit.UnsequencedEquals(dat), Is.False); + }); } @@ -2713,11 +3112,17 @@ public void Normal() dit.Add(3); dit.Add(7); dat.Add(3); - Assert.IsFalse(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.False); + Assert.That(dat.UnsequencedEquals(dit), Is.False); + }); dat.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsTrue(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dat.UnsequencedEquals(dit), Is.True); + }); } @@ -2726,32 +3131,38 @@ public void WrongOrder() { dit.Add(3); dut.Add(3); - Assert.IsTrue(dit.UnsequencedEquals(dut)); - Assert.IsTrue(dut.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dut), Is.True); + Assert.That(dut.UnsequencedEquals(dit), Is.True); + }); dit.Add(7); dut.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dut)); - Assert.IsTrue(dut.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dut), Is.True); + Assert.That(dut.UnsequencedEquals(dit), Is.True); + }); } [Test] public void Reflexive() { - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); dit.Add(3); - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); dit.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); } [TearDown] public void Dispose() { - dit = null; - dat = null; - dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); } } @@ -2760,9 +3171,9 @@ public void Dispose() [TestFixture] public class MultiLevelUnorderedOfUnOrdered { - private ICollection dit, dat, dut; + private HashedLinkedList dit, dat, dut; - private ICollection> Dit, Dat, Dut; + private HashedLinkedList> Dit, Dat, Dut; [SetUp] @@ -2783,8 +3194,11 @@ public void Init() [Test] public void Check() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dit.UnsequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dit.UnsequencedEquals(dut), Is.False); + }); } @@ -2793,16 +3207,23 @@ public void Multi() { Dit.Add(dit); Dit.Add(dut); Dit.Add(dit); Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); - Assert.IsTrue(Dit.UnsequencedEquals(Dat)); - Assert.IsFalse(Dit.UnsequencedEquals(Dut)); + Assert.Multiple(() => + { + Assert.That(Dit.UnsequencedEquals(Dat), Is.True); + Assert.That(Dit.UnsequencedEquals(Dut), Is.False); + }); } [TearDown] public void Dispose() { - dit = dat = dut = null; - Dit = Dat = Dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); } } @@ -2811,9 +3232,9 @@ public void Dispose() [TestFixture] public class MultiLevelOrderedOfUnOrdered { - private ICollection dit, dat, dut; + private HashedLinkedList dit, dat, dut; - private ISequenced> Dit, Dat, Dut; + private HashedLinkedList> Dit, Dat, Dut; [SetUp] @@ -2834,8 +3255,11 @@ public void Init() [Test] public void Check() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dit.UnsequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dit.UnsequencedEquals(dut), Is.False); + }); } @@ -2845,16 +3269,23 @@ public void Multi() Dit.Add(dit); Dit.Add(dut); Dit.Add(dit); Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); Dut.Add(dit); Dut.Add(dut); Dut.Add(dat); - Assert.IsFalse(Dit.SequencedEquals(Dat)); - Assert.IsTrue(Dit.SequencedEquals(Dut)); + Assert.Multiple(() => + { + Assert.That(Dit.SequencedEquals(Dat), Is.False); + Assert.That(Dit.SequencedEquals(Dut), Is.True); + }); } [TearDown] public void Dispose() { - dit = dat = dut = null; - Dit = Dat = Dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); } } @@ -2863,9 +3294,9 @@ public void Dispose() [TestFixture] public class MultiLevelUnOrderedOfOrdered { - private ISequenced dit, dat, dut, dot; + private HashedLinkedList dit, dat, dut, dot; - private ICollection> Dit, Dat, Dut, Dot; + private HashedLinkedList> Dit, Dat, Dut, Dot; [SetUp] @@ -2889,9 +3320,12 @@ public void Init() [Test] public void Check() { - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsTrue(dit.SequencedEquals(dot)); - Assert.IsFalse(dit.SequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dit.SequencedEquals(dot), Is.True); + Assert.That(dit.SequencedEquals(dut), Is.False); + }); } @@ -2902,17 +3336,26 @@ public void Multi() Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); Dut.Add(dot); Dut.Add(dut); Dut.Add(dit); Dot.Add(dit); Dot.Add(dit); Dot.Add(dut); - Assert.IsTrue(Dit.UnsequencedEquals(Dut)); - Assert.IsFalse(Dit.UnsequencedEquals(Dat)); - Assert.IsTrue(Dit.UnsequencedEquals(Dot)); + Assert.Multiple(() => + { + Assert.That(Dit.UnsequencedEquals(Dut), Is.True); + Assert.That(Dit.UnsequencedEquals(Dat), Is.False); + Assert.That(Dit.UnsequencedEquals(Dot), Is.True); + }); } [TearDown] public void Dispose() { - dit = dat = dut = dot = null; - Dit = Dat = Dut = Dot = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + dot.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); + Dot.Dispose(); } } @@ -2921,9 +3364,9 @@ public void Dispose() [TestFixture] public class MultiLevelOrderedOfOrdered { - private ISequenced dit, dat, dut, dot; + private HashedLinkedList dit, dat, dut, dot; - private ISequenced> Dit, Dat, Dut, Dot; + private HashedLinkedList> Dit, Dat, Dut, Dot; [SetUp] @@ -2947,9 +3390,12 @@ public void Init() [Test] public void Check() { - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsTrue(dit.SequencedEquals(dot)); - Assert.IsFalse(dit.SequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dit.SequencedEquals(dot), Is.True); + Assert.That(dit.SequencedEquals(dut), Is.False); + }); } @@ -2960,17 +3406,26 @@ public void Multi() Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); // {{3},{2,1},{1,2}} Dut.Add(dot); Dut.Add(dut); Dut.Add(dit); // {{2,1},{3}} Dot.Add(dit); Dot.Add(dit); Dot.Add(dut); // {{2,1},{3}} - Assert.IsTrue(Dit.SequencedEquals(Dut)); - Assert.IsFalse(Dit.SequencedEquals(Dat)); - Assert.IsTrue(Dit.SequencedEquals(Dot)); + Assert.Multiple(() => + { + Assert.That(Dit.SequencedEquals(Dut), Is.True); + Assert.That(Dit.SequencedEquals(Dat), Is.False); + Assert.That(Dit.SequencedEquals(Dot), Is.True); + }); } [TearDown] public void Dispose() { - dit = dat = dut = dot = null; - Dit = Dat = Dut = Dot = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + dot.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); + Dot.Dispose(); } } } diff --git a/C5.Tests/LinkedLists/LinkedListTest.cs b/C5.Tests/LinkedLists/LinkedListTest.cs index 15dbff0f..c4f36b45 100644 --- a/C5.Tests/LinkedLists/LinkedListTest.cs +++ b/C5.Tests/LinkedLists/LinkedListTest.cs @@ -3,13 +3,12 @@ using NUnit.Framework; using System; +using System.Linq; using SCG = System.Collections.Generic; namespace C5.Tests.linkedlists.plain { - using CollectionOfInt = LinkedList; - [TestFixture] public class GenericTesters { @@ -17,26 +16,17 @@ public class GenericTesters [Test] public void TestEvents() { - CollectionOfInt factory() { return new CollectionOfInt(TenEqualityComparer.Default); } - new C5.Tests.Templates.Events.ListTester().Test(factory); - new C5.Tests.Templates.Events.QueueTester().Test(factory); - new C5.Tests.Templates.Events.StackTester().Test(factory); + LinkedList factory() { return new LinkedList(TenEqualityComparer.Default); } + new C5.Tests.Templates.Events.ListTester>().Test(factory); + new C5.Tests.Templates.Events.QueueTester>().Test(factory); + new C5.Tests.Templates.Events.StackTester>().Test(factory); } - //[Test] - //public void Extensible() - //{ - // C5.Tests.Templates.Extensible.Clone.Tester(); - // C5.Tests.Templates.Extensible.Clone.ViewTester(); - // C5.Tests.Templates.Extensible.Serialization.Tester(); - // C5.Tests.Templates.Extensible.Serialization.ViewTester(); - //} - [Test] public void List() { - C5.Tests.Templates.List.Dispose.Tester(); - C5.Tests.Templates.List.SCG_IList.Tester(); + Templates.List.Dispose.Tester>(); + Templates.List.SCG_IList.Tester>(); } } @@ -68,34 +58,52 @@ public void Init() [Test] public void All() { - Assert.IsTrue(list.All(always)); - Assert.IsTrue(list.All(never)); - Assert.IsTrue(list.All(even)); + Assert.Multiple(() => + { + Assert.That(list.All(always), Is.True); + Assert.That(list.All(never), Is.True); + Assert.That(list.All(even), Is.True); + }); list.Add(8); - Assert.IsTrue(list.All(always)); - Assert.IsFalse(list.All(never)); - Assert.IsTrue(list.All(even)); + Assert.Multiple(() => + { + Assert.That(list.All(always), Is.True); + Assert.That(list.All(never), Is.False); + Assert.That(list.All(even), Is.True); + }); list.Add(5); - Assert.IsTrue(list.All(always)); - Assert.IsFalse(list.All(never)); - Assert.IsFalse(list.All(even)); + Assert.Multiple(() => + { + Assert.That(list.All(always), Is.True); + Assert.That(list.All(never), Is.False); + Assert.That(list.All(even), Is.False); + }); } [Test] public void Exists() { - Assert.IsFalse(list.Exists(always)); - Assert.IsFalse(list.Exists(never)); - Assert.IsFalse(list.Exists(even)); + Assert.Multiple(() => + { + Assert.That(list.Exists(always), Is.False); + Assert.That(list.Exists(never), Is.False); + Assert.That(list.Exists(even), Is.False); + }); list.Add(5); - Assert.IsTrue(list.Exists(always)); - Assert.IsFalse(list.Exists(never)); - Assert.IsFalse(list.Exists(even)); + Assert.Multiple(() => + { + Assert.That(list.Exists(always), Is.True); + Assert.That(list.Exists(never), Is.False); + Assert.That(list.Exists(even), Is.False); + }); list.Add(8); - Assert.IsTrue(list.Exists(always)); - Assert.IsFalse(list.Exists(never)); - Assert.IsTrue(list.Exists(even)); + Assert.Multiple(() => + { + Assert.That(list.Exists(always), Is.True); + Assert.That(list.Exists(never), Is.False); + Assert.That(list.Exists(even), Is.True); + }); } @@ -106,16 +114,16 @@ public void Apply() void a(int i) { sum = i + 10 * sum; } list.Apply(a); - Assert.AreEqual(0, sum); + Assert.That(sum, Is.EqualTo(0)); sum = 0; list.Add(5); list.Add(8); list.Add(7); list.Add(5); list.Apply(a); - Assert.AreEqual(5875, sum); + Assert.That(sum, Is.EqualTo(5875)); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } @@ -135,7 +143,7 @@ public void Empty() { SCG.IEnumerator e = list.GetEnumerator(); - Assert.IsFalse(e.MoveNext()); + Assert.That(e.MoveNext(), Is.False); } @@ -151,19 +159,22 @@ public void Normal() SCG.IEnumerator e = list.GetEnumerator(); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(5, e.Current); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(8, e.Current); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(5, e.Current); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(5, e.Current); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(10, e.Current); - Assert.IsTrue(e.MoveNext()); - Assert.AreEqual(1, e.Current); - Assert.IsFalse(e.MoveNext()); + Assert.Multiple(() => + { + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(5)); + }); + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(8)); + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(5)); + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(5)); + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(10)); + Assert.That(e.MoveNext(), Is.True); + Assert.That(e.Current, Is.EqualTo(1)); + Assert.That(e.MoveNext(), Is.False); } @@ -199,7 +210,7 @@ public void MoveNextAfterUpdate() [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } } @@ -217,12 +228,15 @@ public class Formatting [Test] public void Format() { - Assert.AreEqual("[ ]", coll.ToString()); - coll.AddAll(new int[] { -4, 28, 129, 65530 }); - Assert.AreEqual("[ -4, 28, 129, 65530 ]", coll.ToString()); - Assert.AreEqual("[ -4, 1C, 81, FFFA ]", coll.ToString(null, rad16)); - Assert.AreEqual("[ -4, 28, 129... ]", coll.ToString("L14", null)); - Assert.AreEqual("[ -4, 1C, 81... ]", coll.ToString("L14", rad16)); + Assert.That(coll.ToString(), Is.EqualTo("[ ]")); + coll.AddAll([-4, 28, 129, 65530]); + Assert.Multiple(() => + { + Assert.That(coll.ToString(), Is.EqualTo("[ -4, 28, 129, 65530 ]")); + Assert.That(coll.ToString(null, rad16), Is.EqualTo("[ -4, 1C, 81, FFFA ]")); + Assert.That(coll.ToString("L14", null), Is.EqualTo("[ -4, 28, 129... ]")); + Assert.That(coll.ToString("L14", rad16), Is.EqualTo("[ -4, 1C, 81... ]")); + }); } } @@ -245,7 +259,7 @@ public void NullEqualityComparerinConstructor1() public void Choose() { list.Add(7); - Assert.AreEqual(7, list.Choose()); + Assert.That(list.Choose(), Is.EqualTo(7)); } [Test] @@ -257,17 +271,20 @@ public void BadChoose() [Test] public void CountEtAl() { - Assert.AreEqual(0, list.Count); - Assert.IsTrue(list.IsEmpty); - Assert.IsTrue(list.AllowsDuplicates); + Assert.That(list, Is.Empty); + Assert.Multiple(() => + { + Assert.That(list.IsEmpty, Is.True); + Assert.That(list.AllowsDuplicates, Is.True); + }); list.Add(5); - Assert.AreEqual(1, list.Count); - Assert.IsFalse(list.IsEmpty); + Assert.That(list, Has.Count.EqualTo(1)); + Assert.That(list.IsEmpty, Is.False); list.Add(5); - Assert.AreEqual(2, list.Count); - Assert.IsFalse(list.IsEmpty); + Assert.That(list, Has.Count.EqualTo(2)); + Assert.That(list.IsEmpty, Is.False); list.Add(8); - Assert.AreEqual(3, list.Count); + Assert.That(list, Has.Count.EqualTo(3)); } @@ -276,18 +293,21 @@ public void AddAll() { list.Add(3); list.Add(4); list.Add(5); - LinkedList list2 = new LinkedList(); + LinkedList list2 = new(); list2.AddAll(list); - Assert.IsTrue(IC.Eq(list2, 3, 4, 5)); + Assert.That(IC.Eq(list2, 3, 4, 5), Is.True); list.AddAll(list2); - Assert.IsTrue(IC.Eq(list2, 3, 4, 5)); - Assert.IsTrue(IC.Eq(list, 3, 4, 5, 3, 4, 5)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list2, 3, 4, 5), Is.True); + Assert.That(IC.Eq(list, 3, 4, 5, 3, 4, 5), Is.True); + }); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } [TestFixture] @@ -304,48 +324,54 @@ public void Init() } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } [Test] public void Find() { - Assert.IsFalse(list.Find(pred, out int i)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(list.Find(pred, out i)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.IsTrue(list.Find(pred, out i)); - Assert.AreEqual(45, i); + Assert.That(list.Find(pred, out int i), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(list.Find(pred, out i), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.Multiple(() => + { + Assert.That(list.Find(pred, out i), Is.True); + Assert.That(i, Is.EqualTo(45)); + }); } [Test] public void FindLast() { - Assert.IsFalse(list.FindLast(pred, out int i)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(list.FindLast(pred, out i)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.IsTrue(list.FindLast(pred, out i)); - Assert.AreEqual(675, i); + Assert.That(list.FindLast(pred, out int i), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(list.FindLast(pred, out i), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.Multiple(() => + { + Assert.That(list.FindLast(pred, out i), Is.True); + Assert.That(i, Is.EqualTo(675)); + }); } [Test] public void FindIndex() { - Assert.IsFalse(0 <= list.FindIndex(pred)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(0 <= list.FindIndex(pred)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.AreEqual(4, list.FindIndex(pred)); + Assert.That(0 <= list.FindIndex(pred), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(0 <= list.FindIndex(pred), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.That(list.FindIndex(pred), Is.EqualTo(4)); } [Test] public void FindLastIndex() { - Assert.IsFalse(0 <= list.FindLastIndex(pred)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(0 <= list.FindLastIndex(pred)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.AreEqual(6, list.FindLastIndex(pred)); + Assert.That(0 <= list.FindLastIndex(pred), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(0 <= list.FindLastIndex(pred), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.That(list.FindLastIndex(pred), Is.EqualTo(6)); } } @@ -358,16 +384,22 @@ public class UniqueItems public void Init() { list = new LinkedList(); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } [Test] public void Test() { - Assert.IsTrue(IC.SetEq(list.UniqueItems())); - Assert.IsTrue(IC.SetEq(list.ItemMultiplicities())); - list.AddAll(new int[] { 7, 9, 7 }); - Assert.IsTrue(IC.SetEq(list.UniqueItems(), 7, 9)); - Assert.IsTrue(IC.SetEq(list.ItemMultiplicities(), 7, 2, 9, 1)); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(list.UniqueItems()), Is.True); + Assert.That(IC.SetEq(list.ItemMultiplicities()), Is.True); + }); + list.AddAll([7, 9, 7]); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(list.UniqueItems(), 7, 9), Is.True); + Assert.That(IC.SetEq(list.ItemMultiplicities(), 7, 2, 9, 1), Is.True); + }); } } @@ -391,7 +423,7 @@ public void Init() [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } private string aeq(int[] a, params int[] b) @@ -416,10 +448,10 @@ private string aeq(int[] a, params int[] b) [Test] public void ToArray() { - Assert.AreEqual("Alles klar", aeq(list.ToArray())); + Assert.That(aeq(list.ToArray()), Is.EqualTo("Alles klar")); list.Add(7); list.Add(7); - Assert.AreEqual("Alles klar", aeq(list.ToArray(), 7, 7)); + Assert.That(aeq(list.ToArray(), 7, 7), Is.EqualTo("Alles klar")); } @@ -427,19 +459,19 @@ public void ToArray() public void CopyTo() { list.CopyTo(a, 1); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009), Is.EqualTo("Alles klar")); list.Add(6); list.CopyTo(a, 2); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009), Is.EqualTo("Alles klar")); list.Add(4); list.Add(4); list.Add(9); list.CopyTo(a, 4); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 4, 4, 9, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 6, 4, 4, 9, 1008, 1009), Is.EqualTo("Alles klar")); list.Clear(); list.Add(7); list.CopyTo(a, 9); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 4, 4, 9, 1008, 7)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 6, 4, 4, 9, 1008, 7), Is.EqualTo("Alles klar")); } [Test] @@ -476,12 +508,12 @@ public void Init() } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } [Test] public void Get() { - Assert.IsNotNull(((System.Collections.IList)list).SyncRoot); + Assert.That(((System.Collections.IList)list).SyncRoot, Is.Not.Null); } } } @@ -499,38 +531,53 @@ public class Searching [Test] public void Contains() { - Assert.IsFalse(list.Contains(5)); + Assert.That(list.Contains(5), Is.False); list.Add(5); - Assert.IsTrue(list.Contains(5)); - Assert.IsFalse(list.Contains(7)); + Assert.Multiple(() => + { + Assert.That(list.Contains(5), Is.True); + Assert.That(list.Contains(7), Is.False); + }); list.Add(8); list.Add(10); - Assert.IsTrue(list.Contains(5)); - Assert.IsFalse(list.Contains(7)); - Assert.IsTrue(list.Contains(8)); - Assert.IsTrue(list.Contains(10)); + Assert.Multiple(() => + { + Assert.That(list.Contains(5), Is.True); + Assert.That(list.Contains(7), Is.False); + Assert.That(list.Contains(8), Is.True); + Assert.That(list.Contains(10), Is.True); + }); list.Remove(8); - Assert.IsTrue(list.Contains(5)); - Assert.IsFalse(list.Contains(7)); - Assert.IsFalse(list.Contains(8)); - Assert.IsTrue(list.Contains(10)); + Assert.Multiple(() => + { + Assert.That(list.Contains(5), Is.True); + Assert.That(list.Contains(7), Is.False); + Assert.That(list.Contains(8), Is.False); + Assert.That(list.Contains(10), Is.True); + }); } [Test] public void ContainsCount() { - Assert.AreEqual(0, list.ContainsCount(5)); + Assert.That(list.ContainsCount(5), Is.EqualTo(0)); list.Add(5); - Assert.AreEqual(1, list.ContainsCount(5)); - Assert.AreEqual(0, list.ContainsCount(7)); + Assert.Multiple(() => + { + Assert.That(list.ContainsCount(5), Is.EqualTo(1)); + Assert.That(list.ContainsCount(7), Is.EqualTo(0)); + }); list.Add(8); - Assert.AreEqual(1, list.ContainsCount(5)); - Assert.AreEqual(0, list.ContainsCount(7)); - Assert.AreEqual(1, list.ContainsCount(8)); + Assert.Multiple(() => + { + Assert.That(list.ContainsCount(5), Is.EqualTo(1)); + Assert.That(list.ContainsCount(7), Is.EqualTo(0)); + Assert.That(list.ContainsCount(8), Is.EqualTo(1)); + }); list.Add(5); - Assert.AreEqual(2, list.ContainsCount(5)); - Assert.AreEqual(0, list.ContainsCount(7)); - Assert.AreEqual(1, list.ContainsCount(8)); + Assert.That(list.ContainsCount(5), Is.EqualTo(2)); + Assert.That(list.ContainsCount(7), Is.EqualTo(0)); + Assert.That(list.ContainsCount(8), Is.EqualTo(1)); } @@ -538,14 +585,17 @@ public void ContainsCount() public void RemoveAllCopies() { list.Add(5); list.Add(7); list.Add(5); - Assert.AreEqual(2, list.ContainsCount(5)); - Assert.AreEqual(1, list.ContainsCount(7)); + Assert.Multiple(() => + { + Assert.That(list.ContainsCount(5), Is.EqualTo(2)); + Assert.That(list.ContainsCount(7), Is.EqualTo(1)); + }); list.RemoveAllCopies(5); - Assert.AreEqual(0, list.ContainsCount(5)); - Assert.AreEqual(1, list.ContainsCount(7)); + Assert.That(list.ContainsCount(5), Is.EqualTo(0)); + Assert.That(list.ContainsCount(7), Is.EqualTo(1)); list.Add(5); list.Add(8); list.Add(5); list.RemoveAllCopies(8); - Assert.IsTrue(IC.Eq(list, 7, 5, 5)); + Assert.That(IC.Eq(list, 7, 5, 5), Is.True); } @@ -554,77 +604,92 @@ public void FindAll() { bool f(int i) { return i % 2 == 0; } - Assert.IsTrue(list.FindAll(f).IsEmpty); + Assert.That(list.FindAll(f).IsEmpty, Is.True); list.Add(5); list.Add(8); list.Add(5); list.Add(10); list.Add(8); - Assert.IsTrue(((LinkedList)list.FindAll(f)).Check()); - Assert.IsTrue(IC.Eq(list.FindAll(f), 8, 10, 8)); + Assert.Multiple(() => + { + Assert.That(((LinkedList)list.FindAll(f)).Check(), Is.True); + Assert.That(IC.Eq(list.FindAll(f), 8, 10, 8), Is.True); + }); } [Test] public void ContainsAll() { - LinkedList list2 = new LinkedList(); + LinkedList list2 = new(); - Assert.IsTrue(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.True); list2.Add(4); - Assert.IsFalse(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.False); list.Add(4); - Assert.IsTrue(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.True); list.Add(5); - Assert.IsTrue(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.True); list2.Add(4); - Assert.IsFalse(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.False); list.Add(4); - Assert.IsTrue(list.ContainsAll(list2)); + Assert.That(list.ContainsAll(list2), Is.True); } [Test] public void RetainAll() { - LinkedList list2 = new LinkedList(); + LinkedList list2 = new(); list.Add(4); list.Add(4); list.Add(5); list.Add(4); list.Add(6); list2.Add(5); list2.Add(4); list2.Add(7); list2.Add(7); list2.Add(4); list.RetainAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 4, 5)); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 4, 5), Is.True); + }); list.Add(5); list.Add(4); list.Add(6); list2.Clear(); list2.Add(5); list2.Add(5); list2.Add(6); list.RetainAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 5, 5, 6)); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 5, 5, 6), Is.True); + }); list2.Clear(); list2.Add(7); list2.Add(8); list2.Add(9); list.RetainAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list), Is.True); } [Test] public void RemoveAll() { - LinkedList list2 = new LinkedList(); + LinkedList list2 = new(); list.Add(4); list.Add(4); list.Add(5); list.Add(4); list.Add(6); list2.Add(5); list2.Add(4); list2.Add(7); list2.Add(7); list2.Add(4); list.RemoveAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 6)); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 6), Is.True); + }); list.Add(5); list.Add(4); list.Add(6); list2.Clear(); list2.Add(6); list2.Add(5); list2.Add(5); list2.Add(6); list.RemoveAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 4)); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 4), Is.True); + }); list2.Clear(); list2.Add(7); list2.Add(8); list2.Add(9); list.RemoveAll(list2); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 4)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 4), Is.True); } @@ -632,36 +697,45 @@ public void RemoveAll() public void Remove() { - Assert.IsTrue(list.FIFO); + Assert.That(list.FIFO, Is.True); list.Add(4); list.Add(4); list.Add(5); list.Add(4); list.Add(6); - Assert.IsFalse(list.Remove(2)); - Assert.IsTrue(list.Check()); - Assert.IsTrue(list.Remove(4)); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 5, 4, 6)); - Assert.AreEqual(6, list.RemoveLast()); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 5, 4)); + Assert.Multiple(() => + { + Assert.That(list.Remove(2), Is.False); + Assert.That(list.Check(), Is.True); + Assert.That(list.Remove(4), Is.True); + }); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 5, 4, 6), Is.True); + Assert.That(list.RemoveLast(), Is.EqualTo(6)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 5, 4), Is.True); list.Add(7); - Assert.AreEqual(4, list.RemoveFirst()); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 5, 4, 7)); + Assert.Multiple(() => + { + Assert.That(list.RemoveFirst(), Is.EqualTo(4)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 5, 4, 7), Is.True); + }); list.FIFO = false; list.Clear(); list.Add(4); list.Add(4); list.Add(5); list.Add(4); list.Add(6); - Assert.IsFalse(list.Remove(2)); - Assert.IsTrue(list.Check()); - Assert.IsTrue(list.Remove(4)); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 4, 5, 6)); - Assert.AreEqual(6, list.RemoveLast()); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 4, 5)); + Assert.That(list.Remove(2), Is.False); + Assert.That(list.Check(), Is.True); + Assert.That(list.Remove(4), Is.True); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 4, 5, 6), Is.True); + Assert.That(list.RemoveLast(), Is.EqualTo(6)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 4, 5), Is.True); list.Add(7); - Assert.AreEqual(4, list.RemoveFirst()); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 4, 5, 7)); + Assert.Multiple(() => + { + Assert.That(list.RemoveFirst(), Is.EqualTo(4)); + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 4, 5, 7), Is.True); + }); } @@ -670,12 +744,12 @@ public void Clear() { list.Add(7); list.Add(7); list.Clear(); - Assert.IsTrue(list.IsEmpty); + Assert.That(list.IsEmpty, Is.True); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } } @@ -687,7 +761,7 @@ namespace IIndexed [TestFixture] public class Searching { - private IIndexed dit; + private LinkedList dit; [SetUp] @@ -700,24 +774,30 @@ public void Init() [Test] public void IndexOf() { - Assert.AreEqual(~0, dit.IndexOf(6)); + Assert.That(dit.IndexOf(6), Is.EqualTo(~0)); dit.Add(7); - Assert.AreEqual(~1, dit.IndexOf(6)); - Assert.AreEqual(~1, dit.LastIndexOf(6)); - Assert.AreEqual(0, dit.IndexOf(7)); + Assert.Multiple(() => + { + Assert.That(dit.IndexOf(6), Is.EqualTo(~1)); + Assert.That(dit.LastIndexOf(6), Is.EqualTo(~1)); + Assert.That(dit.IndexOf(7), Is.EqualTo(0)); + }); dit.Add(5); dit.Add(7); dit.Add(8); dit.Add(7); - Assert.AreEqual(~5, dit.IndexOf(6)); - Assert.AreEqual(0, dit.IndexOf(7)); - Assert.AreEqual(4, dit.LastIndexOf(7)); - Assert.AreEqual(3, dit.IndexOf(8)); - Assert.AreEqual(1, dit.LastIndexOf(5)); + Assert.Multiple(() => + { + Assert.That(dit.IndexOf(6), Is.EqualTo(~5)); + Assert.That(dit.IndexOf(7), Is.EqualTo(0)); + Assert.That(dit.LastIndexOf(7), Is.EqualTo(4)); + Assert.That(dit.IndexOf(8), Is.EqualTo(3)); + Assert.That(dit.LastIndexOf(5), Is.EqualTo(1)); + }); } [TearDown] public void Dispose() { - dit = null; + dit.Dispose(); } } @@ -726,7 +806,7 @@ public void Dispose() [TestFixture] public class Removing { - private IIndexed dit; + private LinkedList dit; [SetUp] @@ -740,15 +820,18 @@ public void Init() public void RemoveAt() { dit.Add(5); dit.Add(7); dit.Add(9); dit.Add(1); dit.Add(2); - Assert.AreEqual(7, dit.RemoveAt(1)); - Assert.IsTrue(((LinkedList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 5, 9, 1, 2)); - Assert.AreEqual(5, dit.RemoveAt(0)); - Assert.IsTrue(((LinkedList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 9, 1, 2)); - Assert.AreEqual(2, dit.RemoveAt(2)); - Assert.IsTrue(((LinkedList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 9, 1)); + Assert.Multiple(() => + { + Assert.That(dit.RemoveAt(1), Is.EqualTo(7)); + Assert.That(((LinkedList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 5, 9, 1, 2), Is.True); + Assert.That(dit.RemoveAt(0), Is.EqualTo(5)); + }); + Assert.That(((LinkedList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 9, 1, 2), Is.True); + Assert.That(dit.RemoveAt(2), Is.EqualTo(2)); + Assert.That(((LinkedList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 9, 1), Is.True); } @@ -778,38 +861,53 @@ public void RemoveInterval() dit.RemoveInterval(0, 0); dit.Add(10); dit.Add(20); dit.Add(30); dit.Add(40); dit.Add(50); dit.Add(60); dit.RemoveInterval(3, 0); - Assert.IsTrue(((LinkedList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 10, 20, 30, 40, 50, 60)); + Assert.Multiple(() => + { + Assert.That(((LinkedList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 10, 20, 30, 40, 50, 60), Is.True); + }); dit.RemoveInterval(3, 1); - Assert.IsTrue(((LinkedList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 10, 20, 30, 50, 60)); + Assert.Multiple(() => + { + Assert.That(((LinkedList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 10, 20, 30, 50, 60), Is.True); + }); dit.RemoveInterval(1, 3); - Assert.IsTrue(((LinkedList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 10, 60)); + Assert.Multiple(() => + { + Assert.That(((LinkedList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 10, 60), Is.True); + }); dit.RemoveInterval(0, 2); - Assert.IsTrue(((LinkedList)dit).Check()); - Assert.IsTrue(IC.Eq(dit)); + Assert.Multiple(() => + { + Assert.That(((LinkedList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit), Is.True); + }); dit.Add(10); dit.Add(20); dit.Add(30); dit.Add(40); dit.Add(50); dit.Add(60); dit.RemoveInterval(0, 2); - Assert.IsTrue(((LinkedList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 30, 40, 50, 60)); + Assert.Multiple(() => + { + Assert.That(((LinkedList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 30, 40, 50, 60), Is.True); + }); dit.RemoveInterval(2, 2); - Assert.IsTrue(((LinkedList)dit).Check()); - Assert.IsTrue(IC.Eq(dit, 30, 40)); + Assert.Multiple(() => + { + Assert.That(((LinkedList)dit).Check(), Is.True); + Assert.That(IC.Eq(dit, 30, 40), Is.True); + }); } [TearDown] public void Dispose() { - dit = null; + dit.Dispose(); } } } - - - namespace IList_ { [TestFixture] @@ -827,7 +925,7 @@ public void Init() [TearDown] public void Dispose() { - lst = null; + lst.Dispose(); } [Test] @@ -846,11 +944,17 @@ public void LastBad() public void FirstLast() { lst.Add(19); - Assert.AreEqual(19, lst.First); - Assert.AreEqual(19, lst.Last); + Assert.Multiple(() => + { + Assert.That(lst.First, Is.EqualTo(19)); + Assert.That(lst.Last, Is.EqualTo(19)); + }); lst.Add(34); lst.InsertFirst(12); - Assert.AreEqual(12, lst.First); - Assert.AreEqual(34, lst.Last); + Assert.Multiple(() => + { + Assert.That(lst.First, Is.EqualTo(12)); + Assert.That(lst.Last, Is.EqualTo(34)); + }); } @@ -858,12 +962,12 @@ public void FirstLast() public void This() { lst.Add(34); - Assert.AreEqual(34, lst[0]); + Assert.That(lst[0], Is.EqualTo(34)); lst[0] = 56; - Assert.AreEqual(56, lst.First); + Assert.That(lst.First, Is.EqualTo(56)); lst.Add(7); lst.Add(7); lst.Add(7); lst.Add(7); lst[0] = 45; lst[2] = 78; lst[4] = 101; - Assert.IsTrue(IC.Eq(lst, 45, 7, 78, 7, 101)); + Assert.That(IC.Eq(lst, 45, 7, 78, 7, 101), Is.True); } [Test] @@ -924,105 +1028,129 @@ public void ThisBadHiSet() [TestFixture] public class Combined { - private IList> lst; + private IList> lst; [SetUp] public void Init() { - lst = new LinkedList>(new KeyValuePairEqualityComparer()); + lst = new LinkedList>(new KeyValuePairEqualityComparer()); for (int i = 0; i < 10; i++) { - lst.Add(new System.Collections.Generic.KeyValuePair(i, i + 30)); + lst.Add(new SCG.KeyValuePair(i, i + 30)); } } [TearDown] - public void Dispose() { lst = null; } + public void Dispose() { lst.Dispose(); } [Test] public void Find() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Find(ref p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); - p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Find(ref p)); + Assert.Multiple(() => + { + Assert.That(lst.Find(ref p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); + p = new SCG.KeyValuePair(13, 78); + Assert.That(lst.Find(ref p), Is.False); } [Test] public void FindOrAdd() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.FindOrAdd(ref p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); - p = new System.Collections.Generic.KeyValuePair(13, 79); - Assert.IsFalse(lst.FindOrAdd(ref p)); - Assert.AreEqual(13, lst[10].Key); - Assert.AreEqual(79, lst[10].Value); + Assert.Multiple(() => + { + Assert.That(lst.FindOrAdd(ref p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); + p = new SCG.KeyValuePair(13, 79); + Assert.Multiple(() => + { + Assert.That(lst.FindOrAdd(ref p), Is.False); + Assert.That(lst[10].Key, Is.EqualTo(13)); + Assert.That(lst[10].Value, Is.EqualTo(79)); + }); } [Test] public void Update() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Update(p)); - Assert.AreEqual(3, lst[3].Key); - Assert.AreEqual(78, lst[3].Value); - p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Update(p)); + Assert.Multiple(() => + { + Assert.That(lst.Update(p), Is.True); + Assert.That(lst[3].Key, Is.EqualTo(3)); + Assert.That(lst[3].Value, Is.EqualTo(78)); + }); + p = new SCG.KeyValuePair(13, 78); + Assert.That(lst.Update(p), Is.False); } [Test] public void UpdateOrAdd1() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.UpdateOrAdd(p)); - Assert.AreEqual(3, lst[3].Key); - Assert.AreEqual(78, lst[3].Value); - p = new System.Collections.Generic.KeyValuePair(13, 79); - Assert.IsFalse(lst.UpdateOrAdd(p)); - Assert.AreEqual(13, lst[10].Key); - Assert.AreEqual(79, lst[10].Value); + Assert.Multiple(() => + { + Assert.That(lst.UpdateOrAdd(p), Is.True); + Assert.That(lst[3].Key, Is.EqualTo(3)); + Assert.That(lst[3].Value, Is.EqualTo(78)); + }); + p = new SCG.KeyValuePair(13, 79); + Assert.Multiple(() => + { + Assert.That(lst.UpdateOrAdd(p), Is.False); + Assert.That(lst[10].Key, Is.EqualTo(13)); + Assert.That(lst[10].Value, Is.EqualTo(79)); + }); } [Test] public void UpdateOrAdd2() { - ICollection coll = new LinkedList(); + ICollection coll = new LinkedList(); // s1 and s2 are distinct objects but contain the same text: - String s1 = "abc", s2 = ("def" + s1).Substring(3); - Assert.IsFalse(coll.UpdateOrAdd(s1, out string old)); - Assert.AreEqual(null, old); - Assert.IsTrue(coll.UpdateOrAdd(s2, out old)); - Assert.IsTrue(Object.ReferenceEquals(s1, old)); - Assert.IsFalse(Object.ReferenceEquals(s2, old)); + string s1 = "abc", s2 = ("def" + s1).Substring(3); + Assert.Multiple(() => + { + Assert.That(coll.UpdateOrAdd(s1, out string old), Is.False); + Assert.That(old, Is.EqualTo(null)); + Assert.That(coll.UpdateOrAdd(s2, out old), Is.True); + Assert.That(ReferenceEquals(s1, old), Is.True); + Assert.That(ReferenceEquals(s2, old), Is.False); + }); } [Test] public void RemoveWithReturn() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Remove(p, out p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); - Assert.AreEqual(4, lst[3].Key); - Assert.AreEqual(34, lst[3].Value); - p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Remove(p, out _)); + Assert.Multiple(() => + { + Assert.That(lst.Remove(p, out p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + Assert.That(lst[3].Key, Is.EqualTo(4)); + Assert.That(lst[3].Value, Is.EqualTo(34)); + }); + p = new SCG.KeyValuePair(13, 78); + Assert.That(lst.Remove(p, out _), Is.False); } } @@ -1030,61 +1158,72 @@ public void RemoveWithReturn() [TestFixture] public class Inserting { - private IList? lst; +#pragma warning disable NUnit1032 // TODO: Breaks tests + private IList lst; +#pragma warning restore NUnit1032 // An IDisposable field/property should be Disposed in a TearDown method [SetUp] public void Init() { lst = new LinkedList(); } [TearDown] - public void Dispose() { lst = null; } + public void Dispose() + { + //lst.Dispose(); + } [Test] public void Insert() { lst.Insert(0, 5); - Assert.IsTrue(IC.Eq(lst, 5)); + Assert.That(IC.Eq(lst, 5), Is.True); lst.Insert(0, 7); - Assert.IsTrue(IC.Eq(lst, 7, 5)); + Assert.That(IC.Eq(lst, 7, 5), Is.True); lst.Insert(1, 4); - Assert.IsTrue(IC.Eq(lst, 7, 4, 5)); + Assert.That(IC.Eq(lst, 7, 4, 5), Is.True); lst.Insert(3, 2); - Assert.IsTrue(IC.Eq(lst, 7, 4, 5, 2)); + Assert.That(IC.Eq(lst, 7, 4, 5, 2), Is.True); } [Test] public void InsertDuplicate() { lst.Insert(0, 5); - Assert.IsTrue(IC.Eq(lst, 5)); + Assert.That(IC.Eq(lst, 5), Is.True); lst.Insert(0, 7); - Assert.IsTrue(IC.Eq(lst, 7, 5)); + Assert.That(IC.Eq(lst, 7, 5), Is.True); lst.Insert(1, 5); - Assert.IsTrue(IC.Eq(lst, 7, 5, 5)); + Assert.That(IC.Eq(lst, 7, 5, 5), Is.True); } [Test] public void InsertAllDuplicate1() { lst.Insert(0, 3); - Assert.IsTrue(IC.Eq(lst, 3)); + Assert.That(IC.Eq(lst, 3), Is.True); lst.Insert(0, 7); - Assert.IsTrue(IC.Eq(lst, 7, 3)); - lst.InsertAll(1, new int[] { 1, 2, 3, 4 }); - Assert.IsTrue(IC.Eq(lst, 7, 1, 2, 3, 4, 3)); - Assert.IsTrue(lst.Check()); + Assert.That(IC.Eq(lst, 7, 3), Is.True); + lst.InsertAll(1, [1, 2, 3, 4]); + Assert.Multiple(() => + { + Assert.That(IC.Eq(lst, 7, 1, 2, 3, 4, 3), Is.True); + Assert.That(lst.Check(), Is.True); + }); } [Test] public void InsertAllDuplicate2() { lst.Insert(0, 3); - Assert.IsTrue(IC.Eq(lst, 3)); + Assert.That(IC.Eq(lst, 3), Is.True); lst.Insert(0, 7); - Assert.IsTrue(IC.Eq(lst, 7, 3)); - lst.InsertAll(1, new int[] { 5, 6, 5, 8 }); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 5, 6, 5, 8, 3)); + Assert.That(IC.Eq(lst, 7, 3), Is.True); + lst.InsertAll(1, [5, 6, 5, 8]); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 5, 6, 5, 8, 3), Is.True); + }); } [Test] @@ -1112,15 +1251,18 @@ public void FIFO() lst.Add(2 * i); } - Assert.IsTrue(lst.FIFO); - Assert.AreEqual(0, lst.Remove()); - Assert.AreEqual(2, lst.Remove()); + Assert.Multiple(() => + { + Assert.That(lst.FIFO, Is.True); + Assert.That(lst.Remove(), Is.EqualTo(0)); + }); + Assert.That(lst.Remove(), Is.EqualTo(2)); lst.FIFO = false; - Assert.AreEqual(12, lst.Remove()); - Assert.AreEqual(10, lst.Remove()); + Assert.That(lst.Remove(), Is.EqualTo(12)); + Assert.That(lst.Remove(), Is.EqualTo(10)); lst.FIFO = true; - Assert.AreEqual(4, lst.Remove()); - Assert.AreEqual(6, lst.Remove()); + Assert.That(lst.Remove(), Is.EqualTo(4)); + Assert.That(lst.Remove(), Is.EqualTo(6)); } @@ -1135,7 +1277,7 @@ public void InsertFirstLast() lst.InsertLast(25); lst.InsertFirst(34); lst.InsertLast(55); - Assert.IsTrue(IC.Eq(lst, 34, 24, 14, 4, 5, 15, 25, 55)); + Assert.That(IC.Eq(lst, 34, 24, 14, 4, 5, 15, 25, 55), Is.True); } @@ -1147,14 +1289,23 @@ public void InsertFirst() lst.Add(2); lst.Add(5); lst.ViewOf(2).InsertFirst(7); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 2, 3, 2, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 2, 3, 2, 5), Is.True); + }); lst.ViewOf(3).InsertFirst(8); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 2, 8, 3, 2, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 2, 8, 3, 2, 5), Is.True); + }); lst.ViewOf(5).InsertFirst(9); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 2, 8, 3, 2, 9, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 2, 8, 3, 2, 9, 5), Is.True); + }); } @@ -1165,7 +1316,7 @@ public void BadInsertFirst() lst.Add(3); lst.Add(2); lst.Add(5); - Assert.IsNull(lst.ViewOf(4)); + Assert.That(lst.ViewOf(4), Is.Null); } @@ -1178,14 +1329,23 @@ public void InsertAfter() lst.Add(2); lst.Add(5); lst.LastViewOf(2).InsertLast(7); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 1, 2, 3, 2, 7, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 1, 2, 3, 2, 7, 5), Is.True); + }); lst.LastViewOf(1).InsertLast(8); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 1, 8, 2, 3, 2, 7, 5)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 1, 8, 2, 3, 2, 7, 5), Is.True); + }); lst.LastViewOf(5).InsertLast(9); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 1, 8, 2, 3, 2, 7, 5, 9)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 1, 8, 2, 3, 2, 7, 5, 9), Is.True); + }); } @@ -1196,7 +1356,7 @@ public void BadInsertAfter() lst.Add(3); lst.Add(2); lst.Add(5); - Assert.IsNull(lst.ViewOf(4)); + Assert.That(lst.ViewOf(4), Is.Null); } @@ -1211,14 +1371,23 @@ public void InsertAll() IList lst2 = new LinkedList() { 7, 8, 9 }; lst.InsertAll(0, lst2); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 1, 2, 3, 4)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 1, 2, 3, 4), Is.True); + }); lst.InsertAll(7, lst2); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 1, 2, 3, 4, 7, 8, 9)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 1, 2, 3, 4, 7, 8, 9), Is.True); + }); lst.InsertAll(5, lst2); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 1, 2, 7, 8, 9, 3, 4, 7, 8, 9)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 1, 2, 7, 8, 9, 3, 4, 7, 8, 9), Is.True); + }); } @@ -1228,18 +1397,24 @@ public void Map() string m(int i) { return "<<" + i + ">>"; } IList r = lst.Map(m); - Assert.IsTrue(r.Check()); - Assert.IsTrue(r.IsEmpty); + Assert.Multiple(() => + { + Assert.That(r.Check(), Is.True); + Assert.That(r.IsEmpty, Is.True); + }); lst.Add(1); lst.Add(2); lst.Add(3); lst.Add(4); r = lst.Map(m); - Assert.IsTrue(r.Check()); - Assert.AreEqual(4, r.Count); + Assert.Multiple(() => + { + Assert.That(r.Check(), Is.True); + Assert.That(r, Has.Count.EqualTo(4)); + }); for (int i = 0; i < 4; i++) { - Assert.AreEqual("<<" + (i + 1) + ">>", r[i]); + Assert.That(r[i], Is.EqualTo("<<" + (i + 1) + ">>")); } } [Test] @@ -1314,11 +1489,14 @@ public void RemoveFirstLast() lst.Add(2); lst.Add(3); lst.Add(4); - Assert.AreEqual(1, lst.RemoveFirst()); - Assert.AreEqual(4, lst.RemoveLast()); - Assert.AreEqual(2, lst.RemoveFirst()); - Assert.AreEqual(3, lst.RemoveLast()); - Assert.IsTrue(lst.IsEmpty); + Assert.Multiple(() => + { + Assert.That(lst.RemoveFirst(), Is.EqualTo(1)); + Assert.That(lst.RemoveLast(), Is.EqualTo(4)); + }); + Assert.That(lst.RemoveFirst(), Is.EqualTo(2)); + Assert.That(lst.RemoveLast(), Is.EqualTo(3)); + Assert.That(lst.IsEmpty, Is.True); } [Test] @@ -1342,20 +1520,35 @@ public void Reverse() } lst.Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0), Is.True); + }); lst.View(0, 3).Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0), Is.True); + }); lst.View(7, 0).Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0), Is.True); + }); lst.View(7, 3).Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2), Is.True); + }); lst.View(5, 1).Reverse(); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(IC.Eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2), Is.True); + }); } @@ -1384,62 +1577,86 @@ public class SortingTests [TearDown] - public void Dispose() { lst = null; } + public void Dispose() { lst.Dispose(); } [Test] public void Sort() { lst.Add(5); lst.Add(6); lst.Add(5); lst.Add(7); lst.Add(3); - Assert.IsFalse(lst.IsSorted(new IC())); + Assert.That(lst.IsSorted(new IC()), Is.False); lst.Sort(new IC()); - Assert.IsTrue(lst.Check()); - Assert.IsTrue(lst.IsSorted()); - Assert.IsTrue(lst.IsSorted(new IC())); - Assert.IsTrue(IC.Eq(lst, 3, 5, 5, 6, 7)); + Assert.Multiple(() => + { + Assert.That(lst.Check(), Is.True); + Assert.That(lst.IsSorted(), Is.True); + Assert.That(lst.IsSorted(new IC()), Is.True); + Assert.That(IC.Eq(lst, 3, 5, 5, 6, 7), Is.True); + }); } [Test] public void Stability() { - IList> lst2 = new LinkedList>(); - SCG.IComparer> c = new KeyValuePairComparer(new IC()); - - lst2.Add(new System.Collections.Generic.KeyValuePair(5, "a")); - lst2.Add(new System.Collections.Generic.KeyValuePair(5, "b")); - lst2.Add(new System.Collections.Generic.KeyValuePair(6, "c")); - lst2.Add(new System.Collections.Generic.KeyValuePair(4, "d")); - lst2.Add(new System.Collections.Generic.KeyValuePair(3, "e")); - lst2.Add(new System.Collections.Generic.KeyValuePair(4, "f")); - lst2.Add(new System.Collections.Generic.KeyValuePair(5, "handle")); - Assert.IsFalse(lst2.IsSorted(c)); + IList> lst2 = new LinkedList>(); + SCG.IComparer> c = new KeyValuePairComparer(new IC()); + + lst2.Add(new SCG.KeyValuePair(5, "a")); + lst2.Add(new SCG.KeyValuePair(5, "b")); + lst2.Add(new SCG.KeyValuePair(6, "c")); + lst2.Add(new SCG.KeyValuePair(4, "d")); + lst2.Add(new SCG.KeyValuePair(3, "e")); + lst2.Add(new SCG.KeyValuePair(4, "f")); + lst2.Add(new SCG.KeyValuePair(5, "handle")); + Assert.That(lst2.IsSorted(c), Is.False); lst2.Sort(c); - Assert.IsTrue(lst2.IsSorted(c)); + Assert.That(lst2.IsSorted(c), Is.True); - System.Collections.Generic.KeyValuePair p = lst2.RemoveFirst(); + SCG.KeyValuePair p = lst2.RemoveFirst(); - Assert.AreEqual(3, p.Key); - Assert.AreEqual("e", p.Value); + Assert.Multiple(() => + { + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo("e")); + }); p = lst2.RemoveFirst(); - Assert.AreEqual(4, p.Key); - Assert.AreEqual("d", p.Value); + Assert.Multiple(() => + { + Assert.That(p.Key, Is.EqualTo(4)); + Assert.That(p.Value, Is.EqualTo("d")); + }); p = lst2.RemoveFirst(); - Assert.AreEqual(4, p.Key); - Assert.AreEqual("f", p.Value); + Assert.Multiple(() => + { + Assert.That(p.Key, Is.EqualTo(4)); + Assert.That(p.Value, Is.EqualTo("f")); + }); p = lst2.RemoveFirst(); - Assert.AreEqual(5, p.Key); - Assert.AreEqual("a", p.Value); + Assert.Multiple(() => + { + Assert.That(p.Key, Is.EqualTo(5)); + Assert.That(p.Value, Is.EqualTo("a")); + }); p = lst2.RemoveFirst(); - Assert.AreEqual(5, p.Key); - Assert.AreEqual("b", p.Value); + Assert.Multiple(() => + { + Assert.That(p.Key, Is.EqualTo(5)); + Assert.That(p.Value, Is.EqualTo("b")); + }); p = lst2.RemoveFirst(); - Assert.AreEqual(5, p.Key); - Assert.AreEqual("handle", p.Value); + Assert.Multiple(() => + { + Assert.That(p.Key, Is.EqualTo(5)); + Assert.That(p.Value, Is.EqualTo("handle")); + }); p = lst2.RemoveFirst(); - Assert.AreEqual(6, p.Key); - Assert.AreEqual("c", p.Value); - Assert.IsTrue(lst2.IsEmpty); + Assert.Multiple(() => + { + Assert.That(p.Key, Is.EqualTo(6)); + Assert.That(p.Value, Is.EqualTo("c")); + Assert.That(lst2.IsEmpty, Is.True); + }); } } [TestFixture] @@ -1453,7 +1670,7 @@ public class ShuffleTests [TearDown] - public void Dispose() { lst = null; } + public void Dispose() { lst.Dispose(); } [Test] @@ -1463,10 +1680,10 @@ public void Shuffle() for (int i = 0; i < 100; i++) { lst.Shuffle(new C5Random(i + 1)); - Assert.IsTrue(lst.Check(), "Check " + i); + Assert.That(lst.Check(), Is.True, "Check " + i); int[] lst2 = lst.ToArray(); Sorting.IntroSort(lst2); - Assert.IsTrue(IC.Eq(lst2, 3, 5, 5, 6, 7), "Contents " + i); + Assert.That(IC.Eq(lst2, 3, 5, 5, 6, 7), Is.True, "Contents " + i); } } } @@ -1478,7 +1695,7 @@ namespace IStackQueue [TestFixture] public class Stack { - private IStack list; + private LinkedList list; [SetUp] @@ -1493,28 +1710,28 @@ public void Normal() list.Push(7); list.Push(8); list.Push(9); - Assert.AreEqual(9, list.Pop()); - Assert.AreEqual(8, list.Pop()); - Assert.AreEqual(7, list.Pop()); - Assert.AreEqual(5, list.Pop()); - Assert.AreEqual(7, list.Pop()); + Assert.That(list.Pop(), Is.EqualTo(9)); + Assert.That(list.Pop(), Is.EqualTo(8)); + Assert.That(list.Pop(), Is.EqualTo(7)); + Assert.That(list.Pop(), Is.EqualTo(5)); + Assert.That(list.Pop(), Is.EqualTo(7)); } [Test] public void PopEmpty() { list.Push(5); - Assert.AreEqual(5, list.Pop()); + Assert.That(list.Pop(), Is.EqualTo(5)); Assert.Throws(() => list.Pop()); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } [TestFixture] public class Queue { - private IQueue list; + private LinkedList list; [SetUp] @@ -1529,23 +1746,23 @@ public void Normal() list.Enqueue(7); list.Enqueue(8); list.Enqueue(9); - Assert.AreEqual(7, list.Dequeue()); - Assert.AreEqual(5, list.Dequeue()); - Assert.AreEqual(7, list.Dequeue()); - Assert.AreEqual(8, list.Dequeue()); - Assert.AreEqual(9, list.Dequeue()); + Assert.That(list.Dequeue(), Is.EqualTo(7)); + Assert.That(list.Dequeue(), Is.EqualTo(5)); + Assert.That(list.Dequeue(), Is.EqualTo(7)); + Assert.That(list.Dequeue(), Is.EqualTo(8)); + Assert.That(list.Dequeue(), Is.EqualTo(9)); } [Test] public void DeQueueEmpty() { list.Enqueue(5); - Assert.AreEqual(5, list.Dequeue()); + Assert.That(list.Dequeue(), Is.EqualTo(5)); Assert.Throws(() => list.Dequeue()); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } } } @@ -1562,7 +1779,7 @@ public class Range [TearDown] - public void Dispose() { lst = null; } + public void Dispose() { lst.Dispose(); } [Test] @@ -1574,9 +1791,12 @@ public void GetRange() lst.Add(i); } - Assert.IsTrue(IC.Eq(lst[0, 3], 0, 1, 2)); - Assert.IsTrue(IC.Eq(lst[3, 4], 3, 4, 5, 6)); - Assert.IsTrue(IC.Eq(lst[6, 4], 6, 7, 8, 9)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(lst[0, 3], 0, 1, 2), Is.True); + Assert.That(IC.Eq(lst[3, 4], 3, 4, 5, 6), Is.True); + Assert.That(IC.Eq(lst[6, 4], 6, 7, 8, 9), Is.True); + }); } [Test] @@ -1596,10 +1816,13 @@ public void Backwards() lst.Add(i); } - Assert.IsTrue(IC.Eq(lst.Backwards(), 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)); - Assert.IsTrue(IC.Eq(lst[0, 4].Backwards(), 3, 2, 1, 0)); - Assert.IsTrue(IC.Eq(lst[3, 4].Backwards(), 6, 5, 4, 3)); - Assert.IsTrue(IC.Eq(lst[6, 4].Backwards(), 9, 8, 7, 6)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(lst.Backwards(), 9, 8, 7, 6, 5, 4, 3, 2, 1, 0), Is.True); + Assert.That(IC.Eq(lst[0, 4].Backwards(), 3, 2, 1, 0), Is.True); + Assert.That(IC.Eq(lst[3, 4].Backwards(), 6, 5, 4, 3), Is.True); + Assert.That(IC.Eq(lst[6, 4].Backwards(), 9, 8, 7, 6), Is.True); + }); } [Test] @@ -1610,13 +1833,19 @@ public void DirectionAndCount() lst.Add(i); } - Assert.AreEqual(Direction.Forwards, lst.Direction); - Assert.AreEqual(Direction.Forwards, lst[3, 7].Direction); - Assert.AreEqual(Direction.Backwards, lst[3, 7].Backwards().Direction); - Assert.AreEqual(Direction.Backwards, lst.Backwards().Direction); - Assert.AreEqual(4, lst[3, 4].Count); - Assert.AreEqual(4, lst[3, 4].Backwards().Count); - Assert.AreEqual(10, lst.Backwards().Count); + Assert.Multiple(() => + { + Assert.That(lst.Direction, Is.EqualTo(Direction.Forwards)); + Assert.That(lst[3, 7].Direction, Is.EqualTo(Direction.Forwards)); + Assert.That(lst[3, 7].Backwards().Direction, Is.EqualTo(Direction.Backwards)); + Assert.That(lst.Backwards().Direction, Is.EqualTo(Direction.Backwards)); + Assert.That(lst[3, 4], Has.Count.EqualTo(4)); + }); + Assert.Multiple(() => + { + Assert.That(lst[3, 4].Backwards(), Has.Count.EqualTo(4)); + Assert.That(lst.Backwards(), Has.Count.EqualTo(10)); + }); } [Test] @@ -1646,7 +1875,9 @@ namespace View [TestFixture] public class Simple { +#pragma warning disable NUnit1032 // TODO: Breaks tests private LinkedList list, view; +#pragma warning restore NUnit1032 // An IDisposable field/property should be Disposed in a TearDown method [SetUp] @@ -1660,13 +1891,17 @@ public void Init() [TearDown] public void Dispose() { - list = view = null; + //list.Dispose(); + //view.Dispose(); } private void check() { - Assert.IsTrue(list.Check()); - Assert.IsTrue(view.Check()); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(view.Check(), Is.True); + }); } @@ -1684,8 +1919,11 @@ public void InsertPointer() check(); view.Insert(list.ViewOf(0), 11); check(); - Assert.IsTrue(IC.Eq(list, 0, 11, 1, 9, 7, 2, 10, 3, 8)); - Assert.IsTrue(IC.Eq(view, 11, 1, 9, 7, 2, 10)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 11, 1, 9, 7, 2, 10, 3, 8), Is.True); + Assert.That(IC.Eq(view, 11, 1, 9, 7, 2, 10), Is.True); + }); } [Test] @@ -1717,15 +1955,21 @@ public void InsertPointerBad4() public void Span() { IList span = list.View(1, 0).Span(list.View(2, 0)); - Assert.IsTrue(span.Check()); - Assert.AreEqual(1, span.Offset); - Assert.AreEqual(1, span.Count); + Assert.Multiple(() => + { + Assert.That(span.Check(), Is.True); + Assert.That(span.Offset, Is.EqualTo(1)); + Assert.That(span, Has.Count.EqualTo(1)); + }); span = list.View(0, 2).Span(list.View(2, 2)); - Assert.IsTrue(span.Check()); - Assert.AreEqual(0, span.Offset); - Assert.AreEqual(4, span.Count); + Assert.Multiple(() => + { + Assert.That(span.Check(), Is.True); + Assert.That(span.Offset, Is.EqualTo(0)); + Assert.That(span, Has.Count.EqualTo(4)); + }); span = list.View(3, 1).Span(list.View(1, 1)); - Assert.IsNull(span); + Assert.That(span, Is.Null); } [Test] @@ -1737,37 +1981,49 @@ public void ViewOf() } IList v = view.ViewOf(2); - Assert.IsTrue(v.Check()); - Assert.IsTrue(IC.Eq(v, 2)); - Assert.AreEqual(2, v.Offset); + Assert.Multiple(() => + { + Assert.That(v.Check(), Is.True); + Assert.That(IC.Eq(v, 2), Is.True); + Assert.That(v.Offset, Is.EqualTo(2)); + }); v = list.ViewOf(2); - Assert.IsTrue(v.Check()); - Assert.IsTrue(IC.Eq(v, 2)); - Assert.AreEqual(2, v.Offset); + Assert.Multiple(() => + { + Assert.That(v.Check(), Is.True); + Assert.That(IC.Eq(v, 2), Is.True); + Assert.That(v.Offset, Is.EqualTo(2)); + }); v = list.LastViewOf(2); - Assert.IsTrue(v.Check()); - Assert.IsTrue(IC.Eq(v, 2)); - Assert.AreEqual(6, v.Offset); + Assert.Multiple(() => + { + Assert.That(v.Check(), Is.True); + Assert.That(IC.Eq(v, 2), Is.True); + Assert.That(v.Offset, Is.EqualTo(6)); + }); } [Test] public void BadViewOf() { - Assert.IsNull(view.ViewOf(5)); - Assert.IsNull(view.LastViewOf(5)); - Assert.IsNull(view.ViewOf(3)); - Assert.IsNull(view.LastViewOf(3)); - Assert.IsNull(view.ViewOf(0)); - Assert.IsNull(view.LastViewOf(0)); + Assert.Multiple(() => + { + Assert.That(view.ViewOf(5), Is.Null); + Assert.That(view.LastViewOf(5), Is.Null); + Assert.That(view.ViewOf(3), Is.Null); + Assert.That(view.LastViewOf(3), Is.Null); + Assert.That(view.ViewOf(0), Is.Null); + Assert.That(view.LastViewOf(0), Is.Null); + }); } [Test] public void ArrayStuff() { - Assert.IsTrue(IC.Eq(view.ToArray(), 1, 2)); + Assert.That(IC.Eq(view.ToArray(), 1, 2), Is.True); int[] extarray = new int[5]; view.CopyTo(extarray, 2); - Assert.IsTrue(IC.Eq(extarray, 0, 0, 1, 2, 0)); + Assert.That(IC.Eq(extarray, 0, 0, 1, 2, 0), Is.True); } @@ -1775,81 +2031,120 @@ public void ArrayStuff() public void Add() { check(); - Assert.IsTrue(IC.Eq(list, 0, 1, 2, 3)); - Assert.IsTrue(IC.Eq(view, 1, 2)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 1, 2, 3), Is.True); + Assert.That(IC.Eq(view, 1, 2), Is.True); + }); view.InsertFirst(10); check(); - Assert.IsTrue(IC.Eq(list, 0, 10, 1, 2, 3)); - Assert.IsTrue(IC.Eq(view, 10, 1, 2)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 10, 1, 2, 3), Is.True); + Assert.That(IC.Eq(view, 10, 1, 2), Is.True); + }); view.Clear(); - Assert.IsFalse(view.IsReadOnly); - Assert.IsTrue(view.AllowsDuplicates); - Assert.IsTrue(view.IsEmpty); + Assert.Multiple(() => + { + Assert.That(view.IsReadOnly, Is.False); + Assert.That(view.AllowsDuplicates, Is.True); + Assert.That(view.IsEmpty, Is.True); + }); check(); - Assert.IsTrue(IC.Eq(list, 0, 3)); - Assert.IsTrue(IC.Eq(view)); + Assert.That(IC.Eq(list, 0, 3), Is.True); + Assert.That(IC.Eq(view), Is.True); view.Add(8); - Assert.IsFalse(view.IsEmpty); - Assert.IsTrue(view.AllowsDuplicates); - Assert.IsFalse(view.IsReadOnly); + Assert.That(view.IsEmpty, Is.False); + Assert.That(view.AllowsDuplicates, Is.True); + Assert.That(view.IsReadOnly, Is.False); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 3)); - Assert.IsTrue(IC.Eq(view, 8)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 3), Is.True); + Assert.That(IC.Eq(view, 8), Is.True); + }); view.Add(12); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 12, 3)); - Assert.IsTrue(IC.Eq(view, 8, 12)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 12, 3), Is.True); + Assert.That(IC.Eq(view, 8, 12), Is.True); + }); view./*ViewOf(12).*/InsertLast(15); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 12, 15, 3)); - Assert.IsTrue(IC.Eq(view, 8, 12, 15)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 12, 15, 3), Is.True); + Assert.That(IC.Eq(view, 8, 12, 15), Is.True); + }); view.ViewOf(12).InsertFirst(18); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 18, 12, 15, 3)); - Assert.IsTrue(IC.Eq(view, 8, 18, 12, 15)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 18, 12, 15, 3), Is.True); + Assert.That(IC.Eq(view, 8, 18, 12, 15), Is.True); + }); - LinkedList lst2 = new LinkedList() { 90, 92 }; + LinkedList lst2 = new() { 90, 92 }; view.AddAll(lst2); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 18, 12, 15, 90, 92, 3)); - Assert.IsTrue(IC.Eq(view, 8, 18, 12, 15, 90, 92)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 18, 12, 15, 90, 92, 3), Is.True); + Assert.That(IC.Eq(view, 8, 18, 12, 15, 90, 92), Is.True); + }); view.InsertLast(66); check(); - Assert.IsTrue(IC.Eq(list, 0, 8, 18, 12, 15, 90, 92, 66, 3)); - Assert.IsTrue(IC.Eq(view, 8, 18, 12, 15, 90, 92, 66)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 8, 18, 12, 15, 90, 92, 66, 3), Is.True); + Assert.That(IC.Eq(view, 8, 18, 12, 15, 90, 92, 66), Is.True); + }); } [Test] public void Bxxx() { - Assert.IsTrue(IC.Eq(view.Backwards(), 2, 1)); - Assert.AreSame(list, view.Underlying); - Assert.IsNull(list.Underlying); - Assert.AreEqual(Direction.Forwards, view.Direction); - Assert.AreEqual(Direction.Backwards, view.Backwards().Direction); - Assert.AreEqual(0, list.Offset); - Assert.AreEqual(1, view.Offset); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view.Backwards(), 2, 1), Is.True); + Assert.That(view.Underlying, Is.SameAs(list)); + Assert.That(list.Underlying, Is.Null); + Assert.That(view.Direction, Is.EqualTo(Direction.Forwards)); + Assert.That(view.Backwards().Direction, Is.EqualTo(Direction.Backwards)); + Assert.That(list.Offset, Is.EqualTo(0)); + Assert.That(view.Offset, Is.EqualTo(1)); + }); } [Test] public void Contains() { - Assert.IsTrue(view.Contains(1)); - Assert.IsFalse(view.Contains(0)); + Assert.Multiple(() => + { + Assert.That(view.Contains(1), Is.True); + Assert.That(view.Contains(0), Is.False); + }); - LinkedList lst2 = new LinkedList() { 2 }; + LinkedList lst2 = new() { 2 }; - Assert.IsTrue(view.ContainsAll(lst2)); + Assert.That(view.ContainsAll(lst2), Is.True); lst2.Add(3); - Assert.IsFalse(view.ContainsAll(lst2)); - Assert.AreEqual(Speed.Linear, view.ContainsSpeed); - Assert.AreEqual(2, view.Count); + Assert.Multiple(() => + { + Assert.That(view.ContainsAll(lst2), Is.False); + Assert.That(view.ContainsSpeed, Is.EqualTo(Speed.Linear)); + Assert.That(view, Has.Count.EqualTo(2)); + }); view.Add(1); - Assert.AreEqual(1, view.ContainsCount(2)); - Assert.AreEqual(2, view.ContainsCount(1)); - Assert.AreEqual(3, view.Count); + Assert.Multiple(() => + { + Assert.That(view.ContainsCount(2), Is.EqualTo(1)); + Assert.That(view.ContainsCount(1), Is.EqualTo(2)); + Assert.That(view, Has.Count.EqualTo(3)); + }); } @@ -1858,25 +2153,31 @@ public void CreateView() { LinkedList view2 = (LinkedList)view.View(1, 0); - Assert.AreSame(list, view2.Underlying); + Assert.That(view2.Underlying, Is.SameAs(list)); } [Test] public void FIFO() { - Assert.IsTrue(view.FIFO); + Assert.That(view.FIFO, Is.True); view.Add(23); view.Add(24); view.Add(25); check(); - Assert.IsTrue(IC.Eq(view, 1, 2, 23, 24, 25)); - Assert.AreEqual(1, view.Remove()); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 1, 2, 23, 24, 25), Is.True); + Assert.That(view.Remove(), Is.EqualTo(1)); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 23, 24, 25)); + Assert.That(IC.Eq(view, 2, 23, 24, 25), Is.True); view.FIFO = false; - Assert.IsFalse(view.FIFO); - Assert.AreEqual(25, view.Remove()); + Assert.Multiple(() => + { + Assert.That(view.FIFO, Is.False); + Assert.That(view.Remove(), Is.EqualTo(25)); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 23, 24)); + Assert.That(IC.Eq(view, 2, 23, 24), Is.True); } @@ -1885,25 +2186,34 @@ public void MapEtc() { LinkedList dbl = (LinkedList)view.Map(new Func(delegate (int i) { return i / 10.0; })); - Assert.IsTrue(dbl.Check()); - Assert.AreEqual(0.1, dbl[0]); - Assert.AreEqual(0.2, dbl[1]); + Assert.Multiple(() => + { + Assert.That(dbl.Check(), Is.True); + Assert.That(dbl[0], Is.EqualTo(0.1)); + Assert.That(dbl[1], Is.EqualTo(0.2)); + }); for (int i = 0; i < 10; i++) { view.Add(i); } list = (LinkedList)view.FindAll(new Func(delegate (int i) { return i % 4 == 1; })); - Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 1, 1, 5, 9)); + Assert.Multiple(() => + { + Assert.That(list.Check(), Is.True); + Assert.That(IC.Eq(list, 1, 1, 5, 9), Is.True); + }); } [Test] public void FL() { - Assert.AreEqual(1, view.First); - Assert.AreEqual(2, view.Last); + Assert.Multiple(() => + { + Assert.That(view.First, Is.EqualTo(1)); + Assert.That(view.Last, Is.EqualTo(2)); + }); } @@ -1919,17 +2229,17 @@ public void Indexing() view = (LinkedList)list.View(5, 7); for (int i = 0; i < 7; i++) { - Assert.AreEqual(i + 5, view[i]); + Assert.That(view[i], Is.EqualTo(i + 5)); } for (int i = 0; i < 7; i++) { - Assert.AreEqual(i, view.IndexOf(i + 5)); + Assert.That(view.IndexOf(i + 5), Is.EqualTo(i)); } for (int i = 0; i < 7; i++) { - Assert.AreEqual(i, view.LastIndexOf(i + 5)); + Assert.That(view.LastIndexOf(i + 5), Is.EqualTo(i)); } } @@ -1940,15 +2250,21 @@ public void INsert() view.Insert(0, 34); view.Insert(1, 35); view.Insert(4, 36); - Assert.IsTrue(view.Check()); - Assert.IsTrue(IC.Eq(view, 34, 35, 1, 2, 36)); + Assert.Multiple(() => + { + Assert.That(view.Check(), Is.True); + Assert.That(IC.Eq(view, 34, 35, 1, 2, 36), Is.True); + }); IList list2 = new LinkedList(); list2.AddAll(view); view.InsertAll(3, list2); - Assert.IsTrue(view.Check()); - Assert.IsTrue(IC.Eq(view, 34, 35, 1, 34, 35, 1, 2, 36, 2, 36)); + Assert.Multiple(() => + { + Assert.That(view.Check(), Is.True); + Assert.That(IC.Eq(view, 34, 35, 1, 34, 35, 1, 2, 36, 2, 36), Is.True); + }); } @@ -1956,11 +2272,14 @@ public void INsert() public void Sort() { view.Add(45); view.Add(47); view.Add(46); view.Add(48); - Assert.IsFalse(view.IsSorted(new IC())); + Assert.That(view.IsSorted(new IC()), Is.False); view.Sort(new IC()); check(); - Assert.IsTrue(IC.Eq(list, 0, 1, 2, 45, 46, 47, 48, 3)); - Assert.IsTrue(IC.Eq(view, 1, 2, 45, 46, 47, 48)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(list, 0, 1, 2, 45, 46, 47, 48, 3), Is.True); + Assert.That(IC.Eq(view, 1, 2, 45, 46, 47, 48), Is.True); + }); } @@ -1969,65 +2288,95 @@ public void Remove() { view.FIFO = false; view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0); - Assert.IsTrue(IC.Eq(view, 1, 2, 1, 5, 3, 1, 3, 0)); - Assert.IsTrue(view.Remove(1)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 1, 2, 1, 5, 3, 1, 3, 0), Is.True); + Assert.That(view.Remove(1), Is.True); + }); check(); - Assert.IsTrue(IC.Eq(view, 1, 2, 1, 5, 3, 3, 0)); - Assert.IsTrue(view.Remove(1)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 1, 2, 1, 5, 3, 3, 0), Is.True); + Assert.That(view.Remove(1), Is.True); + }); check(); - Assert.IsTrue(IC.Eq(view, 1, 2, 5, 3, 3, 0)); - Assert.IsTrue(view.Remove(0)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 1, 2, 5, 3, 3, 0), Is.True); + Assert.That(view.Remove(0), Is.True); + }); check(); - Assert.IsTrue(IC.Eq(view, 1, 2, 5, 3, 3)); + Assert.That(IC.Eq(view, 1, 2, 5, 3, 3), Is.True); view.RemoveAllCopies(3); check(); - Assert.IsTrue(IC.Eq(view, 1, 2, 5)); - Assert.IsTrue(IC.Eq(list, 0, 1, 2, 5, 3)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 1, 2, 5), Is.True); + Assert.That(IC.Eq(list, 0, 1, 2, 5, 3), Is.True); + }); view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0); - Assert.IsTrue(IC.Eq(view, 1, 2, 5, 1, 5, 3, 1, 3, 0)); + Assert.That(IC.Eq(view, 1, 2, 5, 1, 5, 3, 1, 3, 0), Is.True); view.FIFO = true; view.Clear(); view.Add(1); view.Add(2); view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0); - Assert.IsTrue(IC.Eq(view, 1, 2, 1, 5, 3, 1, 3, 0)); - Assert.IsTrue(view.Remove(1)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 1, 2, 1, 5, 3, 1, 3, 0), Is.True); + Assert.That(view.Remove(1), Is.True); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 1, 5, 3, 1, 3, 0)); - Assert.IsTrue(view.Remove(1)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 2, 1, 5, 3, 1, 3, 0), Is.True); + Assert.That(view.Remove(1), Is.True); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 5, 3, 1, 3, 0)); - Assert.IsTrue(view.Remove(0)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 2, 5, 3, 1, 3, 0), Is.True); + Assert.That(view.Remove(0), Is.True); + }); check(); - Assert.IsTrue(IC.Eq(view, 2, 5, 3, 1, 3)); + Assert.That(IC.Eq(view, 2, 5, 3, 1, 3), Is.True); view.RemoveAllCopies(3); check(); - Assert.IsTrue(IC.Eq(view, 2, 5, 1)); - Assert.IsTrue(IC.Eq(list, 0, 2, 5, 1, 3)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 2, 5, 1), Is.True); + Assert.That(IC.Eq(list, 0, 2, 5, 1, 3), Is.True); + }); view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0); - Assert.IsTrue(IC.Eq(view, 2, 5, 1, 1, 5, 3, 1, 3, 0)); + Assert.That(IC.Eq(view, 2, 5, 1, 1, 5, 3, 1, 3, 0), Is.True); - LinkedList l2 = new LinkedList() { 1, 2, 2, 3, 1 }; + LinkedList l2 = new() { 1, 2, 2, 3, 1 }; view.RemoveAll(l2); check(); - Assert.IsTrue(IC.Eq(view, 5, 5, 1, 3, 0)); + Assert.That(IC.Eq(view, 5, 5, 1, 3, 0), Is.True); view.RetainAll(l2); check(); - Assert.IsTrue(IC.Eq(view, 1, 3)); + Assert.That(IC.Eq(view, 1, 3), Is.True); view.Add(2); view.Add(4); view.Add(5); - Assert.AreEqual(1, view.RemoveAt(0)); - Assert.AreEqual(5, view.RemoveAt(3)); - Assert.AreEqual(2, view.RemoveAt(1)); + Assert.Multiple(() => + { + Assert.That(view.RemoveAt(0), Is.EqualTo(1)); + Assert.That(view.RemoveAt(3), Is.EqualTo(5)); + Assert.That(view.RemoveAt(1), Is.EqualTo(2)); + }); check(); - Assert.IsTrue(IC.Eq(view, 3, 4)); + Assert.That(IC.Eq(view, 3, 4), Is.True); view.Add(8); - Assert.AreEqual(3, view.RemoveFirst()); - Assert.AreEqual(8, view.RemoveLast()); + Assert.Multiple(() => + { + Assert.That(view.RemoveFirst(), Is.EqualTo(3)); + Assert.That(view.RemoveLast(), Is.EqualTo(8)); + }); view.Add(2); view.Add(5); view.Add(3); view.Add(1); view.RemoveInterval(1, 2); check(); - Assert.IsTrue(IC.Eq(view, 4, 3, 1)); + Assert.That(IC.Eq(view, 4, 3, 1), Is.True); } @@ -2042,10 +2391,13 @@ public void Reverse() view.View(3, 4).Reverse(); check(); - Assert.IsTrue(IC.Eq(view, 10, 11, 12, 16, 15, 14, 13, 17, 18, 19)); + Assert.That(IC.Eq(view, 10, 11, 12, 16, 15, 14, 13, 17, 18, 19), Is.True); view.Reverse(); - Assert.IsTrue(IC.Eq(view, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10)); - Assert.IsTrue(IC.Eq(list, 0, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10, 3)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10), Is.True); + Assert.That(IC.Eq(list, 0, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10, 3), Is.True); + }); } @@ -2054,21 +2406,24 @@ public void Slide() { view.Slide(1); check(); - Assert.IsTrue(IC.Eq(view, 2, 3)); + Assert.That(IC.Eq(view, 2, 3), Is.True); view.Slide(-2); check(); - Assert.IsTrue(IC.Eq(view, 0, 1)); + Assert.That(IC.Eq(view, 0, 1), Is.True); view.Slide(0, 3); check(); - Assert.IsTrue(IC.Eq(view, 0, 1, 2)); + Assert.That(IC.Eq(view, 0, 1, 2), Is.True); view.Slide(2, 1); check(); - Assert.IsTrue(IC.Eq(view, 2)); - Assert.AreEqual(view, view.Slide(-1, 0)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(view, 2), Is.True); + Assert.That(view.Slide(-1, 0), Is.EqualTo(view)); + }); check(); - Assert.IsTrue(IC.Eq(view)); + Assert.That(IC.Eq(view), Is.True); view.Add(28); - Assert.IsTrue(IC.Eq(list, 0, 28, 1, 2, 3)); + Assert.That(IC.Eq(list, 0, 28, 1, 2, 3), Is.True); } [Test] public void Iterate() @@ -2101,21 +2456,23 @@ public void Iterate() } //foreach (int cell in list) Console.Write(" " + cell); //Assert.IsTrue(list.Check()); - Assert.IsTrue(IC.Eq(list, 2, 4, 8, 666, 13, 6, 1, 666, 2, 666, 7)); + Assert.That(IC.Eq(list, 2, 4, 8, 666, 13, 6, 1, 666, 2, 666, 7), Is.True); } [Test] public void SyncRoot() { - Assert.AreSame(((System.Collections.IList)view).SyncRoot, ((System.Collections.IList)list).SyncRoot); + Assert.That(((System.Collections.IList)list).SyncRoot, Is.SameAs(((System.Collections.IList)view).SyncRoot)); } } [TestFixture] public class MulipleViews { +#pragma warning disable NUnit1032 // TODO: Breaks tests private IList list; +#pragma warning restore NUnit1032 // An IDisposable field/property should be Disposed in a TearDown method private IList[][] views; [SetUp] public void Init() @@ -2139,36 +2496,42 @@ public void Init() [TearDown] public void Dispose() { - list = null; + //list.Dispose(); views = null; } [Test] public void Insert() { - Assert.IsTrue(list.Check(), "list check before insert"); + Assert.That(list.Check(), Is.True, "list check before insert"); list.Insert(3, 777); - Assert.IsTrue(list.Check(), "list check after insert"); + Assert.That(list.Check(), Is.True, "list check after insert"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i < 3 && i + j > 3 ? j + 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i < 3 || (i == 3 && j == 0) ? i : i + 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i < 3 && i + j > 3 ? j + 1 : j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void RemoveAt() { - Assert.IsTrue(list.Check(), "list check before remove"); + Assert.That(list.Check(), Is.True, "list check before remove"); list.RemoveAt(3); - Assert.IsTrue(list.Check(), "list check after remove"); + Assert.That(list.Check(), Is.True, "list check after remove"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i <= 3 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i <= 3 && i + j > 3 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i <= 3 ? i : i - 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i <= 3 && i + j > 3 ? j - 1 : j), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2176,15 +2539,18 @@ public void RemoveAt() [Test] public void RemoveInterval() { - Assert.IsTrue(list.Check(), "list check before remove"); + Assert.That(list.Check(), Is.True, "list check before remove"); list.RemoveInterval(3, 2); - Assert.IsTrue(list.Check(), "list check after remove"); + Assert.That(list.Check(), Is.True, "list check after remove"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i <= 3 ? i : i <= 5 ? 3 : i - 2, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(j == 0 ? 0 : i <= 3 && i + j > 4 ? j - 2 : i > 4 || i + j <= 3 ? j : j - 1, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i <= 3 ? i : i <= 5 ? 3 : i - 2), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(j == 0 ? 0 : i <= 3 && i + j > 4 ? j - 2 : i > 4 || i + j <= 3 ? j : j - 1), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2193,75 +2559,90 @@ public void RemoveInterval() [Test] public void InsertAtEnd() { - Assert.IsTrue(list.Check(), "list check before insert"); + Assert.That(list.Check(), Is.True, "list check before insert"); list.InsertLast(777); - Assert.IsTrue(list.Check(), "list check after insert"); + Assert.That(list.Check(), Is.True, "list check after insert"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void RemoveAtEnd() { - Assert.IsTrue(list.Check(), "list check before remove"); + Assert.That(list.Check(), Is.True, "list check before remove"); list.RemoveAt(5); - Assert.IsTrue(list.Check(), "list check after remove"); + Assert.That(list.Check(), Is.True, "list check after remove"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i <= 5 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i <= 5 && i + j > 5 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i <= 5 ? i : i - 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i <= 5 && i + j > 5 ? j - 1 : j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void InsertAtStart() { - Assert.IsTrue(list.Check(), "list check before insert"); + Assert.That(list.Check(), Is.True, "list check before insert"); list.Insert(0, 777); - Assert.IsTrue(list.Check(), "list check after insert"); + Assert.That(list.Check(), Is.True, "list check after insert"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i == 0 && j == 0 ? 0 : i + 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i == 0 && j == 0 ? 0 : i + 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void RemoveAtStart() { - Assert.IsTrue(list.Check(), "list check before remove"); + Assert.That(list.Check(), Is.True, "list check before remove"); list.RemoveAt(0); - Assert.IsTrue(list.Check(), "list check after remove"); + Assert.That(list.Check(), Is.True, "list check after remove"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i == 0 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i == 0 && j > 0 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i == 0 ? i : i - 1), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i == 0 && j > 0 ? j - 1 : j), "view[" + i + "][" + j + "] count"); + }); } } } [Test] public void Clear() { - Assert.IsTrue(list.Check(), "list check before clear"); + Assert.That(list.Check(), Is.True, "list check before clear"); views[2][3].Clear(); - Assert.IsTrue(list.Check(), "list check after clear"); + Assert.That(list.Check(), Is.True, "list check after clear"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i < 2 ? i : i < 6 ? 2 : i - 3, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(s(i, j), views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i < 2 ? i : i < 6 ? 2 : i - 3), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(s(i, j)), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2294,17 +2675,20 @@ private int s(int i, int j) [Test] public void InsertAll() { - LinkedList list2 = new LinkedList(); + LinkedList list2 = new(); for (int i = 0; i < 5; i++) { list2.Add(100 + i); } - Assert.IsTrue(list.Check(), "list check before insertAll"); + Assert.That(list.Check(), Is.True, "list check before insertAll"); list.InsertAll(3, list2); - Assert.IsTrue(list.Check(), "list check after insertAll"); + Assert.That(list.Check(), Is.True, "list check after insertAll"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 5, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i < 3 && i + j > 3 ? j + 5 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i < 3 || (i == 3 && j == 0) ? i : i + 5), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i < 3 && i + j > 3 ? j + 5 : j), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2312,17 +2696,20 @@ public void InsertAll() [Test] public void AddAll() { - LinkedList list2 = new LinkedList(); + LinkedList list2 = new(); for (int i = 0; i < 5; i++) { list2.Add(100 + i); } - Assert.IsTrue(list.Check(), "list check before AddAll"); + Assert.That(list.Check(), Is.True, "list check before AddAll"); list.View(1, 2).AddAll(list2); - Assert.IsTrue(list.Check(), "list check after AddAll"); + Assert.That(list.Check(), Is.True, "list check after AddAll"); for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) { - Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 5, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); - Assert.AreEqual(i < 3 && i + j > 3 ? j + 5 : j, views[i][j].Count, "view[" + i + "][" + j + "] count"); + Assert.Multiple(() => + { + Assert.That(views[i][j].Offset, Is.EqualTo(i < 3 || (i == 3 && j == 0) ? i : i + 5), "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j], Has.Count.EqualTo(i < 3 && i + j > 3 ? j + 5 : j), "view[" + i + "][" + j + "] count"); + }); } } } @@ -2330,7 +2717,7 @@ public void AddAll() [Test] public void RemoveAll1() { - LinkedList list2 = new LinkedList() { 1, 3, 4 }; + LinkedList list2 = new() { 1, 3, 4 }; for (int i = 0; i < 7; i++) { @@ -2344,150 +2731,156 @@ public void RemoveAll1() _ = (LinkedList)list.View(i, j); list.RemoveAll(list2); - Assert.IsTrue(list.Check(), "list check after RemoveAll, i=" + i + ", j=" + j); + Assert.That(list.Check(), Is.True, "list check after RemoveAll, i=" + i + ", j=" + j); } } } [Test] public void RemoveAll2() { - LinkedList list2 = new LinkedList() { 1, 3, 4 }; - Assert.IsTrue(list.Check(), "list check before RemoveAll"); + LinkedList list2 = new() { 1, 3, 4 }; + Assert.That(list.Check(), Is.True, "list check before RemoveAll"); list.RemoveAll(list2); - Assert.AreEqual(0, views[0][0].Offset, "view [0][0] offset"); - Assert.AreEqual(0, views[0][1].Offset, "view [0][1] offset"); - Assert.AreEqual(0, views[0][2].Offset, "view [0][2] offset"); - Assert.AreEqual(0, views[0][3].Offset, "view [0][3] offset"); - Assert.AreEqual(0, views[0][4].Offset, "view [0][4] offset"); - Assert.AreEqual(0, views[0][5].Offset, "view [0][5] offset"); - Assert.AreEqual(0, views[0][6].Offset, "view [0][6] offset"); - Assert.AreEqual(1, views[1][0].Offset, "view [1][0] offset"); - Assert.AreEqual(1, views[1][1].Offset, "view [1][1] offset"); - Assert.AreEqual(1, views[1][2].Offset, "view [1][2] offset"); - Assert.AreEqual(1, views[1][3].Offset, "view [1][3] offset"); - Assert.AreEqual(1, views[1][4].Offset, "view [1][4] offset"); - Assert.AreEqual(1, views[1][5].Offset, "view [1][5] offset"); - Assert.AreEqual(1, views[2][0].Offset, "view [2][0] offset"); - Assert.AreEqual(1, views[2][1].Offset, "view [2][1] offset"); - Assert.AreEqual(1, views[2][2].Offset, "view [2][2] offset"); - Assert.AreEqual(1, views[2][3].Offset, "view [2][3] offset"); - Assert.AreEqual(1, views[2][4].Offset, "view [2][4] offset"); - Assert.AreEqual(2, views[3][0].Offset, "view [3][0] offset"); - Assert.AreEqual(2, views[3][1].Offset, "view [3][1] offset"); - Assert.AreEqual(2, views[3][2].Offset, "view [3][2] offset"); - Assert.AreEqual(2, views[3][3].Offset, "view [3][3] offset"); - Assert.AreEqual(2, views[4][0].Offset, "view [4][0] offset"); - Assert.AreEqual(2, views[4][1].Offset, "view [4][1] offset"); - Assert.AreEqual(2, views[4][2].Offset, "view [4][2] offset"); - Assert.AreEqual(2, views[5][0].Offset, "view [5][0] offset"); - Assert.AreEqual(2, views[5][1].Offset, "view [5][1] offset"); - Assert.AreEqual(3, views[6][0].Offset, "view [6][0] offset"); - - Assert.AreEqual(0, views[0][0].Count, "view [0][0] count"); - Assert.AreEqual(1, views[0][1].Count, "view [0][1] count"); - Assert.AreEqual(1, views[0][2].Count, "view [0][2] count"); - Assert.AreEqual(2, views[0][3].Count, "view [0][3] count"); - Assert.AreEqual(2, views[0][4].Count, "view [0][4] count"); - Assert.AreEqual(2, views[0][5].Count, "view [0][5] count"); - Assert.AreEqual(3, views[0][6].Count, "view [0][6] count"); - Assert.AreEqual(0, views[1][0].Count, "view [1][0] count"); - Assert.AreEqual(0, views[1][1].Count, "view [1][1] count"); - Assert.AreEqual(1, views[1][2].Count, "view [1][2] count"); - Assert.AreEqual(1, views[1][3].Count, "view [1][3] count"); - Assert.AreEqual(1, views[1][4].Count, "view [1][4] count"); - Assert.AreEqual(2, views[1][5].Count, "view [1][5] count"); - Assert.AreEqual(0, views[2][0].Count, "view [2][0] count"); - Assert.AreEqual(1, views[2][1].Count, "view [2][1] count"); - Assert.AreEqual(1, views[2][2].Count, "view [2][2] count"); - Assert.AreEqual(1, views[2][3].Count, "view [2][3] count"); - Assert.AreEqual(2, views[2][4].Count, "view [2][4] count"); - Assert.AreEqual(0, views[3][0].Count, "view [3][0] count"); - Assert.AreEqual(0, views[3][1].Count, "view [3][1] count"); - Assert.AreEqual(0, views[3][2].Count, "view [3][2] count"); - Assert.AreEqual(1, views[3][3].Count, "view [3][3] count"); - Assert.AreEqual(0, views[4][0].Count, "view [4][0] count"); - Assert.AreEqual(0, views[4][1].Count, "view [4][1] count"); - Assert.AreEqual(1, views[4][2].Count, "view [4][2] count"); - Assert.AreEqual(0, views[5][0].Count, "view [5][0] count"); - Assert.AreEqual(1, views[5][1].Count, "view [5][1] count"); - Assert.AreEqual(0, views[6][0].Count, "view [6][0] count"); - - Assert.IsTrue(list.Check(), "list check after RemoveAll"); + Assert.Multiple(() => + { + Assert.That(views[0][0].Offset, Is.EqualTo(0), "view [0][0] offset"); + Assert.That(views[0][1].Offset, Is.EqualTo(0), "view [0][1] offset"); + Assert.That(views[0][2].Offset, Is.EqualTo(0), "view [0][2] offset"); + Assert.That(views[0][3].Offset, Is.EqualTo(0), "view [0][3] offset"); + Assert.That(views[0][4].Offset, Is.EqualTo(0), "view [0][4] offset"); + Assert.That(views[0][5].Offset, Is.EqualTo(0), "view [0][5] offset"); + Assert.That(views[0][6].Offset, Is.EqualTo(0), "view [0][6] offset"); + Assert.That(views[1][0].Offset, Is.EqualTo(1), "view [1][0] offset"); + Assert.That(views[1][1].Offset, Is.EqualTo(1), "view [1][1] offset"); + Assert.That(views[1][2].Offset, Is.EqualTo(1), "view [1][2] offset"); + Assert.That(views[1][3].Offset, Is.EqualTo(1), "view [1][3] offset"); + Assert.That(views[1][4].Offset, Is.EqualTo(1), "view [1][4] offset"); + Assert.That(views[1][5].Offset, Is.EqualTo(1), "view [1][5] offset"); + Assert.That(views[2][0].Offset, Is.EqualTo(1), "view [2][0] offset"); + Assert.That(views[2][1].Offset, Is.EqualTo(1), "view [2][1] offset"); + Assert.That(views[2][2].Offset, Is.EqualTo(1), "view [2][2] offset"); + Assert.That(views[2][3].Offset, Is.EqualTo(1), "view [2][3] offset"); + Assert.That(views[2][4].Offset, Is.EqualTo(1), "view [2][4] offset"); + Assert.That(views[3][0].Offset, Is.EqualTo(2), "view [3][0] offset"); + Assert.That(views[3][1].Offset, Is.EqualTo(2), "view [3][1] offset"); + Assert.That(views[3][2].Offset, Is.EqualTo(2), "view [3][2] offset"); + Assert.That(views[3][3].Offset, Is.EqualTo(2), "view [3][3] offset"); + Assert.That(views[4][0].Offset, Is.EqualTo(2), "view [4][0] offset"); + Assert.That(views[4][1].Offset, Is.EqualTo(2), "view [4][1] offset"); + Assert.That(views[4][2].Offset, Is.EqualTo(2), "view [4][2] offset"); + Assert.That(views[5][0].Offset, Is.EqualTo(2), "view [5][0] offset"); + Assert.That(views[5][1].Offset, Is.EqualTo(2), "view [5][1] offset"); + Assert.That(views[6][0].Offset, Is.EqualTo(3), "view [6][0] offset"); + + Assert.That(views[0][0], Is.Empty, "view [0][0] count"); + Assert.That(views[0][1], Has.Count.EqualTo(1), "view [0][1] count"); + Assert.That(views[0][2], Has.Count.EqualTo(1), "view [0][2] count"); + Assert.That(views[0][3], Has.Count.EqualTo(2), "view [0][3] count"); + Assert.That(views[0][4], Has.Count.EqualTo(2), "view [0][4] count"); + Assert.That(views[0][5], Has.Count.EqualTo(2), "view [0][5] count"); + Assert.That(views[0][6], Has.Count.EqualTo(3), "view [0][6] count"); + Assert.That(views[1][0], Is.Empty, "view [1][0] count"); + Assert.That(views[1][1], Is.Empty, "view [1][1] count"); + Assert.That(views[1][2], Has.Count.EqualTo(1), "view [1][2] count"); + Assert.That(views[1][3], Has.Count.EqualTo(1), "view [1][3] count"); + Assert.That(views[1][4], Has.Count.EqualTo(1), "view [1][4] count"); + Assert.That(views[1][5], Has.Count.EqualTo(2), "view [1][5] count"); + Assert.That(views[2][0], Is.Empty, "view [2][0] count"); + Assert.That(views[2][1], Has.Count.EqualTo(1), "view [2][1] count"); + Assert.That(views[2][2], Has.Count.EqualTo(1), "view [2][2] count"); + Assert.That(views[2][3], Has.Count.EqualTo(1), "view [2][3] count"); + Assert.That(views[2][4], Has.Count.EqualTo(2), "view [2][4] count"); + Assert.That(views[3][0], Is.Empty, "view [3][0] count"); + Assert.That(views[3][1], Is.Empty, "view [3][1] count"); + Assert.That(views[3][2], Is.Empty, "view [3][2] count"); + Assert.That(views[3][3], Has.Count.EqualTo(1), "view [3][3] count"); + Assert.That(views[4][0], Is.Empty, "view [4][0] count"); + Assert.That(views[4][1], Is.Empty, "view [4][1] count"); + Assert.That(views[4][2], Has.Count.EqualTo(1), "view [4][2] count"); + Assert.That(views[5][0], Is.Empty, "view [5][0] count"); + Assert.That(views[5][1], Has.Count.EqualTo(1), "view [5][1] count"); + Assert.That(views[6][0], Is.Empty, "view [6][0] count"); + + Assert.That(list.Check(), Is.True, "list check after RemoveAll"); + }); } [Test] public void RetainAll() { - LinkedList list2 = new LinkedList() { 2, 4, 5 }; - Assert.IsTrue(list.Check(), "list check before RetainAll"); + LinkedList list2 = new() { 2, 4, 5 }; + Assert.That(list.Check(), Is.True, "list check before RetainAll"); list.RetainAll(list2); - Assert.AreEqual(0, views[0][0].Offset, "view [0][0] offset"); - Assert.AreEqual(0, views[0][1].Offset, "view [0][1] offset"); - Assert.AreEqual(0, views[0][2].Offset, "view [0][2] offset"); - Assert.AreEqual(0, views[0][3].Offset, "view [0][3] offset"); - Assert.AreEqual(0, views[0][4].Offset, "view [0][4] offset"); - Assert.AreEqual(0, views[0][5].Offset, "view [0][5] offset"); - Assert.AreEqual(0, views[0][6].Offset, "view [0][6] offset"); - Assert.AreEqual(0, views[1][0].Offset, "view [1][0] offset"); - Assert.AreEqual(0, views[1][1].Offset, "view [1][1] offset"); - Assert.AreEqual(0, views[1][2].Offset, "view [1][2] offset"); - Assert.AreEqual(0, views[1][3].Offset, "view [1][3] offset"); - Assert.AreEqual(0, views[1][4].Offset, "view [1][4] offset"); - Assert.AreEqual(0, views[1][5].Offset, "view [1][5] offset"); - Assert.AreEqual(0, views[2][0].Offset, "view [2][0] offset"); - Assert.AreEqual(0, views[2][1].Offset, "view [2][1] offset"); - Assert.AreEqual(0, views[2][2].Offset, "view [2][2] offset"); - Assert.AreEqual(0, views[2][3].Offset, "view [2][3] offset"); - Assert.AreEqual(0, views[2][4].Offset, "view [2][4] offset"); - Assert.AreEqual(1, views[3][0].Offset, "view [3][0] offset"); - Assert.AreEqual(1, views[3][1].Offset, "view [3][1] offset"); - Assert.AreEqual(1, views[3][2].Offset, "view [3][2] offset"); - Assert.AreEqual(1, views[3][3].Offset, "view [3][3] offset"); - Assert.AreEqual(1, views[4][0].Offset, "view [4][0] offset"); - Assert.AreEqual(1, views[4][1].Offset, "view [4][1] offset"); - Assert.AreEqual(1, views[4][2].Offset, "view [4][2] offset"); - Assert.AreEqual(2, views[5][0].Offset, "view [5][0] offset"); - Assert.AreEqual(2, views[5][1].Offset, "view [5][1] offset"); - Assert.AreEqual(3, views[6][0].Offset, "view [6][0] offset"); - - Assert.AreEqual(0, views[0][0].Count, "view [0][0] count"); - Assert.AreEqual(0, views[0][1].Count, "view [0][1] count"); - Assert.AreEqual(0, views[0][2].Count, "view [0][2] count"); - Assert.AreEqual(1, views[0][3].Count, "view [0][3] count"); - Assert.AreEqual(1, views[0][4].Count, "view [0][4] count"); - Assert.AreEqual(2, views[0][5].Count, "view [0][5] count"); - Assert.AreEqual(3, views[0][6].Count, "view [0][6] count"); - Assert.AreEqual(0, views[1][0].Count, "view [1][0] count"); - Assert.AreEqual(0, views[1][1].Count, "view [1][1] count"); - Assert.AreEqual(1, views[1][2].Count, "view [1][2] count"); - Assert.AreEqual(1, views[1][3].Count, "view [1][3] count"); - Assert.AreEqual(2, views[1][4].Count, "view [1][4] count"); - Assert.AreEqual(3, views[1][5].Count, "view [1][5] count"); - Assert.AreEqual(0, views[2][0].Count, "view [2][0] count"); - Assert.AreEqual(1, views[2][1].Count, "view [2][1] count"); - Assert.AreEqual(1, views[2][2].Count, "view [2][2] count"); - Assert.AreEqual(2, views[2][3].Count, "view [2][3] count"); - Assert.AreEqual(3, views[2][4].Count, "view [2][4] count"); - Assert.AreEqual(0, views[3][0].Count, "view [3][0] count"); - Assert.AreEqual(0, views[3][1].Count, "view [3][1] count"); - Assert.AreEqual(1, views[3][2].Count, "view [3][2] count"); - Assert.AreEqual(2, views[3][3].Count, "view [3][3] count"); - Assert.AreEqual(0, views[4][0].Count, "view [4][0] count"); - Assert.AreEqual(1, views[4][1].Count, "view [4][1] count"); - Assert.AreEqual(2, views[4][2].Count, "view [4][2] count"); - Assert.AreEqual(0, views[5][0].Count, "view [5][0] count"); - Assert.AreEqual(1, views[5][1].Count, "view [5][1] count"); - Assert.AreEqual(0, views[6][0].Count, "view [6][0] count"); - - - Assert.IsTrue(list.Check(), "list check after RetainAll"); + Assert.Multiple(() => + { + Assert.That(views[0][0].Offset, Is.EqualTo(0), "view [0][0] offset"); + Assert.That(views[0][1].Offset, Is.EqualTo(0), "view [0][1] offset"); + Assert.That(views[0][2].Offset, Is.EqualTo(0), "view [0][2] offset"); + Assert.That(views[0][3].Offset, Is.EqualTo(0), "view [0][3] offset"); + Assert.That(views[0][4].Offset, Is.EqualTo(0), "view [0][4] offset"); + Assert.That(views[0][5].Offset, Is.EqualTo(0), "view [0][5] offset"); + Assert.That(views[0][6].Offset, Is.EqualTo(0), "view [0][6] offset"); + Assert.That(views[1][0].Offset, Is.EqualTo(0), "view [1][0] offset"); + Assert.That(views[1][1].Offset, Is.EqualTo(0), "view [1][1] offset"); + Assert.That(views[1][2].Offset, Is.EqualTo(0), "view [1][2] offset"); + Assert.That(views[1][3].Offset, Is.EqualTo(0), "view [1][3] offset"); + Assert.That(views[1][4].Offset, Is.EqualTo(0), "view [1][4] offset"); + Assert.That(views[1][5].Offset, Is.EqualTo(0), "view [1][5] offset"); + Assert.That(views[2][0].Offset, Is.EqualTo(0), "view [2][0] offset"); + Assert.That(views[2][1].Offset, Is.EqualTo(0), "view [2][1] offset"); + Assert.That(views[2][2].Offset, Is.EqualTo(0), "view [2][2] offset"); + Assert.That(views[2][3].Offset, Is.EqualTo(0), "view [2][3] offset"); + Assert.That(views[2][4].Offset, Is.EqualTo(0), "view [2][4] offset"); + Assert.That(views[3][0].Offset, Is.EqualTo(1), "view [3][0] offset"); + Assert.That(views[3][1].Offset, Is.EqualTo(1), "view [3][1] offset"); + Assert.That(views[3][2].Offset, Is.EqualTo(1), "view [3][2] offset"); + Assert.That(views[3][3].Offset, Is.EqualTo(1), "view [3][3] offset"); + Assert.That(views[4][0].Offset, Is.EqualTo(1), "view [4][0] offset"); + Assert.That(views[4][1].Offset, Is.EqualTo(1), "view [4][1] offset"); + Assert.That(views[4][2].Offset, Is.EqualTo(1), "view [4][2] offset"); + Assert.That(views[5][0].Offset, Is.EqualTo(2), "view [5][0] offset"); + Assert.That(views[5][1].Offset, Is.EqualTo(2), "view [5][1] offset"); + Assert.That(views[6][0].Offset, Is.EqualTo(3), "view [6][0] offset"); + + Assert.That(views[0][0], Is.Empty, "view [0][0] count"); + Assert.That(views[0][1], Is.Empty, "view [0][1] count"); + Assert.That(views[0][2], Is.Empty, "view [0][2] count"); + Assert.That(views[0][3], Has.Count.EqualTo(1), "view [0][3] count"); + Assert.That(views[0][4], Has.Count.EqualTo(1), "view [0][4] count"); + Assert.That(views[0][5], Has.Count.EqualTo(2), "view [0][5] count"); + Assert.That(views[0][6], Has.Count.EqualTo(3), "view [0][6] count"); + Assert.That(views[1][0], Is.Empty, "view [1][0] count"); + Assert.That(views[1][1], Is.Empty, "view [1][1] count"); + Assert.That(views[1][2], Has.Count.EqualTo(1), "view [1][2] count"); + Assert.That(views[1][3], Has.Count.EqualTo(1), "view [1][3] count"); + Assert.That(views[1][4], Has.Count.EqualTo(2), "view [1][4] count"); + Assert.That(views[1][5], Has.Count.EqualTo(3), "view [1][5] count"); + Assert.That(views[2][0], Is.Empty, "view [2][0] count"); + Assert.That(views[2][1], Has.Count.EqualTo(1), "view [2][1] count"); + Assert.That(views[2][2], Has.Count.EqualTo(1), "view [2][2] count"); + Assert.That(views[2][3], Has.Count.EqualTo(2), "view [2][3] count"); + Assert.That(views[2][4], Has.Count.EqualTo(3), "view [2][4] count"); + Assert.That(views[3][0], Is.Empty, "view [3][0] count"); + Assert.That(views[3][1], Is.Empty, "view [3][1] count"); + Assert.That(views[3][2], Has.Count.EqualTo(1), "view [3][2] count"); + Assert.That(views[3][3], Has.Count.EqualTo(2), "view [3][3] count"); + Assert.That(views[4][0], Is.Empty, "view [4][0] count"); + Assert.That(views[4][1], Has.Count.EqualTo(1), "view [4][1] count"); + Assert.That(views[4][2], Has.Count.EqualTo(2), "view [4][2] count"); + Assert.That(views[5][0], Is.Empty, "view [5][0] count"); + Assert.That(views[5][1], Has.Count.EqualTo(1), "view [5][1] count"); + Assert.That(views[6][0], Is.Empty, "view [6][0] count"); + + + Assert.That(list.Check(), Is.True, "list check after RetainAll"); + }); } [Test] public void RemoveAllCopies() { - LinkedList list2 = new LinkedList() { 0, 2, 2, 2, 5, 2, 1 }; + LinkedList list2 = new() { 0, 2, 2, 2, 5, 2, 1 }; for (int i = 0; i < 7; i++) { for (int j = 0; j < 7 - i; j++) @@ -2496,9 +2889,12 @@ public void RemoveAllCopies() list.AddAll(list2); LinkedList v = (LinkedList)list.View(i, j); list.RemoveAllCopies(2); - Assert.AreEqual(i == 0 ? 0 : i <= 4 ? 1 : i <= 6 ? 2 : 3, v.Offset, "v.Offset, i=" + i + ", j=" + j); - Assert.AreEqual((i == 0 && j > 0 ? 1 : 0) + (i <= 4 && i + j > 4 ? 1 : 0) + (i <= 6 && i + j > 6 ? 1 : 0), v.Count, "v.Count, i=" + i + ", j=" + j); - Assert.IsTrue(list.Check(), "list check after RemoveAllCopies, i=" + i + ", j=" + j); + Assert.Multiple(() => + { + Assert.That(v.Offset, Is.EqualTo(i == 0 ? 0 : i <= 4 ? 1 : i <= 6 ? 2 : 3), "v.Offset, i=" + i + ", j=" + j); + Assert.That(v, Has.Count.EqualTo((i == 0 && j > 0 ? 1 : 0) + (i <= 4 && i + j > 4 ? 1 : 0) + (i <= 6 && i + j > 6 ? 1 : 0)), "v.Count, i=" + i + ", j=" + j); + Assert.That(list.Check(), Is.True, "list check after RemoveAllCopies, i=" + i + ", j=" + j); + }); } } } @@ -2520,14 +2916,14 @@ private void checkDisposed(bool reverse, int start, int count) { Assert.Fail("view[" + i + "][" + j + "] threw"); } - Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] size"); + Assert.That(views[i][j], Has.Count.EqualTo(j), "view[" + i + "][" + j + "] size"); if (reverse && ((j > 0 && start <= i && start + count >= i + j) || (j == 0 && start < i && start + count > i))) { - Assert.AreEqual(start + (start + count - i - j), views[i][j].Offset, "view[" + i + "][" + j + "] offset (mirrored)"); + Assert.That(views[i][j].Offset, Is.EqualTo(start + (start + count - i - j)), "view[" + i + "][" + j + "] offset (mirrored)"); } else { - Assert.AreEqual(i, views[i][j].Offset, "view[" + i + "][" + j + "] offset"); + Assert.That(views[i][j].Offset, Is.EqualTo(i), "view[" + i + "][" + j + "] offset"); } } else @@ -2548,9 +2944,9 @@ public void Reverse() { int start = 2, count = 3; IList list2 = list.View(start, count); - Assert.IsTrue(list.Check(), "list check before Reverse"); + Assert.That(list.Check(), Is.True, "list check before Reverse"); list2.Reverse(); - Assert.IsTrue(list.Check(), "list check after Reverse"); + Assert.That(list.Check(), Is.True, "list check after Reverse"); checkDisposed(true, start, count); } [Test] @@ -2558,9 +2954,9 @@ public void Sort() { int start = 2, count = 3; IList list2 = list.View(start, count); - Assert.IsTrue(list.Check(), "list check before Sort"); + Assert.That(list.Check(), Is.True, "list check before Sort"); list2.Sort(); - Assert.IsTrue(list.Check(), "list check after Sort"); + Assert.That(list.Check(), Is.True, "list check after Sort"); checkDisposed(false, start, count); } [Test] @@ -2568,9 +2964,9 @@ public void Shuffle() { int start = 2, count = 3; IList list2 = list.View(start, count); - Assert.IsTrue(list.Check(), "list check before Shuffle"); + Assert.That(list.Check(), Is.True, "list check before Shuffle"); list2.Shuffle(); - Assert.IsTrue(list.Check(), "list check after Shuffle"); + Assert.That(list.Check(), Is.True, "list check after Shuffle"); checkDisposed(false, start, count); } @@ -2598,8 +2994,8 @@ public void Init() [TearDown] public void Dispose() { - list = null; - view = null; + list.Dispose(); + view.Dispose(); } //Properties @@ -2633,13 +3029,13 @@ public void Add() [Test] public void AddAll_int_() { - Assert.Throws(() => view.AddAll(new int[] { })); + Assert.Throws(() => view.AddAll([])); } [Test] public void AddAll() { - Assert.Throws(() => view.AddAll(new int[] { })); + Assert.Throws(() => view.AddAll([])); } [Test] @@ -2681,7 +3077,7 @@ public void Clear() [Test] public void ContainsAll() { - Assert.Throws(() => view.ContainsAll(new int[] { })); + Assert.Throws(() => view.ContainsAll([])); } [Test] @@ -2826,9 +3222,13 @@ namespace LinkedListOfTreesORLists [TestFixture] public class MultiLevelUnorderedOfUnOrdered { - private ICollection dit, dat, dut; + private LinkedList dit; + private TreeSet dat; + private LinkedList dut; - private ICollection> Dit, Dat, Dut; + private LinkedList> Dit; + private LinkedList> Dat; + private LinkedList> Dut; [SetUp] @@ -2849,8 +3249,11 @@ public void Init() [Test] public void Check() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dit.UnsequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dit.UnsequencedEquals(dut), Is.False); + }); } @@ -2859,16 +3262,23 @@ public void Multi() { Dit.Add(dit); Dit.Add(dut); Dit.Add(dit); Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); - Assert.IsTrue(Dit.UnsequencedEquals(Dat)); - Assert.IsFalse(Dit.UnsequencedEquals(Dut)); + Assert.Multiple(() => + { + Assert.That(Dit.UnsequencedEquals(Dat), Is.True); + Assert.That(Dit.UnsequencedEquals(Dut), Is.False); + }); } [TearDown] public void Dispose() { - dit = dat = dut = null; - Dit = Dat = Dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); } } @@ -2877,9 +3287,13 @@ public void Dispose() [TestFixture] public class MultiLevelOrderedOfUnOrdered { - private ICollection dit, dat, dut; + private LinkedList dit; + private TreeSet dat; + private LinkedList dut; - private ISequenced> Dit, Dat, Dut; + private LinkedList> Dit; + private LinkedList> Dat; + private LinkedList> Dut; [SetUp] @@ -2900,8 +3314,11 @@ public void Init() [Test] public void Check() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dit.UnsequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dit.UnsequencedEquals(dut), Is.False); + }); } @@ -2911,16 +3328,23 @@ public void Multi() Dit.Add(dit); Dit.Add(dut); Dit.Add(dit); Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); Dut.Add(dit); Dut.Add(dut); Dut.Add(dat); - Assert.IsFalse(Dit.SequencedEquals(Dat)); - Assert.IsTrue(Dit.SequencedEquals(Dut)); + Assert.Multiple(() => + { + Assert.That(Dit.SequencedEquals(Dat), Is.False); + Assert.That(Dit.SequencedEquals(Dut), Is.True); + }); } [TearDown] public void Dispose() { - dit = dat = dut = null; - Dit = Dat = Dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); } } @@ -2929,9 +3353,15 @@ public void Dispose() [TestFixture] public class MultiLevelUnOrderedOfOrdered { - private ISequenced dit, dat, dut, dot; + private TreeSet dit; + private LinkedList dat; + private LinkedList dut; + private LinkedList dot; - private ICollection> Dit, Dat, Dut, Dot; + private LinkedList> Dit; + private LinkedList> Dat; + private LinkedList> Dut; + private LinkedList> Dot; [SetUp] @@ -2955,9 +3385,12 @@ public void Init() [Test] public void Check() { - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsTrue(dit.SequencedEquals(dot)); - Assert.IsFalse(dit.SequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dit.SequencedEquals(dot), Is.True); + Assert.That(dit.SequencedEquals(dut), Is.False); + }); } @@ -2968,17 +3401,26 @@ public void Multi() Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); Dut.Add(dot); Dut.Add(dut); Dut.Add(dit); Dot.Add(dit); Dot.Add(dit); Dot.Add(dut); - Assert.IsTrue(Dit.UnsequencedEquals(Dut)); - Assert.IsFalse(Dit.UnsequencedEquals(Dat)); - Assert.IsTrue(Dit.UnsequencedEquals(Dot)); + Assert.Multiple(() => + { + Assert.That(Dit.UnsequencedEquals(Dut), Is.True); + Assert.That(Dit.UnsequencedEquals(Dat), Is.False); + Assert.That(Dit.UnsequencedEquals(Dot), Is.True); + }); } [TearDown] public void Dispose() { - dit = dat = dut = dot = null; - Dit = Dat = Dut = Dot = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + dot.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); + Dot.Dispose(); } } @@ -2987,10 +3429,15 @@ public void Dispose() [TestFixture] public class MultiLevelOrderedOfOrdered { - private ISequenced dit, dat, dut, dot; - - private ISequenced> Dit, Dat, Dut, Dot; + private TreeSet dit; + private LinkedList dat; + private LinkedList dut; + private LinkedList dot; + private LinkedList> Dit; + private LinkedList> Dat; + private LinkedList> Dut; + private LinkedList> Dot; [SetUp] public void Init() @@ -3013,9 +3460,12 @@ public void Init() [Test] public void Check() { - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsTrue(dit.SequencedEquals(dot)); - Assert.IsFalse(dit.SequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dit.SequencedEquals(dot), Is.True); + Assert.That(dit.SequencedEquals(dut), Is.False); + }); } @@ -3026,17 +3476,26 @@ public void Multi() Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); Dut.Add(dot); Dut.Add(dut); Dut.Add(dit); Dot.Add(dit); Dot.Add(dit); Dot.Add(dut); - Assert.IsTrue(Dit.SequencedEquals(Dut)); - Assert.IsFalse(Dit.SequencedEquals(Dat)); - Assert.IsFalse(Dit.SequencedEquals(Dot)); + Assert.Multiple(() => + { + Assert.That(Dit.SequencedEquals(Dut), Is.True); + Assert.That(Dit.SequencedEquals(Dat), Is.False); + Assert.That(Dit.SequencedEquals(Dot), Is.False); + }); } [TearDown] public void Dispose() { - dit = dat = dut = dot = null; - Dit = Dat = Dut = Dot = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + dot.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); + Dot.Dispose(); } } } @@ -3049,7 +3508,7 @@ namespace HashingAndEquals [TestFixture] public class ISequenced { - private ISequenced dit, dat, dut; + private LinkedList dit, dat, dut; [SetUp] @@ -3064,7 +3523,7 @@ public void Init() [Test] public void EmptyEmpty() { - Assert.IsTrue(dit.SequencedEquals(dat)); + Assert.That(dit.SequencedEquals(dat), Is.True); } @@ -3072,23 +3531,29 @@ public void EmptyEmpty() public void EmptyNonEmpty() { dit.Add(3); - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsFalse(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dat.SequencedEquals(dit), Is.False); + }); } [Test] public void HashVal() { - Assert.AreEqual(CHC.SequencedHashCode(), dit.GetSequencedHashCode()); + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode())); dit.Add(3); - Assert.AreEqual(CHC.SequencedHashCode(3), dit.GetSequencedHashCode()); + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(3))); dit.Add(7); - Assert.AreEqual(CHC.SequencedHashCode(3, 7), dit.GetSequencedHashCode()); - Assert.AreEqual(CHC.SequencedHashCode(), dut.GetSequencedHashCode()); + Assert.Multiple(() => + { + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(3, 7))); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode())); + }); dut.Add(7); - Assert.AreEqual(CHC.SequencedHashCode(7), dut.GetSequencedHashCode()); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(7))); dut.Add(3); - Assert.AreEqual(CHC.SequencedHashCode(7, 3), dut.GetSequencedHashCode()); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(7, 3))); } @@ -3097,8 +3562,11 @@ public void EqualHashButDifferent() { dit.Add(0); dit.Add(31); dat.Add(1); dat.Add(0); - Assert.AreEqual(dit.GetSequencedHashCode(), dat.GetSequencedHashCode()); - Assert.IsFalse(dit.SequencedEquals(dat)); + Assert.Multiple(() => + { + Assert.That(dat.GetSequencedHashCode(), Is.EqualTo(dit.GetSequencedHashCode())); + Assert.That(dit.SequencedEquals(dat), Is.False); + }); } @@ -3108,11 +3576,17 @@ public void Normal() dit.Add(3); dit.Add(7); dat.Add(3); - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsFalse(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dat.SequencedEquals(dit), Is.False); + }); dat.Add(7); - Assert.IsTrue(dit.SequencedEquals(dat)); - Assert.IsTrue(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.True); + Assert.That(dat.SequencedEquals(dit), Is.True); + }); } @@ -3121,32 +3595,38 @@ public void WrongOrder() { dit.Add(3); dut.Add(3); - Assert.IsTrue(dit.SequencedEquals(dut)); - Assert.IsTrue(dut.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dut), Is.True); + Assert.That(dut.SequencedEquals(dit), Is.True); + }); dit.Add(7); ((LinkedList)dut).InsertFirst(7); - Assert.IsFalse(dit.SequencedEquals(dut)); - Assert.IsFalse(dut.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dut), Is.False); + Assert.That(dut.SequencedEquals(dit), Is.False); + }); } [Test] public void Reflexive() { - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); dit.Add(3); - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); dit.Add(7); - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); } [TearDown] public void Dispose() { - dit = null; - dat = null; - dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); } } @@ -3155,7 +3635,7 @@ public void Dispose() [TestFixture] public class IEditableCollection { - private ICollection dit, dat, dut; + private LinkedList dit, dat, dut; [SetUp] @@ -3170,7 +3650,7 @@ public void Init() [Test] public void EmptyEmpty() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); + Assert.That(dit.UnsequencedEquals(dat), Is.True); } @@ -3178,24 +3658,30 @@ public void EmptyEmpty() public void EmptyNonEmpty() { dit.Add(3); - Assert.IsFalse(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.False); + Assert.That(dat.UnsequencedEquals(dit), Is.False); + }); } [Test] public void HashVal() { - Assert.AreEqual(CHC.UnsequencedHashCode(), dit.GetUnsequencedHashCode()); + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode())); dit.Add(3); - Assert.AreEqual(CHC.UnsequencedHashCode(3), dit.GetUnsequencedHashCode()); + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3))); dit.Add(7); - Assert.AreEqual(CHC.UnsequencedHashCode(3, 7), dit.GetUnsequencedHashCode()); - Assert.AreEqual(CHC.UnsequencedHashCode(), dut.GetUnsequencedHashCode()); + Assert.Multiple(() => + { + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3, 7))); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode())); + }); dut.Add(3); - Assert.AreEqual(CHC.UnsequencedHashCode(3), dut.GetUnsequencedHashCode()); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3))); dut.Add(7); - Assert.AreEqual(CHC.UnsequencedHashCode(7, 3), dut.GetUnsequencedHashCode()); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(7, 3))); } @@ -3204,8 +3690,11 @@ public void EqualHashButDifferent() { dit.Add(-1657792980); dit.Add(-1570288808); dat.Add(1862883298); dat.Add(-272461342); - Assert.AreEqual(dit.GetUnsequencedHashCode(), dat.GetUnsequencedHashCode()); - Assert.IsFalse(dit.UnsequencedEquals(dat)); + Assert.Multiple(() => + { + Assert.That(dat.GetUnsequencedHashCode(), Is.EqualTo(dit.GetUnsequencedHashCode())); + Assert.That(dit.UnsequencedEquals(dat), Is.False); + }); } @@ -3215,11 +3704,17 @@ public void Normal() dit.Add(3); dit.Add(7); dat.Add(3); - Assert.IsFalse(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.False); + Assert.That(dat.UnsequencedEquals(dit), Is.False); + }); dat.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsTrue(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dat.UnsequencedEquals(dit), Is.True); + }); } @@ -3228,32 +3723,38 @@ public void WrongOrder() { dit.Add(3); dut.Add(3); - Assert.IsTrue(dit.UnsequencedEquals(dut)); - Assert.IsTrue(dut.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dut), Is.True); + Assert.That(dut.UnsequencedEquals(dit), Is.True); + }); dit.Add(7); dut.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dut)); - Assert.IsTrue(dut.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dut), Is.True); + Assert.That(dut.UnsequencedEquals(dit), Is.True); + }); } [Test] public void Reflexive() { - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); dit.Add(3); - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); dit.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); } [TearDown] public void Dispose() { - dit = null; - dat = null; - dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); } } @@ -3262,9 +3763,9 @@ public void Dispose() [TestFixture] public class MultiLevelUnorderedOfUnOrdered { - private ICollection dit, dat, dut; + private LinkedList dit, dat, dut; - private ICollection> Dit, Dat, Dut; + private LinkedList> Dit, Dat, Dut; [SetUp] @@ -3285,8 +3786,11 @@ public void Init() [Test] public void Check() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dit.UnsequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dit.UnsequencedEquals(dut), Is.False); + }); } @@ -3295,16 +3799,23 @@ public void Multi() { Dit.Add(dit); Dit.Add(dut); Dit.Add(dit); Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); - Assert.IsTrue(Dit.UnsequencedEquals(Dat)); - Assert.IsFalse(Dit.UnsequencedEquals(Dut)); + Assert.Multiple(() => + { + Assert.That(Dit.UnsequencedEquals(Dat), Is.True); + Assert.That(Dit.UnsequencedEquals(Dut), Is.False); + }); } [TearDown] public void Dispose() { - dit = dat = dut = null; - Dit = Dat = Dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); } } @@ -3313,9 +3824,9 @@ public void Dispose() [TestFixture] public class MultiLevelOrderedOfUnOrdered { - private ICollection dit, dat, dut; + private LinkedList dit, dat, dut; - private ISequenced> Dit, Dat, Dut; + private LinkedList> Dit, Dat, Dut; [SetUp] @@ -3336,8 +3847,11 @@ public void Init() [Test] public void Check() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dit.UnsequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dit.UnsequencedEquals(dut), Is.False); + }); } @@ -3347,16 +3861,23 @@ public void Multi() Dit.Add(dit); Dit.Add(dut); Dit.Add(dit); Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); Dut.Add(dit); Dut.Add(dut); Dut.Add(dat); - Assert.IsFalse(Dit.SequencedEquals(Dat)); - Assert.IsTrue(Dit.SequencedEquals(Dut)); + Assert.Multiple(() => + { + Assert.That(Dit.SequencedEquals(Dat), Is.False); + Assert.That(Dit.SequencedEquals(Dut), Is.True); + }); } [TearDown] public void Dispose() { - dit = dat = dut = null; - Dit = Dat = Dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); } } @@ -3365,9 +3886,9 @@ public void Dispose() [TestFixture] public class MultiLevelUnOrderedOfOrdered { - private ISequenced dit, dat, dut, dot; + private LinkedList dit, dat, dut, dot; - private ICollection> Dit, Dat, Dut, Dot; + private LinkedList> Dit, Dat, Dut, Dot; [SetUp] @@ -3391,9 +3912,12 @@ public void Init() [Test] public void Check() { - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsTrue(dit.SequencedEquals(dot)); - Assert.IsFalse(dit.SequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dit.SequencedEquals(dot), Is.True); + Assert.That(dit.SequencedEquals(dut), Is.False); + }); } @@ -3404,17 +3928,26 @@ public void Multi() Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); Dut.Add(dot); Dut.Add(dut); Dut.Add(dit); Dot.Add(dit); Dot.Add(dit); Dot.Add(dut); - Assert.IsTrue(Dit.UnsequencedEquals(Dut)); - Assert.IsFalse(Dit.UnsequencedEquals(Dat)); - Assert.IsTrue(Dit.UnsequencedEquals(Dot)); + Assert.Multiple(() => + { + Assert.That(Dit.UnsequencedEquals(Dut), Is.True); + Assert.That(Dit.UnsequencedEquals(Dat), Is.False); + Assert.That(Dit.UnsequencedEquals(Dot), Is.True); + }); } [TearDown] public void Dispose() { - dit = dat = dut = dot = null; - Dit = Dat = Dut = Dot = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + dot.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); + Dot.Dispose(); } } @@ -3423,9 +3956,9 @@ public void Dispose() [TestFixture] public class MultiLevelOrderedOfOrdered { - private ISequenced dit, dat, dut, dot; + private LinkedList dit, dat, dut, dot; - private ISequenced> Dit, Dat, Dut, Dot; + private LinkedList> Dit, Dat, Dut, Dot; [SetUp] @@ -3449,9 +3982,12 @@ public void Init() [Test] public void Check() { - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsTrue(dit.SequencedEquals(dot)); - Assert.IsFalse(dit.SequencedEquals(dut)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dit.SequencedEquals(dot), Is.True); + Assert.That(dit.SequencedEquals(dut), Is.False); + }); } @@ -3462,17 +3998,26 @@ public void Multi() Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); Dut.Add(dot); Dut.Add(dut); Dut.Add(dit); Dot.Add(dit); Dot.Add(dit); Dot.Add(dut); - Assert.IsTrue(Dit.SequencedEquals(Dut)); - Assert.IsFalse(Dit.SequencedEquals(Dat)); - Assert.IsFalse(Dit.SequencedEquals(Dot)); + Assert.Multiple(() => + { + Assert.That(Dit.SequencedEquals(Dut), Is.True); + Assert.That(Dit.SequencedEquals(Dat), Is.False); + Assert.That(Dit.SequencedEquals(Dot), Is.False); + }); } [TearDown] public void Dispose() { - dit = dat = dut = dot = null; - Dit = Dat = Dut = Dot = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + dot.Dispose(); + Dit.Dispose(); + Dat.Dispose(); + Dut.Dispose(); + Dot.Dispose(); } } } diff --git a/C5.Tests/Refactored/ArrayListTests.cs b/C5.Tests/Refactored/ArrayListTests.cs new file mode 100644 index 00000000..e32e54dd --- /dev/null +++ b/C5.Tests/Refactored/ArrayListTests.cs @@ -0,0 +1,117 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +using NUnit.Framework; +using System; +using SCG = System.Collections.Generic; + +namespace C5.Tests; + +public class ArrayListTests +{ + [Test] + public void ArrayList_Implements_IReadOnlyList() + { + var list = new ArrayList { 0, 1, 2, 3, 4 } as SCG.IReadOnlyList; + + Assert.That(list, Has.Count.EqualTo(5)); + Assert.That(list[2], Is.EqualTo(2)); + } + + [Test] + public void IList_index_set_given_null_when_T_is_value_type_throws() + { + System.Collections.IList list = new ArrayList { 1, 2, 3 }; + + Assert.Throws(() => list[1] = null); + } + + [Test] + public void IList_index_set_given_wrong_type_throws() + { + System.Collections.IList list = new ArrayList { 1, 2, 3 }; + + Assert.Throws(() => list[1] = "four"); + } + + [Test] + public void IList_Add_given_null_when_T_is_value_type_throws() + { + System.Collections.IList list = new ArrayList { 1, 2, 3 }; + + Assert.Throws(() => list.Add(null)); + } + + [Test] + public void IList_Add_given_wrong_type_throws() + { + System.Collections.IList list = new ArrayList { 1, 2, 3 }; + + Assert.Throws(() => list.Add("four")); + } + + [Test] + public void IList_Contains_given_null_when_T_is_value_type_returns_false() + { + System.Collections.IList list = new ArrayList { 1, 2, 3 }; + + Assert.That(list.Contains(null), Is.False); + } + + [Test] + public void IList_Contains_given_wrong_type_returns_false() + { + System.Collections.IList list = new ArrayList { 1, 2, 3 }; + + Assert.That(list.Contains("four"), Is.False); + } + + [Test] + public void IList_IndexOf_given_null_when_T_is_value_type_returns_minus_1() + { + System.Collections.IList list = new ArrayList { 1, 2, 3 }; + + Assert.That(list.IndexOf(null), Is.EqualTo(-1)); + } + + [Test] + public void IList_IndexOf_given_wrong_type_returns() + { + System.Collections.IList list = new ArrayList { 1, 2, 3 }; + + Assert.DoesNotThrow(() => list.IndexOf("four")); + } + + [Test] + public void IList_Insert_given_null_when_T_is_value_type_throws() + { + System.Collections.IList list = new ArrayList { 1, 2, 3 }; + + Assert.Throws(() => list.Insert(1, null)); + } + + + [Test] + public void IList_Insert_given_wrong_type_throws() + { + System.Collections.IList list = new ArrayList { 1, 2, 3 }; + + Assert.Throws(() => list.Insert(1, "two")); + } + + [Test] + public void IList_Remove_given_null_when_T_is_value_type_returns() + { + System.Collections.IList list = new ArrayList { 1, 2, 3 }; + + Assert.DoesNotThrow(() => list.Remove(null)); + } + + [Test] + public void IList_Remove_given_wrong_type_returns() + { + System.Collections.IList list = new ArrayList { 1, 2, 3 }; + + Assert.DoesNotThrow(() => list.Remove("four")); + } +} diff --git a/C5.Tests/Refactored/ComparerZeroHashCodeEqualityComparerTests.cs b/C5.Tests/Refactored/ComparerZeroHashCodeEqualityComparerTests.cs new file mode 100644 index 00000000..2fd324fc --- /dev/null +++ b/C5.Tests/Refactored/ComparerZeroHashCodeEqualityComparerTests.cs @@ -0,0 +1,33 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +using NUnit.Framework; + +namespace C5.Tests; + +public class ComparerZeroHashCodeEqualityComparerTests +{ + [Test] + public void Equals_given_null_and_null_returns_true() + { + var comparer = new ComparerZeroHashCodeEqualityComparer(System.StringComparer.InvariantCultureIgnoreCase); + + Assert.That(comparer.Equals(null, null), Is.True); + } + + [Test] + public void Equals_given_null_and_something_returns_false() + { + var comparer = new ComparerZeroHashCodeEqualityComparer(System.StringComparer.InvariantCultureIgnoreCase); + + Assert.That(comparer.Equals(null, "something"), Is.False); + } + + [Test] + public void Equals_given_something_and_null_returns_false() + { + var comparer = new ComparerZeroHashCodeEqualityComparer(System.StringComparer.InvariantCultureIgnoreCase); + + Assert.That(comparer.Equals("something", null), Is.False); + } +} diff --git a/C5.Tests/Refactored/GuardedListTests.cs b/C5.Tests/Refactored/GuardedListTests.cs new file mode 100644 index 00000000..3a6b0b1f --- /dev/null +++ b/C5.Tests/Refactored/GuardedListTests.cs @@ -0,0 +1,41 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +using NUnit.Framework; + +namespace C5.Tests; + +public class GuardedListTests +{ + [Test] + public void IList_Contains_given_null_when_T_is_value_type_returns_false() + { + System.Collections.IList list = new GuardedList(new ArrayList { 1, 2, 3 }); + + Assert.That(list.Contains(null), Is.False); + } + + [Test] + public void IList_Contains_given_wrong_type_returns_false() + { + System.Collections.IList list = new GuardedList(new ArrayList { 1, 2, 3 }); + + Assert.That(list.Contains("four"), Is.False); + } + + [Test] + public void IList_IndexOf_given_null_when_T_is_value_type_returns_minus_1() + { + System.Collections.IList list = new GuardedList(new ArrayList { 1, 2, 3 }); + + Assert.That(list.IndexOf(null), Is.EqualTo(-1)); + } + + [Test] + public void IList_IndexOf_given_wrong_type_returns() + { + System.Collections.IList list = new GuardedList(new ArrayList { 1, 2, 3 }); + + Assert.DoesNotThrow(() => list.IndexOf("four")); + } +} diff --git a/C5.Tests/Refactored/HashedArrayListTests.cs b/C5.Tests/Refactored/HashedArrayListTests.cs new file mode 100644 index 00000000..76430282 --- /dev/null +++ b/C5.Tests/Refactored/HashedArrayListTests.cs @@ -0,0 +1,107 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +using NUnit.Framework; +using System; + +namespace C5.Tests; + +public class HashedArrayListTests +{ + [Test] + public void IList_index_set_given_null_when_T_is_value_type_throws() + { + System.Collections.IList list = new HashedArrayList { 1, 2, 3 }; + + Assert.Throws(() => list[1] = null); + } + + [Test] + public void IList_index_set_given_wrong_type_throws() + { + System.Collections.IList list = new HashedArrayList { 1, 2, 3 }; + + Assert.Throws(() => list[1] = "four"); + } + + [Test] + public void IList_Add_given_null_when_T_is_value_type_throws() + { + System.Collections.IList list = new HashedArrayList { 1, 2, 3 }; + + Assert.Throws(() => list.Add(null)); + } + + [Test] + public void IList_Add_given_wrong_type_throws() + { + System.Collections.IList list = new HashedArrayList { 1, 2, 3 }; + + Assert.Throws(() => list.Add("four")); + } + + [Test] + public void IList_Contains_given_null_when_T_is_value_type_returns_false() + { + System.Collections.IList list = new HashedArrayList { 1, 2, 3 }; + + Assert.That(list.Contains(null), Is.False); + } + + [Test] + public void IList_Contains_given_wrong_type_returns_false() + { + System.Collections.IList list = new HashedArrayList { 1, 2, 3 }; + + Assert.That(list.Contains("four"), Is.False); + } + + [Test] + public void IList_IndexOf_given_null_when_T_is_value_type_returns_minus_1() + { + System.Collections.IList list = new HashedArrayList { 1, 2, 3 }; + + Assert.That(list.IndexOf(null), Is.EqualTo(-1)); + } + + [Test] + public void IList_IndexOf_given_wrong_type_returns() + { + System.Collections.IList list = new HashedArrayList { 1, 2, 3 }; + + Assert.DoesNotThrow(() => list.IndexOf("four")); + } + + [Test] + public void IList_Insert_given_null_when_T_is_value_type_throws() + { + System.Collections.IList list = new HashedArrayList { 1, 2, 3 }; + + Assert.Throws(() => list.Insert(1, null)); + } + + + [Test] + public void IList_Insert_given_wrong_type_throws() + { + System.Collections.IList list = new HashedArrayList { 1, 2, 3 }; + + Assert.Throws(() => list.Insert(1, "two")); + } + + [Test] + public void IList_Remove_given_null_when_T_is_value_type_returns() + { + System.Collections.IList list = new HashedArrayList { 1, 2, 3 }; + + Assert.DoesNotThrow(() => list.Remove(null)); + } + + [Test] + public void IList_Remove_given_wrong_type_returns() + { + System.Collections.IList list = new HashedArrayList { 1, 2, 3 }; + + Assert.DoesNotThrow(() => list.Remove("four")); + } +} diff --git a/C5.Tests/Refactored/HashedLinkedListTests.cs b/C5.Tests/Refactored/HashedLinkedListTests.cs new file mode 100644 index 00000000..d1b70985 --- /dev/null +++ b/C5.Tests/Refactored/HashedLinkedListTests.cs @@ -0,0 +1,107 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +using NUnit.Framework; +using System; + +namespace C5.Tests; + +public class HashedLinkedListTests +{ + [Test] + public void IList_index_set_given_null_when_T_is_value_type_throws() + { + System.Collections.IList list = new HashedLinkedList { 1, 2, 3 }; + + Assert.Throws(() => list[1] = null); + } + + [Test] + public void IList_index_set_given_wrong_type_throws() + { + System.Collections.IList list = new HashedLinkedList { 1, 2, 3 }; + + Assert.Throws(() => list[1] = "four"); + } + + [Test] + public void IList_Add_given_null_when_T_is_value_type_throws() + { + System.Collections.IList list = new HashedLinkedList { 1, 2, 3 }; + + Assert.Throws(() => list.Add(null)); + } + + [Test] + public void IList_Add_given_wrong_type_throws() + { + System.Collections.IList list = new HashedLinkedList { 1, 2, 3 }; + + Assert.Throws(() => list.Add("four")); + } + + [Test] + public void IList_Contains_given_null_when_T_is_value_type_returns_false() + { + System.Collections.IList list = new HashedLinkedList { 1, 2, 3 }; + + Assert.That(list.Contains(null), Is.False); + } + + [Test] + public void IList_Contains_given_wrong_type_returns_false() + { + System.Collections.IList list = new HashedLinkedList { 1, 2, 3 }; + + Assert.That(list.Contains("four"), Is.False); + } + + [Test] + public void IList_IndexOf_given_null_when_T_is_value_type_returns_minus_1() + { + System.Collections.IList list = new HashedLinkedList { 1, 2, 3 }; + + Assert.That(list.IndexOf(null), Is.EqualTo(-1)); + } + + [Test] + public void IList_IndexOf_given_wrong_type_returns() + { + System.Collections.IList list = new HashedLinkedList { 1, 2, 3 }; + + Assert.DoesNotThrow(() => list.IndexOf("four")); + } + + [Test] + public void IList_Insert_given_null_when_T_is_value_type_throws() + { + System.Collections.IList list = new HashedLinkedList { 1, 2, 3 }; + + Assert.Throws(() => list.Insert(1, null)); + } + + + [Test] + public void IList_Insert_given_wrong_type_throws() + { + System.Collections.IList list = new HashedLinkedList { 1, 2, 3 }; + + Assert.Throws(() => list.Insert(1, "two")); + } + + [Test] + public void IList_Remove_given_null_when_T_is_value_type_returns() + { + System.Collections.IList list = new HashedLinkedList { 1, 2, 3 }; + + Assert.DoesNotThrow(() => list.Remove(null)); + } + + [Test] + public void IList_Remove_given_wrong_type_returns() + { + System.Collections.IList list = new HashedLinkedList { 1, 2, 3 }; + + Assert.DoesNotThrow(() => list.Remove("four")); + } +} diff --git a/C5.Tests/Refactored/InternalComparerTests.cs b/C5.Tests/Refactored/InternalComparerTests.cs new file mode 100644 index 00000000..077a0024 --- /dev/null +++ b/C5.Tests/Refactored/InternalComparerTests.cs @@ -0,0 +1,34 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +using NUnit.Framework; +using System; + +namespace C5.Tests; + +public class InternalComparerTests +{ + [Test] + public void Compare_given_null_and_null_returns_0() + { + var comparer = new InternalComparer(StringComparer.InvariantCultureIgnoreCase.Compare); + + Assert.That(comparer.Compare(null, null), Is.EqualTo(0)); + } + + [Test] + public void Compare_given_null_and_something_returns_minus_1() + { + var comparer = new InternalComparer(StringComparer.InvariantCultureIgnoreCase.Compare); + + Assert.That(comparer.Compare(null, "something"), Is.EqualTo(-1)); + } + + [Test] + public void Compare_given_something_and_null_returns_1() + { + var comparer = new InternalComparer(StringComparer.InvariantCultureIgnoreCase.Compare); + + Assert.That(comparer.Compare("something", null), Is.EqualTo(1)); + } +} diff --git a/C5.Tests/Refactored/InternalEqualityComparerTests.cs b/C5.Tests/Refactored/InternalEqualityComparerTests.cs new file mode 100644 index 00000000..67108fd6 --- /dev/null +++ b/C5.Tests/Refactored/InternalEqualityComparerTests.cs @@ -0,0 +1,34 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +using NUnit.Framework; +using System; + +namespace C5.Tests; + +internal class InternalEqualityComparerTests +{ + [Test] + public void Equals_given_null_and_null_returns_true() + { + var comparer = new InternalEqualityComparer(StringComparer.InvariantCultureIgnoreCase.Equals, StringComparer.InvariantCultureIgnoreCase.GetHashCode); + + Assert.That(comparer.Equals(null, null), Is.True); + } + + [Test] + public void Equals_given_null_and_something_returns_false() + { + var comparer = new InternalEqualityComparer(StringComparer.InvariantCultureIgnoreCase.Equals, StringComparer.InvariantCultureIgnoreCase.GetHashCode); + + Assert.That(comparer.Equals(null, "something"), Is.False); + } + + [Test] + public void Equals_given_something_and_null_returns_false() + { + var comparer = new InternalEqualityComparer(StringComparer.InvariantCultureIgnoreCase.Equals, StringComparer.InvariantCultureIgnoreCase.GetHashCode); + + Assert.That(comparer.Equals("something", null), Is.False); + } +} diff --git a/C5.Tests/Refactored/LinkedListTests.cs b/C5.Tests/Refactored/LinkedListTests.cs new file mode 100644 index 00000000..6883b7fd --- /dev/null +++ b/C5.Tests/Refactored/LinkedListTests.cs @@ -0,0 +1,107 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +using NUnit.Framework; +using System; + +namespace C5.Tests; + +public class LinkedListTests +{ + [Test] + public void IList_index_set_given_null_when_T_is_value_type_throws() + { + System.Collections.IList list = new LinkedList { 1, 2, 3 }; + + Assert.Throws(() => list[1] = null); + } + + [Test] + public void IList_index_set_given_wrong_type_throws() + { + System.Collections.IList list = new LinkedList { 1, 2, 3 }; + + Assert.Throws(() => list[1] = "four"); + } + + [Test] + public void IList_Add_given_null_when_T_is_value_type_throws() + { + System.Collections.IList list = new LinkedList { 1, 2, 3 }; + + Assert.Throws(() => list.Add(null)); + } + + [Test] + public void IList_Add_given_wrong_type_throws() + { + System.Collections.IList list = new LinkedList { 1, 2, 3 }; + + Assert.Throws(() => list.Add("four")); + } + + [Test] + public void IList_Contains_given_null_when_T_is_value_type_returns_false() + { + System.Collections.IList list = new LinkedList { 1, 2, 3 }; + + Assert.That(list.Contains(null), Is.False); + } + + [Test] + public void IList_Contains_given_wrong_type_returns_false() + { + System.Collections.IList list = new LinkedList { 1, 2, 3 }; + + Assert.That(list.Contains("four"), Is.False); + } + + [Test] + public void IList_IndexOf_given_null_when_T_is_value_type_returns_minus_1() + { + System.Collections.IList list = new LinkedList { 1, 2, 3 }; + + Assert.That(list.IndexOf(null), Is.EqualTo(-1)); + } + + [Test] + public void IList_IndexOf_given_wrong_type_returns() + { + System.Collections.IList list = new LinkedList { 1, 2, 3 }; + + Assert.DoesNotThrow(() => list.IndexOf("four")); + } + + [Test] + public void IList_Insert_given_null_when_T_is_value_type_throws() + { + System.Collections.IList list = new LinkedList { 1, 2, 3 }; + + Assert.Throws(() => list.Insert(1, null)); + } + + + [Test] + public void IList_Insert_given_wrong_type_throws() + { + System.Collections.IList list = new LinkedList { 1, 2, 3 }; + + Assert.Throws(() => list.Insert(1, "two")); + } + + [Test] + public void IList_Remove_given_null_when_T_is_value_type_returns() + { + System.Collections.IList list = new LinkedList { 1, 2, 3 }; + + Assert.DoesNotThrow(() => list.Remove(null)); + } + + [Test] + public void IList_Remove_given_wrong_type_returns() + { + System.Collections.IList list = new LinkedList { 1, 2, 3 }; + + Assert.DoesNotThrow(() => list.Remove("four")); + } +} diff --git a/C5.Tests/Refactored/README.md b/C5.Tests/Refactored/README.md new file mode 100644 index 00000000..dde72152 --- /dev/null +++ b/C5.Tests/Refactored/README.md @@ -0,0 +1,3 @@ +# Refactored Tests + +This folder contains tests refactored for NUnit 4.x diff --git a/C5.Tests/Refactored/SequencedCollectionEqualityComparerTests.cs b/C5.Tests/Refactored/SequencedCollectionEqualityComparerTests.cs new file mode 100644 index 00000000..43bfd1cc --- /dev/null +++ b/C5.Tests/Refactored/SequencedCollectionEqualityComparerTests.cs @@ -0,0 +1,38 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +using NUnit.Framework; +using System; + +namespace C5.Tests; + +public class SequencedCollectionEqualityComparerTests +{ + [Test] + public void Equals_given_null_and_null_returns_true() + { + var comparer = SequencedCollectionEqualityComparer, char>.Default; + + Assert.That(comparer.Equals(null, null), Is.True); + } + + [Test] + public void Equals_given_null_and_something_returns_false() + { + var comparer = SequencedCollectionEqualityComparer, char>.Default; + + TreeBag something = ['a', 'b', 'c']; + + Assert.That(comparer.Equals(null, something), Is.False); + } + + [Test] + public void Equals_given_something_and_null_returns_false() + { + var comparer = SequencedCollectionEqualityComparer, char>.Default; + + TreeBag something = ['a', 'b', 'c']; + + Assert.That(comparer.Equals(something, null), Is.False); + } +} \ No newline at end of file diff --git a/C5.Tests/Refactored/UnsequencedCollectionEqualityComparerTests.cs b/C5.Tests/Refactored/UnsequencedCollectionEqualityComparerTests.cs new file mode 100644 index 00000000..e112952b --- /dev/null +++ b/C5.Tests/Refactored/UnsequencedCollectionEqualityComparerTests.cs @@ -0,0 +1,38 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +using NUnit.Framework; +using System; + +namespace C5.Tests; + +public class UnsequencedCollectionEqualityComparerTests +{ + [Test] + public void Equals_given_null_and_null_returns_true() + { + var comparer = UnsequencedCollectionEqualityComparer, char>.Default; + + Assert.That(comparer.Equals(null, null), Is.True); + } + + [Test] + public void Equals_given_null_and_something_returns_false() + { + var comparer = UnsequencedCollectionEqualityComparer, char>.Default; + + TreeBag something = ['a', 'b', 'c']; + + Assert.That(comparer.Equals(null, something), Is.False); + } + + [Test] + public void Equals_given_something_and_null_returns_false() + { + var comparer = UnsequencedCollectionEqualityComparer, char>.Default; + + TreeBag something = ['a', 'b', 'c']; + + Assert.That(comparer.Equals(something, null), Is.False); + } +} \ No newline at end of file diff --git a/C5.Tests/Refactored/WrappedArrayTests.cs b/C5.Tests/Refactored/WrappedArrayTests.cs new file mode 100644 index 00000000..1e600021 --- /dev/null +++ b/C5.Tests/Refactored/WrappedArrayTests.cs @@ -0,0 +1,107 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +using NUnit.Framework; +using System; + +namespace C5.Tests; + +public class WrappedArrayTests +{ + [Test] + public void IList_index_set_given_null_when_T_is_value_type_throws() + { + System.Collections.IList list = new WrappedArray([ 1, 2, 3 ]); + + Assert.Throws(() => list[1] = null); + } + + [Test] + public void IList_index_set_given_wrong_type_throws() + { + System.Collections.IList list = new WrappedArray([ 1, 2, 3 ]); + + Assert.Throws(() => list[1] = "four"); + } + + [Test] + public void IList_Add_given_null_when_T_is_value_type_throws() + { + System.Collections.IList list = new WrappedArray([ 1, 2, 3 ]); + + Assert.Throws(() => list.Add(null)); + } + + [Test] + public void IList_Add_given_wrong_type_throws() + { + System.Collections.IList list = new WrappedArray([ 1, 2, 3 ]); + + Assert.Throws(() => list.Add("four")); + } + + [Test] + public void IList_Contains_given_null_when_T_is_value_type_returns_false() + { + System.Collections.IList list = new WrappedArray([ 1, 2, 3 ]); + + Assert.That(list.Contains(null), Is.False); + } + + [Test] + public void IList_Contains_given_wrong_type_returns_false() + { + System.Collections.IList list = new WrappedArray([ 1, 2, 3 ]); + + Assert.That(list.Contains("four"), Is.False); + } + + [Test] + public void IList_IndexOf_given_null_when_T_is_value_type_returns_minus_1() + { + System.Collections.IList list = new WrappedArray([ 1, 2, 3 ]); + + Assert.That(list.IndexOf(null), Is.EqualTo(-1)); + } + + [Test] + public void IList_IndexOf_given_wrong_type_returns() + { + System.Collections.IList list = new WrappedArray([ 1, 2, 3 ]); + + Assert.DoesNotThrow(() => list.IndexOf("four")); + } + + [Test] + public void IList_Insert_given_null_when_T_is_value_type_throws() + { + System.Collections.IList list = new WrappedArray([ 1, 2, 3 ]); + + Assert.Throws(() => list.Insert(1, null)); + } + + + [Test] + public void IList_Insert_given_wrong_type_throws() + { + System.Collections.IList list = new WrappedArray([ 1, 2, 3 ]); + + Assert.Throws(() => list.Insert(1, "two")); + } + + [Test] + public void IList_Remove_given_null_when_T_is_value_returns() + { + System.Collections.IList list = new WrappedArray([ 1, 2, 3 ]); + + Assert.DoesNotThrow(() => list.Remove(null)); + } + + [Test] + public void IList_Remove_given_wrong_type_returns() + { + System.Collections.IList list = new WrappedArray([ 1, 2, 3 ]); + + Assert.DoesNotThrow(() => list.Remove("four")); + } +} diff --git a/C5.Tests/Sorting.cs b/C5.Tests/Sorting.cs index 9c850437..33bb80c4 100644 --- a/C5.Tests/Sorting.cs +++ b/C5.Tests/Sorting.cs @@ -35,7 +35,7 @@ public void HeapSort() Sorting.HeapSort(a, 0, length, ic); for (int i = 1; i < length; i++) { - Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i); + Assert.That(a[i - 1] <= a[i], Is.True, "Inversion at " + i); } } @@ -46,7 +46,7 @@ public void IntroSort() Sorting.IntroSort(a, 0, length, ic); for (int i = 1; i < length; i++) { - Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i); + Assert.That(a[i - 1] <= a[i], Is.True, "Inversion at " + i); } } @@ -58,13 +58,13 @@ public void InsertionSort() Sorting.InsertionSort(a, 0, length, ic); for (int i = 1; i < length; i++) { - Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i); + Assert.That(a[i - 1] <= a[i], Is.True, "Inversion at " + i); } Sorting.InsertionSort(a, length, 2 * length, ic); for (int i = length + 1; i < 2 * length; i++) { - Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i); + Assert.That(a[i - 1] <= a[i], Is.True, "Inversion at " + i); } } @@ -104,7 +104,7 @@ public void HeapSort() Sorting.HeapSort(a, 0, length, ic); for (int i = 1; i < length; i++) { - Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i); + Assert.That(a[i - 1] <= a[i], Is.True, "Inversion at " + i); } } @@ -115,7 +115,7 @@ public void IntroSort() Sorting.IntroSort(a, 0, length, ic); for (int i = 1; i < length; i++) { - Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i); + Assert.That(a[i - 1] <= a[i], Is.True, "Inversion at " + i); } } @@ -127,13 +127,13 @@ public void InsertionSort() Sorting.InsertionSort(a, 0, length, ic); for (int i = 1; i < length; i++) { - Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i); + Assert.That(a[i - 1] <= a[i], Is.True, "Inversion at " + i); } Sorting.InsertionSort(a, length, 2 * length, ic); for (int i = length + 1; i < 2 * length; i++) { - Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i); + Assert.That(a[i - 1] <= a[i], Is.True, "Inversion at " + i); } } @@ -171,7 +171,7 @@ public void HeapSort() Sorting.HeapSort(a, 0, length, ic); for (int i = 1; i < length; i++) { - Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i); + Assert.That(a[i - 1] <= a[i], Is.True, "Inversion at " + i); } } @@ -182,7 +182,7 @@ public void IntroSort() Sorting.IntroSort(a, 0, length, ic); for (int i = 1; i < length; i++) { - Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i); + Assert.That(a[i - 1] <= a[i], Is.True, "Inversion at " + i); } } @@ -194,13 +194,13 @@ public void InsertionSort() Sorting.InsertionSort(a, 0, length, ic); for (int i = 1; i < length; i++) { - Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i); + Assert.That(a[i - 1] <= a[i], Is.True, "Inversion at " + i); } Sorting.InsertionSort(a, length, 2 * length, ic); for (int i = length + 1; i < 2 * length; i++) { - Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i); + Assert.That(a[i - 1] <= a[i], Is.True, "Inversion at " + i); } } @@ -238,7 +238,7 @@ public void HeapSort() Sorting.HeapSort(a, 0, length, ic); for (int i = 1; i < length; i++) { - Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i); + Assert.That(a[i - 1] <= a[i], Is.True, "Inversion at " + i); } } @@ -249,7 +249,7 @@ public void IntroSort() Sorting.IntroSort(a, 0, length, ic); for (int i = 1; i < length; i++) { - Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i); + Assert.That(a[i - 1] <= a[i], Is.True, "Inversion at " + i); } } @@ -261,13 +261,13 @@ public void InsertionSort() Sorting.InsertionSort(a, 0, length, ic); for (int i = 1; i < length; i++) { - Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i); + Assert.That(a[i - 1] <= a[i], Is.True, "Inversion at " + i); } Sorting.InsertionSort(a, length, 2 * length, ic); for (int i = length + 1; i < 2 * length; i++) { - Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i); + Assert.That(a[i - 1] <= a[i], Is.True, "Inversion at " + i); } } diff --git a/C5.Tests/SupportClasses.cs b/C5.Tests/SupportClasses.cs index 4b5436ea..d767163c 100644 --- a/C5.Tests/SupportClasses.cs +++ b/C5.Tests/SupportClasses.cs @@ -5,7 +5,6 @@ using System; using SCG = System.Collections.Generic; - namespace C5.Tests { internal class SC : SCG.IComparer @@ -15,52 +14,54 @@ public int Compare(string a, string b) return a.CompareTo(b); } - - public void appl(String s) + public void appl(string s) { - System.Console.WriteLine("--{0}", s); + Console.WriteLine("--{0}", s); } } internal class TenEqualityComparer : SCG.IEqualityComparer, SCG.IComparer { private TenEqualityComparer() { } - public static TenEqualityComparer Default => new TenEqualityComparer(); + + public static TenEqualityComparer Default => new(); + public int GetHashCode(int item) { return (item / 10).GetHashCode(); } + public bool Equals(int item1, int item2) { return item1 / 10 == item2 / 10; } + public int Compare(int a, int b) { return (a / 10).CompareTo(b / 10); } } internal class IC : SCG.IComparer, IComparable, SCG.IComparer, IComparable { - public int Compare(int a, int b) - { - return a > b ? 1 : a < b ? -1 : 0; - } + public int Compare(int a, int b) => a > b ? 1 : a < b ? -1 : 0; - - public int Compare(IC a, IC b) - { - return a.I > b.I ? 1 : a.I < b.I ? -1 : 0; - } + public int Compare(IC a, IC b) => a.I > b.I ? 1 : a.I < b.I ? -1 : 0; public int I { get; set; } - public IC() { } + public IC(int i) => I = i; - public IC(int i) { I = i; } - - - public int CompareTo(int that) { return I > that ? 1 : I < that ? -1 : 0; } + public int CompareTo(int that) => I > that ? 1 : I < that ? -1 : 0; - public bool Equals(int that) { return I == that; } + public bool Equals(int that) => I == that; + public int CompareTo(IC? that) + { + if (that is null || I > that.I) + { + return 1; + } + else + { + return I < that.I ? -1 : 0; + } + } - public int CompareTo(IC that) { return I > that.I ? 1 : I < that.I ? -1 : 0; } - public bool Equals(IC that) { return I == that.I; } - + public bool Equals(IC that) => I == that.I; public static bool Eq(SCG.IEnumerable me, params int[] that) { @@ -307,7 +308,7 @@ public CollectionEvent(EventType act, EventArgs args, object sender) public bool Equals(CollectionEvent otherEvent, SCG.IEqualityComparer itemequalityComparer) { - if (otherEvent == null || Act != otherEvent.Act || !object.ReferenceEquals(Sender, otherEvent.Sender)) + if (otherEvent == null || Act != otherEvent.Act || !ReferenceEquals(Sender, otherEvent.Sender)) { return false; } @@ -435,11 +436,11 @@ public RadixFormatter(int radix) // The value to be formatted is returned as a signed string // of digits from the rDigits array. - private static readonly char[] rDigits = { + private static readonly char[] rDigits = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'X', 'Y', 'Z' }; + 'U', 'V', 'W', 'X', 'Y', 'Z' ]; public string Format(string format, object arg, IFormatProvider formatProvider) { diff --git a/C5.Tests/Templates/Clone.cs b/C5.Tests/Templates/Clone.cs deleted file mode 100644 index 23f42dff..00000000 --- a/C5.Tests/Templates/Clone.cs +++ /dev/null @@ -1,135 +0,0 @@ -// This file is part of the C5 Generic Collection Library for C# and CLI -// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. - -namespace C5.Tests.Templates.Extensible -{ - //class Clone - //{ - // public static void Tester() where U : class, IExtensible, new() - // { - // U extensible = new U(); - // RealTester(extensible); - // extensible.Add(12); - // extensible.Add(23); - // extensible.Add(56); - // RealTester(extensible); - // } - - // public static void ViewTester() where U : class, IList, new() - // { - // U baselist = new U(); - // baselist.Add(12); - // baselist.Add(23); - // baselist.Add(56); - // baselist.Add(112); - // baselist.Add(123); - // baselist.Add(156); - // U view = (U)baselist.View(2, 2); - // RealTester(view); - // } - - // public static void RealTester(U extensible) where U : class, IExtensible, new() - // { - // object clone = extensible.Clone(); - // Assert.IsNotNull(clone); - // Assert.AreEqual(typeof(U), clone.GetType(), - // string.Format("Wrong type '{0}' of clone of '{1}'", clone.GetType(), typeof(U))); - // U theClone = clone as U; - // Assert.IsTrue(theClone.Check(), "Clone does not pass Check()"); - // if (typeof(ICollection).IsAssignableFrom(typeof(U))) - // Assert.IsTrue(EqualityComparer.Default.Equals(extensible, theClone), "Clone has wrong contents"); - // else //merely extensible - // Assert.IsTrue(IC.eq(theClone, extensible.ToArray()), "Clone has wrong contents"); - // } - //} - - //class Serialization - //{ - // public static void Tester() where U : class, IExtensible, new() - // { - // U extensible = new U(); - // realtester(extensible); - // extensible.Add(12); - // extensible.Add(23); - // extensible.Add(56); - // realtester(extensible); - // } - - // public static void ViewTester() where U : class, IList, new() - // { - // U baselist = new U(); - // baselist.Add(12); - // baselist.Add(23); - // baselist.Add(56); - // baselist.Add(112); - // baselist.Add(123); - // baselist.Add(156); - // U view = (U)baselist.View(2, 2); - // realtester(view); - // } - - // private static void realtester(U extensible) where U : class, IExtensible, new() - // { - // object clone = serializeAndDeserialize(extensible); - - // Assert.IsNotNull(clone); - // Assert.AreEqual(typeof(U), clone.GetType(), - // string.Format("Wrong type '{0}' of clone of '{1}'", clone.GetType(), typeof(U))); - // U theClone = clone as U; - // if (typeof(IExtensible).IsAssignableFrom(typeof(U))) - // Assert.IsTrue(((IExtensible)theClone).Check(), "Clone does not pass Check()"); - // if (typeof(ICollection).IsAssignableFrom(typeof(U))) - // Assert.IsTrue(EqualityComparer.Default.Equals(extensible, theClone), "Clone has wrong contents"); - // else //merely extensible - // Assert.IsTrue(IC.eq(theClone, extensible.ToArray()), "Clone has wrong contents"); - // } - - // private static object serializeAndDeserialize(object extensible) - // { - // System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = - // new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); - // System.IO.Stream stream = new System.IO.MemoryStream(); - // formatter.Serialize(stream, extensible); - // stream.Flush(); - // stream.Seek(0L, System.IO.SeekOrigin.Begin); - // object clone = formatter.Deserialize(stream); - // return clone; - // } - - // public static void DTester() where U : class, IDictionary, new() - // { - // U dict = new U(); - // realDtester(dict); - // dict.Add(12, 4); - // dict.Add(23, 6); - // dict.Add(56, 1); - // realDtester(dict); - // Assert.IsTrue(IC.eq((ICollectionValue)serializeAndDeserialize(dict.Keys), dict.Keys.ToArray()), "Keys clone has wrong contents"); - // Assert.IsTrue(IC.eq((ICollectionValue)serializeAndDeserialize(dict.Values), dict.Values.ToArray()), "Values Clone has wrong contents"); - // } - - // private static void realDtester(U dict) where U : class, IDictionary, new() - // { - // System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = - // new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); - // System.IO.Stream stream = new System.IO.MemoryStream(); - // formatter.Serialize(stream, dict); - // stream.Flush(); - // stream.Seek(0L, System.IO.SeekOrigin.Begin); - // object clone = formatter.Deserialize(stream); - - // Assert.IsNotNull(clone); - // Assert.AreEqual(typeof(U), clone.GetType(), - // string.Format("Wrong type '{0}' of clone of '{1}'", clone.GetType(), typeof(U))); - // U theClone = clone as U; - // Assert.IsTrue(theClone.Check(), "Clone does not pass Check()"); - - // Assert.AreEqual(dict.Count, theClone.Count, "wrong size"); - // foreach (int i in dict.Keys) - // { - // Assert.AreEqual(dict[i], theClone[i], "Wrong value"); - // } - // } - //} - -} diff --git a/C5.Tests/Templates/Events.cs b/C5.Tests/Templates/Events.cs index 0b9a8661..47c64c73 100644 --- a/C5.Tests/Templates/Events.cs +++ b/C5.Tests/Templates/Events.cs @@ -26,11 +26,8 @@ public SCG.IEnumerable SpecsBasic { get { - CircularQueue specs = new CircularQueue(); - //foreach (EventType listenTo in Enum.GetValues(typeof(EventType))) - // if ((listenTo & ~EventType.Basic) == 0) - // specs.Enqueue(listenTo); - //specs.Enqueue(EventType.Added | EventType.Removed); + CircularQueue specs = new(); + for (int spec = 0; spec <= (int)EventType.Basic; spec++) { specs.Enqueue((EventType)spec); @@ -43,10 +40,7 @@ public SCG.IEnumerable SpecsAll { get { - CircularQueue specs = new CircularQueue(); - //foreach (EventType listenTo in Enum.GetValues(typeof(EventType))) - // specs.Enqueue(listenTo); - //specs.Enqueue(EventType.Added | EventType.Removed); + CircularQueue specs = new(); for (int spec = 0; spec <= (int)EventType.All; spec++) { @@ -69,20 +63,23 @@ public override SCG.IEnumerable GetSpecs() } public virtual void Listenable() { - Assert.AreEqual(EventType.Basic, collection.ListenableEvents); - Assert.AreEqual(EventType.None, collection.ActiveEvents); + Assert.Multiple(() => + { + Assert.That(collection.ListenableEvents, Is.EqualTo(EventType.Basic)); + Assert.That(collection.ActiveEvents, Is.EqualTo(EventType.None)); + }); listen(); - Assert.AreEqual(listenTo, collection.ActiveEvents); + Assert.That(collection.ActiveEvents, Is.EqualTo(listenTo)); } public void Add() { listen(); - seen.Check(new CollectionEvent[0]); + seen.Check([]); collection.Add(23); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(23, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); } public void AddAll() @@ -92,28 +89,28 @@ public void AddAll() collection.Add(10 * i + 5); } listen(); - collection.AddAll(new int[] { 45, 200, 56, 67 }); + collection.AddAll([45, 200, 56, 67]); seen.Check(collection.AllowsDuplicates ? collection.DuplicatesByCounting ? new CollectionEvent[] { - new CollectionEvent(EventType.Added, new ItemCountEventArgs(45, 1), collection), - new CollectionEvent(EventType.Added, new ItemCountEventArgs(200, 1), collection), - new CollectionEvent(EventType.Added, new ItemCountEventArgs(55, 1), collection), - new CollectionEvent(EventType.Added, new ItemCountEventArgs(65, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)} + new(EventType.Added, new ItemCountEventArgs(45, 1), collection), + new(EventType.Added, new ItemCountEventArgs(200, 1), collection), + new(EventType.Added, new ItemCountEventArgs(55, 1), collection), + new(EventType.Added, new ItemCountEventArgs(65, 1), collection), + new(EventType.Changed, new EventArgs(), collection)} : - new CollectionEvent[] { + [ new CollectionEvent(EventType.Added, new ItemCountEventArgs(45, 1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(200, 1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(56, 1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(67, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)} + new CollectionEvent(EventType.Changed, new EventArgs(), collection)] : - new CollectionEvent[] { + [ new CollectionEvent(EventType.Added, new ItemCountEventArgs(200, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); - collection.AddAll(new int[] { }); - seen.Check(new CollectionEvent[] { }); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); + collection.AddAll([]); + seen.Check([]); } } @@ -129,22 +126,22 @@ public void Update() collection.AllowsDuplicates ? collection.DuplicatesByCounting ? new CollectionEvent[] { - new CollectionEvent(EventType.Removed, new ItemCountEventArgs(54, 2), collection), - new CollectionEvent(EventType.Added, new ItemCountEventArgs(53, 2), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection) + new(EventType.Removed, new ItemCountEventArgs(54, 2), collection), + new(EventType.Added, new ItemCountEventArgs(53, 2), collection), + new(EventType.Changed, new EventArgs(), collection) } - : new CollectionEvent[] { + : [ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(54, 1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(53, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection) - } - : new CollectionEvent[] { + ] + : [ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(54, 1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(53, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); + ]); collection.Update(67); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } public void FindOrAdd() @@ -153,13 +150,13 @@ public void FindOrAdd() listen(); int val = 53; collection.FindOrAdd(ref val); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); val = 67; collection.FindOrAdd(ref val); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(67, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); + ]); } public void UpdateOrAdd() @@ -168,29 +165,29 @@ public void UpdateOrAdd() listen(); int val = 53; collection.UpdateOrAdd(val); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(53, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); + ]); val = 67; collection.UpdateOrAdd(val); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(67, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); + ]); collection.UpdateOrAdd(51, out _); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(53, 1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(51, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); + ]); // val = 67; collection.UpdateOrAdd(81, out _); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(81, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); + ]); } public void RemoveItem() @@ -198,13 +195,13 @@ public void RemoveItem() collection.Add(4); collection.Add(56); collection.Add(18); listen(); collection.Remove(53); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); collection.Remove(11); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(18, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); } public void RemoveAll() @@ -214,14 +211,14 @@ public void RemoveAll() collection.Add(10 * i + 5); } listen(); - collection.RemoveAll(new int[] { 32, 187, 45 }); + collection.RemoveAll([32, 187, 45]); //TODO: the order depends on internals of the HashSet - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(35, 1), collection), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(45, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); - collection.RemoveAll(new int[] { 200, 300 }); - seen.Check(new CollectionEvent[] { }); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); + collection.RemoveAll([200, 300]); + seen.Check([]); } public void RetainAll() @@ -231,15 +228,15 @@ public void RetainAll() collection.Add(10 * i + 5); } listen(); - collection.RetainAll(new int[] { 32, 187, 45, 62, 75, 82, 95, 2 }); - seen.Check(new CollectionEvent[] { + collection.RetainAll([32, 187, 45, 62, 75, 82, 95, 2]); + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(15, 1), collection), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(25, 1), collection), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(55, 1), collection), //new CollectionEvent(EventType.Removed, new ItemCountEventArgs(75, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); - collection.RetainAll(new int[] { 32, 187, 45, 62, 75, 82, 95, 2 }); - seen.Check(new CollectionEvent[] { }); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); + collection.RetainAll([32, 187, 45, 62, 75, 82, 95, 2]); + seen.Check([]); } public void RemoveAllCopies() @@ -254,20 +251,20 @@ public void RemoveAllCopies() collection.AllowsDuplicates ? collection.DuplicatesByCounting ? new CollectionEvent[] { - new CollectionEvent(EventType.Removed, new ItemCountEventArgs(11, 3), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)} + new(EventType.Removed, new ItemCountEventArgs(11, 3), collection), + new(EventType.Changed, new EventArgs(), collection)} : - new CollectionEvent[] { + [ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(11, 1), collection), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(14, 1), collection), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(17, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)} + new CollectionEvent(EventType.Changed, new EventArgs(), collection)] : - new CollectionEvent[] { + [ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(11, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); collection.RemoveAllCopies(14); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } public virtual void Clear() @@ -275,12 +272,12 @@ public virtual void Clear() collection.Add(4); collection.Add(56); collection.Add(8); listen(); collection.Clear(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Cleared, new ClearedEventArgs(true, collection.AllowsDuplicates ? 3 : 2), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); + ]); collection.Clear(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } } @@ -292,10 +289,10 @@ public void RemoveAt() collection.Add(4); collection.Add(16); collection.Add(28); listen(); collection.RemoveAt(1); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(16,1), collection), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(16, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); } public void RemoveInterval() @@ -303,14 +300,14 @@ public void RemoveInterval() collection.Add(4); collection.Add(56); collection.Add(18); listen(); collection.RemoveInterval(1, 2); - seen.Check(new CollectionEvent[] { + seen.Check([ collection is IList ? new CollectionEvent(EventType.Cleared, new ClearedRangeEventArgs(false,2,1), collection): new CollectionEvent(EventType.Cleared, new ClearedEventArgs(false,2), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); + ]); collection.RemoveInterval(1, 0); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } } @@ -324,44 +321,44 @@ public void DeleteMinMax() collection.Add(12); listen(); collection.DeleteMax(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection), - }); + ]); collection.DeleteMin(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(12, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection), - }); + ]); } public void AddSorted() { listen(); - collection.AddSorted(collection.AllowsDuplicates ? new int[] { 31, 62, 63, 93 } : new int[] { 31, 62, 93 }); + collection.AddSorted(collection.AllowsDuplicates ? new int[] { 31, 62, 63, 93 } : [31, 62, 93]); seen.Check(collection.AllowsDuplicates ? collection.DuplicatesByCounting ? new CollectionEvent[] { - new CollectionEvent(EventType.Added, new ItemCountEventArgs(31, 1), collection), - new CollectionEvent(EventType.Added, new ItemCountEventArgs(62, 1), collection), - new CollectionEvent(EventType.Added, new ItemCountEventArgs(62, 1), collection), - new CollectionEvent(EventType.Added, new ItemCountEventArgs(93, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)} + new(EventType.Added, new ItemCountEventArgs(31, 1), collection), + new(EventType.Added, new ItemCountEventArgs(62, 1), collection), + new(EventType.Added, new ItemCountEventArgs(62, 1), collection), + new(EventType.Added, new ItemCountEventArgs(93, 1), collection), + new(EventType.Changed, new EventArgs(), collection)} : - new CollectionEvent[] { + [ new CollectionEvent(EventType.Added, new ItemCountEventArgs(31, 1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(62, 1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(63, 1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(93, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)} + new CollectionEvent(EventType.Changed, new EventArgs(), collection)] : - new CollectionEvent[] { + [ new CollectionEvent(EventType.Added, new ItemCountEventArgs(31, 1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(62, 1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(93, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); - collection.AddSorted(new int[] { }); - seen.Check(new CollectionEvent[] { }); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); + collection.AddSorted([]); + seen.Check([]); } public void RemoveRange() @@ -375,31 +372,31 @@ public void RemoveRange() collection.RemoveRangeFrom(173); //TODO: fix order to remove in: seen.Check( - new CollectionEvent[] { + [ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(195, 1), collection), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(185, 1), collection), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(175, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); collection.RemoveRangeFromTo(83, 113); seen.Check( - new CollectionEvent[] { + [ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(105, 1), collection), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(95, 1), collection), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(85, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); collection.RemoveRangeTo(33); seen.Check( - new CollectionEvent[] { + [ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(5, 1), collection), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(15, 1), collection), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(25, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); collection.RemoveRangeFrom(173); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); collection.RemoveRangeFromTo(83, 113); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); collection.RemoveRangeTo(33); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } } @@ -412,23 +409,26 @@ public override SCG.IEnumerable GetSpecs() public override void Listenable() { - Assert.AreEqual(EventType.All, collection.ListenableEvents); - Assert.AreEqual(EventType.None, collection.ActiveEvents); + Assert.Multiple(() => + { + Assert.That(collection.ListenableEvents, Is.EqualTo(EventType.All)); + Assert.That(collection.ActiveEvents, Is.EqualTo(EventType.None)); + }); listen(); - Assert.AreEqual(listenTo, collection.ActiveEvents); + Assert.That(collection.ActiveEvents, Is.EqualTo(listenTo)); } public void SetThis() { collection.Add(4); collection.Add(56); collection.Add(8); listen(); collection[1] = 45; - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), collection), new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(56,1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(45, 1), collection), new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(45,1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); + ]); } public void Insert() @@ -436,20 +436,20 @@ public void Insert() collection.Add(4); collection.Add(56); collection.Add(8); listen(); collection.Insert(1, 45); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(45,1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(45, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); + ]); } public void InsertAll() { collection.Add(4); collection.Add(56); collection.Add(8); listen(); - collection.InsertAll(1, new int[] { 666, 777, 888 }); + collection.InsertAll(1, [666, 777, 888]); //seen.Print(Console.Error); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(666,1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(666, 1), collection), new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(777,2), collection), @@ -457,9 +457,9 @@ public void InsertAll() new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(888,3), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(888, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); - collection.InsertAll(1, new int[] { }); - seen.Check(new CollectionEvent[] { }); + ]); + collection.InsertAll(1, []); + seen.Check([]); } public void InsertFirstLast() @@ -467,17 +467,17 @@ public void InsertFirstLast() collection.Add(4); collection.Add(56); collection.Add(18); listen(); collection.InsertFirst(45); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(45,0), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(45, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); + ]); collection.InsertLast(88); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(88,4), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(88, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); + ]); } public void Remove() @@ -486,14 +486,14 @@ public void Remove() collection.Add(4); collection.Add(56); collection.Add(18); listen(); collection.Remove(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(18, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); collection.FIFO = true; collection.Remove(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(4, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); } public void RemoveFirst() @@ -501,10 +501,10 @@ public void RemoveFirst() collection.Add(4); collection.Add(56); collection.Add(18); listen(); collection.RemoveFirst(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(4,0), collection), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(4, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); } public void RemoveLast() @@ -512,10 +512,10 @@ public void RemoveLast() collection.Add(4); collection.Add(56); collection.Add(18); listen(); collection.RemoveLast(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(18,2), collection), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(18, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); } public void Reverse() @@ -523,11 +523,11 @@ public void Reverse() collection.Add(4); collection.Add(56); collection.Add(8); listen(); collection.Reverse(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); + ]); collection.View(1, 0).Reverse(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } @@ -536,11 +536,11 @@ public void Sort() collection.Add(4); collection.Add(56); collection.Add(8); listen(); collection.Sort(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); + ]); collection.View(1, 0).Sort(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } public void Shuffle() @@ -548,11 +548,11 @@ public void Shuffle() collection.Add(4); collection.Add(56); collection.Add(8); listen(); collection.Shuffle(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); + ]); collection.View(1, 0).Shuffle(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } public override void Clear() @@ -560,17 +560,17 @@ public override void Clear() collection.Add(4); collection.Add(56); collection.Add(18); listen(); collection.View(1, 1).Clear(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Cleared, new ClearedRangeEventArgs(false,1,1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); + ]); collection.Clear(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Cleared, new ClearedRangeEventArgs(true,2,0), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); + ]); collection.Clear(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } public void ListDispose() @@ -578,14 +578,14 @@ public void ListDispose() collection.Add(4); collection.Add(56); collection.Add(18); listen(); collection.View(1, 1).Dispose(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); collection.Dispose(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Cleared, new ClearedRangeEventArgs(true,3,0), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); + ]); collection.Dispose(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } /* @@ -683,27 +683,27 @@ public override SCG.IEnumerable GetSpecs() public void PushPop() { listen(); - seen.Check(new CollectionEvent[0]); + seen.Check([]); collection.Push(23); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(23,0), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(23, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); collection.Push(-12); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(-12,1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(-12, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); collection.Pop(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(-12,1), collection), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(-12, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); collection.Pop(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(23,0), collection), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(23, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); } } @@ -718,25 +718,25 @@ public void EnqueueDequeue() { listen(); collection.Enqueue(67); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(67,0), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(67, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); collection.Enqueue(2); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(2,1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(2, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); collection.Dequeue(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(67,0), collection), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(67, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); collection.Dequeue(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(2,0), collection), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(2, 1), collection), - new CollectionEvent(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent(EventType.Changed, new EventArgs(), collection)]); } } @@ -752,46 +752,45 @@ public void Direct() { listen(); collection.Add(34); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(34, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection), - }); + ]); collection.Add(56); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(56, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection), - }); - collection.AddAll(new int[] { }); - seen.Check(new CollectionEvent[] { - }); + ]); + collection.AddAll([]); + seen.Check([]); collection.Add(34); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(34, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection), - }); + ]); collection.Add(12); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(12, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection), - }); + ]); collection.DeleteMax(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection), - }); + ]); collection.DeleteMin(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(12, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection), - }); - collection.AddAll(new int[] { 4, 5, 6, 2 }); - seen.Check(new CollectionEvent[] { + ]); + collection.AddAll([4, 5, 6, 2]); + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(4, 1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(5, 1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(6, 1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(2, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection) - }); + ]); } public void WithHandles() @@ -799,48 +798,48 @@ public void WithHandles() listen(); IPriorityQueueHandle handle = null; collection.Add(34); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(34, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection), - }); + ]); collection.Add(56); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(56, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection), - }); + ]); collection.Add(ref handle, 34); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(34, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection), - }); + ]); collection.Add(12); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(12, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection), - }); + ]); collection.DeleteMax(out _); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection), - }); + ]); collection.DeleteMin(out _); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(12, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection), - }); + ]); collection.Replace(handle, 117); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(34, 1), collection), new CollectionEvent(EventType.Added, new ItemCountEventArgs(117, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection), - }); + ]); collection.Delete(handle); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(117, 1), collection), new CollectionEvent(EventType.Changed, new EventArgs(), collection), - }); + ]); } } @@ -853,24 +852,27 @@ public override SCG.IEnumerable GetSpecs() public virtual void Listenable() { - Assert.AreEqual(EventType.Basic, collection.ListenableEvents); - Assert.AreEqual(EventType.None, collection.ActiveEvents); + Assert.Multiple(() => + { + Assert.That(collection.ListenableEvents, Is.EqualTo(EventType.Basic)); + Assert.That(collection.ActiveEvents, Is.EqualTo(EventType.None)); + }); listen(); - Assert.AreEqual(listenTo, collection.ActiveEvents); + Assert.That(collection.ActiveEvents, Is.EqualTo(listenTo)); } public void AddAndREmove() { listen(); - seen.Check(new CollectionEvent>[0]); + seen.Check([]); collection.Add(23, 45); - seen.Check(new CollectionEvent>[] { + seen.Check([ new CollectionEvent>(EventType.Added, new ItemCountEventArgs>(new System.Collections.Generic.KeyValuePair(23,45), 1), collection), - new CollectionEvent>(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent>(EventType.Changed, new EventArgs(), collection)]); collection.Remove(25); - seen.Check(new CollectionEvent>[] { + seen.Check([ new CollectionEvent>(EventType.Removed, new ItemCountEventArgs>(new System.Collections.Generic.KeyValuePair(23,45), 1), collection), - new CollectionEvent>(EventType.Changed, new EventArgs(), collection)}); + new CollectionEvent>(EventType.Changed, new EventArgs(), collection)]); } diff --git a/C5.Tests/Templates/GenericCollectionTester.cs b/C5.Tests/Templates/GenericCollectionTester.cs index 8145c283..09135105 100644 --- a/C5.Tests/Templates/GenericCollectionTester.cs +++ b/C5.Tests/Templates/GenericCollectionTester.cs @@ -57,7 +57,7 @@ public abstract class GenericCollectionTester : GenericCollectionTester GetSpecs() { - return new int[] { 0 }; + return [0]; } public override void SetUp(U collection, int testSpec) diff --git a/C5.Tests/Templates/List.cs b/C5.Tests/Templates/List.cs index dbac78b3..0fb1cfa1 100644 --- a/C5.Tests/Templates/List.cs +++ b/C5.Tests/Templates/List.cs @@ -10,7 +10,7 @@ internal class Dispose { public static void Tester() where U : class, IList, new() { - U extensible = new U(); + U extensible = new(); extensible.Dispose(); } } @@ -24,9 +24,12 @@ internal class SCG_IList slist.Add(5); slist.Add(6); slist.RemoveAt(1); - Assert.AreEqual(2, slist.Count); - Assert.AreEqual(4, slist[0]); - Assert.AreEqual(6, slist[1]); + Assert.That(slist, Has.Count.EqualTo(2)); + Assert.Multiple(() => + { + Assert.That(slist[0], Is.EqualTo(4)); + Assert.That(slist[1], Is.EqualTo(6)); + }); } } } diff --git a/C5.Tests/Trees/Bag.cs b/C5.Tests/Trees/Bag.cs index 251a1d29..0ddb53c4 100644 --- a/C5.Tests/Trees/Bag.cs +++ b/C5.Tests/Trees/Bag.cs @@ -8,9 +8,6 @@ namespace C5.Tests.trees.TreeBag { - using CollectionOfInt = TreeBag; - - [TestFixture] public class NewTest { @@ -32,7 +29,7 @@ public void A() //list.dump(); // OK list.Remove(316201); //list.dump(); // Not OK - Assert.IsTrue(list.Check()); + Assert.That(list.Check(), Is.True); } [Test] public void B() @@ -51,7 +48,7 @@ public void B() list.Remove(r); //list.dump(); list.Remove(r); - Assert.IsTrue(list.Check("removing" + r)); + Assert.That(list.Check("removing" + r), Is.True); } } } @@ -62,16 +59,9 @@ public class GenericTesters [Test] public void TestEvents() { - CollectionOfInt factory() { return new CollectionOfInt(TenEqualityComparer.Default); } - new C5.Tests.Templates.Events.SortedIndexedTester().Test(factory); + TreeBag factory() { return new TreeBag(TenEqualityComparer.Default); } + new C5.Tests.Templates.Events.SortedIndexedTester>().Test(factory); } - - //[Test] - //public void Extensible() - //{ - // C5.Tests.Templates.Extensible.Clone.Tester(); - // C5.Tests.Templates.Extensible.Serialization.Tester(); - //} } internal static class Factory @@ -92,116 +82,143 @@ public class Formatting [Test] public void Format() { - Assert.AreEqual("{{ }}", coll.ToString()); - coll.AddAll(new int[] { -4, 28, 129, 65530, -4, 28 }); - Assert.AreEqual("{{ -4(*2), 28(*2), 129(*1), 65530(*1) }}", coll.ToString()); - Assert.AreEqual("{{ -4(*2), 1C(*2), 81(*1), FFFA(*1) }}", coll.ToString(null, rad16)); - Assert.AreEqual("{{ -4(*2), 28(*2)... }}", coll.ToString("L18", null)); - Assert.AreEqual("{{ -4(*2), 1C(*2)... }}", coll.ToString("L18", rad16)); + Assert.That(coll.ToString(), Is.EqualTo("{{ }}")); + coll.AddAll([-4, 28, 129, 65530, -4, 28]); + Assert.Multiple(() => + { + Assert.That(coll.ToString(), Is.EqualTo("{{ -4(*2), 28(*2), 129(*1), 65530(*1) }}")); + Assert.That(coll.ToString(null, rad16), Is.EqualTo("{{ -4(*2), 1C(*2), 81(*1), FFFA(*1) }}")); + Assert.That(coll.ToString("L18", null), Is.EqualTo("{{ -4(*2), 28(*2)... }}")); + Assert.That(coll.ToString("L18", rad16), Is.EqualTo("{{ -4(*2), 1C(*2)... }}")); + }); } } [TestFixture] public class Combined { - private IIndexedSorted> lst; + private TreeBag> lst; [SetUp] public void Init() { - lst = new TreeBag>(new KeyValuePairComparer(new IC())); + lst = new TreeBag>(new KeyValuePairComparer(new IC())); for (int i = 0; i < 10; i++) { - lst.Add(new System.Collections.Generic.KeyValuePair(i, i + 30)); + lst.Add(new SCG.KeyValuePair(i, i + 30)); } } [TearDown] - public void Dispose() { lst = null; } + public void Dispose() { lst.Dispose(); } [Test] public void Find() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Find(ref p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); - p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Find(ref p)); + Assert.Multiple(() => + { + Assert.That(lst.Find(ref p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); + p = new SCG.KeyValuePair(13, 78); + Assert.That(lst.Find(ref p), Is.False); } [Test] public void FindOrAdd() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.FindOrAdd(ref p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); - p = new System.Collections.Generic.KeyValuePair(13, 79); - Assert.IsFalse(lst.FindOrAdd(ref p)); - Assert.AreEqual(13, lst[11].Key); - Assert.AreEqual(79, lst[11].Value); + Assert.Multiple(() => + { + Assert.That(lst.FindOrAdd(ref p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); + p = new SCG.KeyValuePair(13, 79); + Assert.Multiple(() => + { + Assert.That(lst.FindOrAdd(ref p), Is.False); + Assert.That(lst[11].Key, Is.EqualTo(13)); + Assert.That(lst[11].Value, Is.EqualTo(79)); + }); } [Test] public void Update() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Update(p)); - Assert.AreEqual(3, lst[3].Key); - Assert.AreEqual(78, lst[3].Value); - p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Update(p)); + Assert.Multiple(() => + { + Assert.That(lst.Update(p), Is.True); + Assert.That(lst[3].Key, Is.EqualTo(3)); + Assert.That(lst[3].Value, Is.EqualTo(78)); + }); + p = new SCG.KeyValuePair(13, 78); + Assert.That(lst.Update(p), Is.False); } [Test] public void UpdateOrAdd1() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.UpdateOrAdd(p)); - Assert.AreEqual(3, lst[3].Key); - Assert.AreEqual(78, lst[3].Value); - p = new System.Collections.Generic.KeyValuePair(13, 79); - Assert.IsFalse(lst.UpdateOrAdd(p)); - Assert.AreEqual(13, lst[10].Key); - Assert.AreEqual(79, lst[10].Value); + Assert.Multiple(() => + { + Assert.That(lst.UpdateOrAdd(p), Is.True); + Assert.That(lst[3].Key, Is.EqualTo(3)); + Assert.That(lst[3].Value, Is.EqualTo(78)); + }); + p = new SCG.KeyValuePair(13, 79); + Assert.Multiple(() => + { + Assert.That(lst.UpdateOrAdd(p), Is.False); + Assert.That(lst[10].Key, Is.EqualTo(13)); + Assert.That(lst[10].Value, Is.EqualTo(79)); + }); } [Test] public void UpdateOrAdd2() { - ICollection coll = new TreeBag(); + ICollection coll = new TreeBag(); // s1 and s2 are distinct objects but contain the same text: - String s1 = "abc", s2 = ("def" + s1).Substring(3); - Assert.IsFalse(coll.UpdateOrAdd(s1, out string old)); - Assert.AreEqual(null, old); - Assert.IsTrue(coll.UpdateOrAdd(s2, out old)); - Assert.IsTrue(Object.ReferenceEquals(s1, old)); - Assert.IsFalse(Object.ReferenceEquals(s2, old)); + string s1 = "abc", s2 = ("def" + s1).Substring(3); + Assert.Multiple(() => + { + Assert.That(coll.UpdateOrAdd(s1, out string old), Is.False); + Assert.That(old, Is.EqualTo(null)); + Assert.That(coll.UpdateOrAdd(s2, out old), Is.True); + Assert.That(ReferenceEquals(s1, old), Is.True); + Assert.That(ReferenceEquals(s2, old), Is.False); + }); } [Test] public void RemoveWithReturn() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Remove(p, out p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); - Assert.AreEqual(4, lst[3].Key); - Assert.AreEqual(34, lst[3].Value); - p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Remove(p, out _)); + Assert.Multiple(() => + { + Assert.That(lst.Remove(p, out p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + Assert.That(lst[3].Key, Is.EqualTo(4)); + Assert.That(lst[3].Value, Is.EqualTo(34)); + }); + p = new SCG.KeyValuePair(13, 78); + Assert.That(lst.Remove(p, out _), Is.False); } } @@ -222,108 +239,135 @@ public void Init() [TearDown] public void Dispose() { - bag = null; + bag.Dispose(); } [Test] public void Initial() { - Assert.IsFalse(bag.IsReadOnly); - Assert.AreEqual(0, bag.Count, "new bag should be empty"); - Assert.AreEqual(0, bag.ContainsCount("A")); - Assert.AreEqual(0, bag.ContainsCount("B")); - Assert.AreEqual(0, bag.ContainsCount("C")); - Assert.IsFalse(bag.Contains("A")); - Assert.IsFalse(bag.Contains("B")); - Assert.IsFalse(bag.Contains("C")); + Assert.Multiple(() => + { + Assert.That(bag.IsReadOnly, Is.False); + Assert.That(bag, Is.Empty, "new bag should be empty"); + }); + Assert.Multiple(() => + { + Assert.That(bag.ContainsCount("A"), Is.EqualTo(0)); + Assert.That(bag.ContainsCount("B"), Is.EqualTo(0)); + Assert.That(bag.ContainsCount("C"), Is.EqualTo(0)); + Assert.That(bag.Contains("A"), Is.False); + Assert.That(bag.Contains("B"), Is.False); + Assert.That(bag.Contains("C"), Is.False); + }); bag.Add("A"); - Assert.AreEqual(1, bag.Count); - Assert.AreEqual(1, bag.ContainsCount("A")); - Assert.AreEqual(0, bag.ContainsCount("B")); - Assert.AreEqual(0, bag.ContainsCount("C")); - Assert.IsTrue(bag.Contains("A")); - Assert.IsFalse(bag.Contains("B")); - Assert.IsFalse(bag.Contains("C")); + Assert.That(bag, Has.Count.EqualTo(1)); + Assert.Multiple(() => + { + Assert.That(bag.ContainsCount("A"), Is.EqualTo(1)); + Assert.That(bag.ContainsCount("B"), Is.EqualTo(0)); + Assert.That(bag.ContainsCount("C"), Is.EqualTo(0)); + Assert.That(bag.Contains("A"), Is.True); + Assert.That(bag.Contains("B"), Is.False); + Assert.That(bag.Contains("C"), Is.False); + }); bag.Add("C"); - Assert.AreEqual(2, bag.Count); - Assert.AreEqual(1, bag.ContainsCount("A")); - Assert.AreEqual(0, bag.ContainsCount("B")); - Assert.AreEqual(1, bag.ContainsCount("C")); - Assert.IsTrue(bag.Contains("A")); - Assert.IsFalse(bag.Contains("B")); - Assert.IsTrue(bag.Contains("C")); + Assert.That(bag, Has.Count.EqualTo(2)); + Assert.Multiple(() => + { + Assert.That(bag.ContainsCount("A"), Is.EqualTo(1)); + Assert.That(bag.ContainsCount("B"), Is.EqualTo(0)); + Assert.That(bag.ContainsCount("C"), Is.EqualTo(1)); + Assert.That(bag.Contains("A"), Is.True); + Assert.That(bag.Contains("B"), Is.False); + Assert.That(bag.Contains("C"), Is.True); + }); bag.Add("C"); - Assert.AreEqual(3, bag.Count); - Assert.AreEqual(1, bag.ContainsCount("A")); - Assert.AreEqual(0, bag.ContainsCount("B")); - Assert.AreEqual(2, bag.ContainsCount("C")); - Assert.IsTrue(bag.Contains("A")); - Assert.IsFalse(bag.Contains("B")); - Assert.IsTrue(bag.Contains("C")); + Assert.That(bag, Has.Count.EqualTo(3)); + Assert.Multiple(() => + { + Assert.That(bag.ContainsCount("A"), Is.EqualTo(1)); + Assert.That(bag.ContainsCount("B"), Is.EqualTo(0)); + Assert.That(bag.ContainsCount("C"), Is.EqualTo(2)); + Assert.That(bag.Contains("A"), Is.True); + Assert.That(bag.Contains("B"), Is.False); + Assert.That(bag.Contains("C"), Is.True); + }); bag.Add("B"); bag.Add("C"); - Assert.AreEqual(5, bag.Count); - Assert.AreEqual(1, bag.ContainsCount("A")); - Assert.AreEqual(1, bag.ContainsCount("B")); - Assert.AreEqual(3, bag.ContainsCount("C")); - Assert.IsTrue(bag.Contains("A")); - Assert.IsTrue(bag.Contains("B")); - Assert.IsTrue(bag.Contains("C")); + Assert.That(bag, Has.Count.EqualTo(5)); + Assert.Multiple(() => + { + Assert.That(bag.ContainsCount("A"), Is.EqualTo(1)); + Assert.That(bag.ContainsCount("B"), Is.EqualTo(1)); + Assert.That(bag.ContainsCount("C"), Is.EqualTo(3)); + Assert.That(bag.Contains("A"), Is.True); + Assert.That(bag.Contains("B"), Is.True); + Assert.That(bag.Contains("C"), Is.True); + }); _ = bag.Remove("C"); - Assert.AreEqual(4, bag.Count); - Assert.AreEqual(1, bag.ContainsCount("A")); - Assert.AreEqual(1, bag.ContainsCount("B")); - Assert.AreEqual(2, bag.ContainsCount("C")); - Assert.IsTrue(bag.Contains("A")); - Assert.IsTrue(bag.Contains("B")); - Assert.IsTrue(bag.Contains("C")); + Assert.That(bag, Has.Count.EqualTo(4)); + Assert.Multiple(() => + { + Assert.That(bag.ContainsCount("A"), Is.EqualTo(1)); + Assert.That(bag.ContainsCount("B"), Is.EqualTo(1)); + Assert.That(bag.ContainsCount("C"), Is.EqualTo(2)); + Assert.That(bag.Contains("A"), Is.True); + Assert.That(bag.Contains("B"), Is.True); + Assert.That(bag.Contains("C"), Is.True); + }); _ = bag.Remove("A"); - Assert.AreEqual(3, bag.Count); - Assert.AreEqual(0, bag.ContainsCount("A")); - Assert.AreEqual(1, bag.ContainsCount("B")); - Assert.AreEqual(2, bag.ContainsCount("C")); - Assert.IsFalse(bag.Contains("A")); - Assert.IsTrue(bag.Contains("B")); - Assert.IsTrue(bag.Contains("C")); + Assert.That(bag, Has.Count.EqualTo(3)); + Assert.Multiple(() => + { + Assert.That(bag.ContainsCount("A"), Is.EqualTo(0)); + Assert.That(bag.ContainsCount("B"), Is.EqualTo(1)); + Assert.That(bag.ContainsCount("C"), Is.EqualTo(2)); + Assert.That(bag.Contains("A"), Is.False); + Assert.That(bag.Contains("B"), Is.True); + Assert.That(bag.Contains("C"), Is.True); + }); bag.RemoveAllCopies("C"); - Assert.AreEqual(1, bag.Count); - Assert.AreEqual(0, bag.ContainsCount("A")); - Assert.AreEqual(1, bag.ContainsCount("B")); - Assert.AreEqual(0, bag.ContainsCount("C")); - Assert.IsFalse(bag.Contains("A")); - Assert.IsTrue(bag.Contains("B")); - Assert.IsFalse(bag.Contains("C")); - Assert.IsFalse(bag.Contains("Z")); - Assert.IsFalse(bag.Remove("Z")); + Assert.That(bag, Has.Count.EqualTo(1)); + Assert.Multiple(() => + { + Assert.That(bag.ContainsCount("A"), Is.EqualTo(0)); + Assert.That(bag.ContainsCount("B"), Is.EqualTo(1)); + Assert.That(bag.ContainsCount("C"), Is.EqualTo(0)); + Assert.That(bag.Contains("A"), Is.False); + Assert.That(bag.Contains("B"), Is.True); + Assert.That(bag.Contains("C"), Is.False); + Assert.That(bag.Contains("Z"), Is.False); + Assert.That(bag.Remove("Z"), Is.False); + }); bag.RemoveAllCopies("Z"); - Assert.AreEqual(1, bag.Count); - Assert.AreEqual(0, bag.ContainsCount("A")); - Assert.AreEqual(1, bag.ContainsCount("B")); - Assert.AreEqual(0, bag.ContainsCount("C")); - Assert.IsFalse(bag.Contains("A")); - Assert.IsTrue(bag.Contains("B")); - Assert.IsFalse(bag.Contains("C")); - Assert.IsFalse(bag.Contains("Z")); + Assert.That(bag, Has.Count.EqualTo(1)); + Assert.That(bag.ContainsCount("A"), Is.EqualTo(0)); + Assert.That(bag.ContainsCount("B"), Is.EqualTo(1)); + Assert.That(bag.ContainsCount("C"), Is.EqualTo(0)); + Assert.That(bag.Contains("A"), Is.False); + Assert.That(bag.Contains("B"), Is.True); + Assert.That(bag.Contains("C"), Is.False); + Assert.That(bag.Contains("Z"), Is.False); } } [TestFixture] public class FindOrAdd { - private TreeBag> bag; + private TreeBag> bag; [SetUp] public void Init() { - bag = new TreeBag>(new KeyValuePairComparer(new IC())); + bag = new TreeBag>(new KeyValuePairComparer(new IC())); } [TearDown] public void Dispose() { - bag = null; + bag.Dispose(); } @@ -331,13 +375,19 @@ public void Dispose() public void Test() { var p = new SCG.KeyValuePair(3, "tre"); - Assert.IsFalse(bag.FindOrAdd(ref p)); + Assert.That(bag.FindOrAdd(ref p), Is.False); p = new SCG.KeyValuePair(p.Key, "drei"); - Assert.IsTrue(bag.FindOrAdd(ref p)); - Assert.AreEqual("tre", p.Value); + Assert.Multiple(() => + { + Assert.That(bag.FindOrAdd(ref p), Is.True); + Assert.That(p.Value, Is.EqualTo("tre")); + }); p = new SCG.KeyValuePair(p.Key, "three"); - Assert.AreEqual(2, bag.ContainsCount(p)); - Assert.AreEqual("tre", bag[0].Value); + Assert.Multiple(() => + { + Assert.That(bag.ContainsCount(p), Is.EqualTo(2)); + Assert.That(bag[0].Value, Is.EqualTo("tre")); + }); } } @@ -366,8 +416,8 @@ public void Init() [TearDown] public void Dispose() { - bagenum = null; - bag = null; + bagenum.Dispose(); + bag.Dispose(); } @@ -384,23 +434,26 @@ public void MoveNextOnModified() [Test] public void NormalUse() { - Assert.IsTrue(bagenum.MoveNext()); - Assert.AreEqual(bagenum.Current, "A"); - Assert.IsTrue(bagenum.MoveNext()); - Assert.AreEqual(bagenum.Current, "A"); - Assert.IsTrue(bagenum.MoveNext()); - Assert.AreEqual(bagenum.Current, "A"); - Assert.IsTrue(bagenum.MoveNext()); - Assert.AreEqual(bagenum.Current, "B"); - Assert.IsTrue(bagenum.MoveNext()); - Assert.AreEqual(bagenum.Current, "B"); - Assert.IsTrue(bagenum.MoveNext()); - Assert.AreEqual(bagenum.Current, "B"); - Assert.IsTrue(bagenum.MoveNext()); - Assert.AreEqual(bagenum.Current, "C"); - Assert.IsTrue(bagenum.MoveNext()); - Assert.AreEqual(bagenum.Current, "D"); - Assert.IsFalse(bagenum.MoveNext()); + Assert.Multiple(() => + { + Assert.That(bagenum.MoveNext(), Is.True); + Assert.That(bagenum.Current, Is.EqualTo("A")); + }); + Assert.That(bagenum.MoveNext(), Is.True); + Assert.That(bagenum.Current, Is.EqualTo("A")); + Assert.That(bagenum.MoveNext(), Is.True); + Assert.That(bagenum.Current, Is.EqualTo("A")); + Assert.That(bagenum.MoveNext(), Is.True); + Assert.That(bagenum.Current, Is.EqualTo("B")); + Assert.That(bagenum.MoveNext(), Is.True); + Assert.That(bagenum.Current, Is.EqualTo("B")); + Assert.That(bagenum.MoveNext(), Is.True); + Assert.That(bagenum.Current, Is.EqualTo("B")); + Assert.That(bagenum.MoveNext(), Is.True); + Assert.That(bagenum.Current, Is.EqualTo("C")); + Assert.That(bagenum.MoveNext(), Is.True); + Assert.That(bagenum.Current, Is.EqualTo("D")); + Assert.That(bagenum.MoveNext(), Is.False); } } @@ -429,13 +482,13 @@ public void Enumerator() { SCG.IEnumerator e = tree.RangeFromTo(5, 17).GetEnumerator(); int i = 0; - int[] all = new int[] { 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16 }; + int[] all = [5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16]; while (e.MoveNext()) { - Assert.AreEqual(all[i++], e.Current); + Assert.That(e.Current, Is.EqualTo(all[i++])); } - Assert.AreEqual(12, i); + Assert.That(i, Is.EqualTo(12)); } @@ -464,124 +517,133 @@ public void Enumerator3() [Test] public void Remove() { - int[] all = new int[] { 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16, 18, 20 }; + int[] all = [1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16, 18, 20]; tree.RemoveRangeFrom(18); - Assert.IsTrue(IC.Eq(tree, new int[] { 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16 })); + Assert.That(IC.Eq(tree, [1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16]), Is.True); tree.RemoveRangeFrom(28); - Assert.IsTrue(IC.Eq(tree, new int[] { 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16 })); + Assert.That(IC.Eq(tree, [1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16]), Is.True); tree.RemoveRangeFrom(1); - Assert.IsTrue(IC.Eq(tree)); + Assert.That(IC.Eq(tree), Is.True); foreach (int i in all) { tree.Add(i); } tree.RemoveRangeTo(10); - Assert.IsTrue(IC.Eq(tree, new int[] { 10, 10, 12, 14, 16, 18, 20 })); + Assert.That(IC.Eq(tree, [10, 10, 12, 14, 16, 18, 20]), Is.True); tree.RemoveRangeTo(2); - Assert.IsTrue(IC.Eq(tree, new int[] { 10, 10, 12, 14, 16, 18, 20 })); + Assert.That(IC.Eq(tree, [10, 10, 12, 14, 16, 18, 20]), Is.True); tree.RemoveRangeTo(21); - Assert.IsTrue(IC.Eq(tree)); + Assert.That(IC.Eq(tree), Is.True); foreach (int i in all) { tree.Add(i); } tree.RemoveRangeFromTo(4, 8); - Assert.IsTrue(IC.Eq(tree, 1, 2, 2, 3, 8, 8, 9, 10, 10, 12, 14, 16, 18, 20)); + Assert.That(IC.Eq(tree, 1, 2, 2, 3, 8, 8, 9, 10, 10, 12, 14, 16, 18, 20), Is.True); tree.RemoveRangeFromTo(14, 28); - Assert.IsTrue(IC.Eq(tree, 1, 2, 2, 3, 8, 8, 9, 10, 10, 12)); + Assert.That(IC.Eq(tree, 1, 2, 2, 3, 8, 8, 9, 10, 10, 12), Is.True); tree.RemoveRangeFromTo(0, 9); - Assert.IsTrue(IC.Eq(tree, 9, 10, 10, 12)); + Assert.That(IC.Eq(tree, 9, 10, 10, 12), Is.True); tree.RemoveRangeFromTo(0, 81); - Assert.IsTrue(IC.Eq(tree)); + Assert.That(IC.Eq(tree), Is.True); } [Test] public void Normal() { - int[] all = new int[] { 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16, 18, 20 }; - - Assert.IsTrue(IC.Eq(tree, all)); - Assert.IsTrue(IC.Eq(tree.RangeAll(), all)); - Assert.AreEqual(20, tree.RangeAll().Count); - Assert.IsTrue(IC.Eq(tree.RangeFrom(11), new int[] { 12, 14, 16, 18, 20 })); - Assert.AreEqual(5, tree.RangeFrom(11).Count); - Assert.IsTrue(IC.Eq(tree.RangeFrom(12), new int[] { 12, 14, 16, 18, 20 })); - Assert.IsTrue(IC.Eq(tree.RangeFrom(1), all)); - Assert.IsTrue(IC.Eq(tree.RangeFrom(0), all)); - Assert.IsTrue(IC.Eq(tree.RangeFrom(21), new int[] { })); - Assert.IsTrue(IC.Eq(tree.RangeFrom(20), new int[] { 20 })); - Assert.IsTrue(IC.Eq(tree.RangeTo(8), new int[] { 1, 2, 2, 3, 4, 4, 5, 6, 6, 7 })); - Assert.IsTrue(IC.Eq(tree.RangeTo(7), new int[] { 1, 2, 2, 3, 4, 4, 5, 6, 6 })); - Assert.AreEqual(9, tree.RangeTo(7).Count); - Assert.IsTrue(IC.Eq(tree.RangeTo(1), new int[] { })); - Assert.IsTrue(IC.Eq(tree.RangeTo(0), new int[] { })); - Assert.IsTrue(IC.Eq(tree.RangeTo(3), new int[] { 1, 2, 2 })); - Assert.IsTrue(IC.Eq(tree.RangeTo(20), new int[] { 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16, 18 })); - Assert.IsTrue(IC.Eq(tree.RangeTo(21), all)); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(7, 12), new int[] { 7, 8, 8, 9, 10, 10 })); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(6, 11), new int[] { 6, 6, 7, 8, 8, 9, 10, 10 })); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(1, 12), new int[] { 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10 })); - Assert.AreEqual(15, tree.RangeFromTo(1, 12).Count); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(2, 12), new int[] { 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10 })); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(6, 21), new int[] { 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16, 18, 20 })); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(6, 20), new int[] { 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16, 18 })); + int[] all = [1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16, 18, 20]; + + Assert.Multiple(() => + { + Assert.That(IC.Eq(tree, all), Is.True); + Assert.That(IC.Eq(tree.RangeAll(), all), Is.True); + Assert.That(tree.RangeAll(), Has.Count.EqualTo(20)); + Assert.That(IC.Eq(tree.RangeFrom(11), [12, 14, 16, 18, 20]), Is.True); + Assert.That(tree.RangeFrom(11), Has.Count.EqualTo(5)); + Assert.That(IC.Eq(tree.RangeFrom(12), [12, 14, 16, 18, 20]), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(1), all), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(0), all), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(21), []), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(20), [20]), Is.True); + Assert.That(IC.Eq(tree.RangeTo(8), [1, 2, 2, 3, 4, 4, 5, 6, 6, 7]), Is.True); + Assert.That(IC.Eq(tree.RangeTo(7), [1, 2, 2, 3, 4, 4, 5, 6, 6]), Is.True); + Assert.That(tree.RangeTo(7), Has.Count.EqualTo(9)); + Assert.That(IC.Eq(tree.RangeTo(1), []), Is.True); + Assert.That(IC.Eq(tree.RangeTo(0), []), Is.True); + Assert.That(IC.Eq(tree.RangeTo(3), [1, 2, 2]), Is.True); + Assert.That(IC.Eq(tree.RangeTo(20), [1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16, 18]), Is.True); + Assert.That(IC.Eq(tree.RangeTo(21), all), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(7, 12), [7, 8, 8, 9, 10, 10]), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(6, 11), [6, 6, 7, 8, 8, 9, 10, 10]), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(1, 12), [1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10]), Is.True); + Assert.That(tree.RangeFromTo(1, 12), Has.Count.EqualTo(15)); + Assert.That(IC.Eq(tree.RangeFromTo(2, 12), [2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10]), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(6, 21), [6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16, 18, 20]), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(6, 20), [6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16, 18]), Is.True); + }); } [Test] public void Backwards() { - int[] all = new int[] { 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16, 18, 20 }; - int[] lla = new int[] { 20, 18, 16, 14, 12, 10, 10, 9, 8, 8, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1 }; - - Assert.IsTrue(IC.Eq(tree, all)); - Assert.IsTrue(IC.Eq(tree.RangeAll().Backwards(), lla)); - Assert.IsTrue(IC.Eq(tree.RangeFrom(11).Backwards(), new int[] { 20, 18, 16, 14, 12 })); - Assert.IsTrue(IC.Eq(tree.RangeFrom(12).Backwards(), new int[] { 20, 18, 16, 14, 12 })); - Assert.IsTrue(IC.Eq(tree.RangeFrom(1).Backwards(), lla)); - Assert.IsTrue(IC.Eq(tree.RangeFrom(0).Backwards(), lla)); - Assert.IsTrue(IC.Eq(tree.RangeFrom(21).Backwards(), new int[] { })); - Assert.IsTrue(IC.Eq(tree.RangeFrom(20).Backwards(), new int[] { 20 })); - Assert.IsTrue(IC.Eq(tree.RangeTo(8).Backwards(), new int[] { 7, 6, 6, 5, 4, 4, 3, 2, 2, 1 })); - Assert.IsTrue(IC.Eq(tree.RangeTo(7).Backwards(), new int[] { 6, 6, 5, 4, 4, 3, 2, 2, 1 })); - Assert.IsTrue(IC.Eq(tree.RangeTo(1).Backwards(), new int[] { })); - Assert.IsTrue(IC.Eq(tree.RangeTo(0).Backwards(), new int[] { })); - Assert.IsTrue(IC.Eq(tree.RangeTo(3).Backwards(), new int[] { 2, 2, 1 })); - Assert.IsTrue(IC.Eq(tree.RangeTo(20).Backwards(), new int[] { 18, 16, 14, 12, 10, 10, 9, 8, 8, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1 })); - Assert.IsTrue(IC.Eq(tree.RangeTo(21).Backwards(), lla)); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(7, 12).Backwards(), new int[] { 10, 10, 9, 8, 8, 7 })); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(6, 11).Backwards(), new int[] { 10, 10, 9, 8, 8, 7, 6, 6 })); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(0, 12).Backwards(), new int[] { 10, 10, 9, 8, 8, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1 })); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(1, 12).Backwards(), new int[] { 10, 10, 9, 8, 8, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1 })); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(6, 21).Backwards(), new int[] { 20, 18, 16, 14, 12, 10, 10, 9, 8, 8, 7, 6, 6 })); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(6, 20).Backwards(), new int[] { 18, 16, 14, 12, 10, 10, 9, 8, 8, 7, 6, 6 })); + int[] all = [1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16, 18, 20]; + int[] lla = [20, 18, 16, 14, 12, 10, 10, 9, 8, 8, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1]; + + Assert.Multiple(() => + { + Assert.That(IC.Eq(tree, all), Is.True); + Assert.That(IC.Eq(tree.RangeAll().Backwards(), lla), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(11).Backwards(), [20, 18, 16, 14, 12]), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(12).Backwards(), [20, 18, 16, 14, 12]), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(1).Backwards(), lla), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(0).Backwards(), lla), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(21).Backwards(), []), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(20).Backwards(), [20]), Is.True); + Assert.That(IC.Eq(tree.RangeTo(8).Backwards(), [7, 6, 6, 5, 4, 4, 3, 2, 2, 1]), Is.True); + Assert.That(IC.Eq(tree.RangeTo(7).Backwards(), [6, 6, 5, 4, 4, 3, 2, 2, 1]), Is.True); + Assert.That(IC.Eq(tree.RangeTo(1).Backwards(), []), Is.True); + Assert.That(IC.Eq(tree.RangeTo(0).Backwards(), []), Is.True); + Assert.That(IC.Eq(tree.RangeTo(3).Backwards(), [2, 2, 1]), Is.True); + Assert.That(IC.Eq(tree.RangeTo(20).Backwards(), [18, 16, 14, 12, 10, 10, 9, 8, 8, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1]), Is.True); + Assert.That(IC.Eq(tree.RangeTo(21).Backwards(), lla), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(7, 12).Backwards(), [10, 10, 9, 8, 8, 7]), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(6, 11).Backwards(), [10, 10, 9, 8, 8, 7, 6, 6]), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(0, 12).Backwards(), [10, 10, 9, 8, 8, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1]), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(1, 12).Backwards(), [10, 10, 9, 8, 8, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1]), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(6, 21).Backwards(), [20, 18, 16, 14, 12, 10, 10, 9, 8, 8, 7, 6, 6]), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(6, 20).Backwards(), [18, 16, 14, 12, 10, 10, 9, 8, 8, 7, 6, 6]), Is.True); + }); } [Test] public void Direction() { - Assert.AreEqual(C5.Direction.Forwards, tree.Direction); - Assert.AreEqual(C5.Direction.Forwards, tree.RangeFrom(20).Direction); - Assert.AreEqual(C5.Direction.Forwards, tree.RangeTo(7).Direction); - Assert.AreEqual(C5.Direction.Forwards, tree.RangeFromTo(1, 12).Direction); - Assert.AreEqual(C5.Direction.Forwards, tree.RangeAll().Direction); - Assert.AreEqual(C5.Direction.Backwards, tree.Backwards().Direction); - Assert.AreEqual(C5.Direction.Backwards, tree.RangeFrom(20).Backwards().Direction); - Assert.AreEqual(C5.Direction.Backwards, tree.RangeTo(7).Backwards().Direction); - Assert.AreEqual(C5.Direction.Backwards, tree.RangeFromTo(1, 12).Backwards().Direction); - Assert.AreEqual(C5.Direction.Backwards, tree.RangeAll().Backwards().Direction); + Assert.Multiple(() => + { + Assert.That(tree.Direction, Is.EqualTo(C5.Direction.Forwards)); + Assert.That(tree.RangeFrom(20).Direction, Is.EqualTo(C5.Direction.Forwards)); + Assert.That(tree.RangeTo(7).Direction, Is.EqualTo(C5.Direction.Forwards)); + Assert.That(tree.RangeFromTo(1, 12).Direction, Is.EqualTo(C5.Direction.Forwards)); + Assert.That(tree.RangeAll().Direction, Is.EqualTo(C5.Direction.Forwards)); + Assert.That(tree.Backwards().Direction, Is.EqualTo(C5.Direction.Backwards)); + Assert.That(tree.RangeFrom(20).Backwards().Direction, Is.EqualTo(C5.Direction.Backwards)); + Assert.That(tree.RangeTo(7).Backwards().Direction, Is.EqualTo(C5.Direction.Backwards)); + Assert.That(tree.RangeFromTo(1, 12).Backwards().Direction, Is.EqualTo(C5.Direction.Backwards)); + Assert.That(tree.RangeAll().Backwards().Direction, Is.EqualTo(C5.Direction.Backwards)); + }); } [TearDown] public void Dispose() { - tree = null; + tree.Dispose(); c = null; } } @@ -609,11 +671,14 @@ public void Init() [Test] public void Both() { - Assert.AreEqual(0, tree.ContainsCount(7)); - Assert.AreEqual(1, tree.ContainsCount(10)); - Assert.AreEqual(2, tree.ContainsCount(17)); + Assert.Multiple(() => + { + Assert.That(tree.ContainsCount(7), Is.EqualTo(0)); + Assert.That(tree.ContainsCount(10), Is.EqualTo(1)); + Assert.That(tree.ContainsCount(17), Is.EqualTo(2)); + }); tree.RemoveAllCopies(17); - Assert.AreEqual(0, tree.ContainsCount(17)); + Assert.That(tree.ContainsCount(17), Is.EqualTo(0)); tree.RemoveAllCopies(7); } @@ -621,7 +686,7 @@ public void Both() [TearDown] public void Dispose() { - tree = null; + tree.Dispose(); } } @@ -677,7 +742,7 @@ public void NullEqualityComparerinConstructor5() public void Choose() { tree.Add(7); - Assert.AreEqual(7, tree.Choose()); + Assert.That(tree.Choose(), Is.EqualTo(7)); } [Test] @@ -690,28 +755,31 @@ public void BadChoose() [Test] public void NoDuplicates() { - Assert.IsTrue(tree.AllowsDuplicates); + Assert.That(tree.AllowsDuplicates, Is.True); loadup(); - Assert.IsTrue(tree.AllowsDuplicates); + Assert.That(tree.AllowsDuplicates, Is.True); } [Test] public void Add() { - Assert.IsTrue(tree.Add(17)); - Assert.IsTrue(tree.Add(17)); - Assert.IsTrue(tree.Add(18)); - Assert.IsTrue(tree.Add(18)); - Assert.AreEqual(4, tree.Count); - Assert.IsTrue(IC.Eq(tree, 17, 17, 18, 18)); + Assert.That(tree.Add(17), Is.True); + Assert.Multiple(() => + { + Assert.That(tree.Add(17), Is.True); + Assert.That(tree.Add(18), Is.True); + }); + Assert.That(tree.Add(18), Is.True); + Assert.That(tree, Has.Count.EqualTo(4)); + Assert.That(IC.Eq(tree, 17, 17, 18, 18), Is.True); } [TearDown] public void Dispose() { - tree = null; + tree.Dispose(); } } @@ -729,48 +797,54 @@ public void Init() } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } [Test] public void Find() { - Assert.IsFalse(list.Find(pred, out int i)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(list.Find(pred, out i)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.IsTrue(list.Find(pred, out i)); - Assert.AreEqual(45, i); + Assert.That(list.Find(pred, out int i), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(list.Find(pred, out i), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.Multiple(() => + { + Assert.That(list.Find(pred, out i), Is.True); + Assert.That(i, Is.EqualTo(45)); + }); } [Test] public void FindLast() { - Assert.IsFalse(list.FindLast(pred, out int i)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(list.FindLast(pred, out i)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.IsTrue(list.FindLast(pred, out i)); - Assert.AreEqual(675, i); + Assert.That(list.FindLast(pred, out int i), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(list.FindLast(pred, out i), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.Multiple(() => + { + Assert.That(list.FindLast(pred, out i), Is.True); + Assert.That(i, Is.EqualTo(675)); + }); } [Test] public void FindIndex() { - Assert.IsFalse(0 <= list.FindIndex(pred)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(0 <= list.FindIndex(pred)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.AreEqual(3, list.FindIndex(pred)); + Assert.That(0 <= list.FindIndex(pred), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(0 <= list.FindIndex(pred), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.That(list.FindIndex(pred), Is.EqualTo(3)); } [Test] public void FindLastIndex() { - Assert.IsFalse(0 <= list.FindLastIndex(pred)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(0 <= list.FindLastIndex(pred)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.AreEqual(7, list.FindLastIndex(pred)); + Assert.That(0 <= list.FindLastIndex(pred), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(0 <= list.FindLastIndex(pred), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.That(list.FindLastIndex(pred), Is.EqualTo(7)); } } @@ -783,16 +857,22 @@ public class UniqueItems public void Init() { list = new TreeBag(); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } [Test] public void Test() { - Assert.IsTrue(IC.SetEq(list.UniqueItems())); - Assert.IsTrue(IC.SetEq(list.ItemMultiplicities())); - list.AddAll(new int[] { 7, 9, 7 }); - Assert.IsTrue(IC.SetEq(list.UniqueItems(), 7, 9)); - Assert.IsTrue(IC.SetEq(list.ItemMultiplicities(), 7, 2, 9, 1)); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(list.UniqueItems()), Is.True); + Assert.That(IC.SetEq(list.ItemMultiplicities()), Is.True); + }); + list.AddAll([7, 9, 7]); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(list.UniqueItems(), 7, 9), Is.True); + Assert.That(IC.SetEq(list.ItemMultiplicities(), 7, 2, 9, 1), Is.True); + }); } } @@ -805,110 +885,110 @@ public class UniqueItemCount public void Init() { list = new TreeBag(); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } [Test] public void Test1() { - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); - list.AddAll(new int[] { 7, 9, 7 }); - Assert.AreEqual(2, list.UniqueCount); - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); + list.AddAll([7, 9, 7]); + Assert.That(list.UniqueCount, Is.EqualTo(2)); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); list.Remove(7); - Assert.AreEqual(2, list.UniqueCount); - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); + Assert.That(list.UniqueCount, Is.EqualTo(2)); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); list.Remove(7); - Assert.AreEqual(1, list.UniqueCount); - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); + Assert.That(list.UniqueCount, Is.EqualTo(1)); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); } [Test] public void Test2() { - list.AddSorted(new int[] { 7, 8, 9, 10, 10 }); - Assert.AreEqual(4, list.UniqueCount); - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); + list.AddSorted([7, 8, 9, 10, 10]); + Assert.That(list.UniqueCount, Is.EqualTo(4)); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); } [Test] public void Test3() { - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); list.Add(7); list.Add(9); list.Add(7); - Assert.AreEqual(2, list.UniqueCount); - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); + Assert.That(list.UniqueCount, Is.EqualTo(2)); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); list.Remove(7); - Assert.AreEqual(2, list.UniqueCount); - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); + Assert.That(list.UniqueCount, Is.EqualTo(2)); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); list.Remove(7); - Assert.AreEqual(1, list.UniqueCount); - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); + Assert.That(list.UniqueCount, Is.EqualTo(1)); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); } [Test] public void Test_FindOrAdd() { - list.AddSorted(new int[] { 7, 8, 9, 10, 10 }); + list.AddSorted([7, 8, 9, 10, 10]); int tmp = 7; list.FindOrAdd(ref tmp); - Assert.AreEqual(4, list.UniqueCount); - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); + Assert.That(list.UniqueCount, Is.EqualTo(4)); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); tmp = 11; list.FindOrAdd(ref tmp); - Assert.AreEqual(5, list.UniqueCount); - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); + Assert.That(list.UniqueCount, Is.EqualTo(5)); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); } [Test] public void Test_RemoveAllCopies() { - list.AddSorted(new int[] { 7, 8, 8, 9, 10, 10 }); + list.AddSorted([7, 8, 8, 9, 10, 10]); list.RemoveAllCopies(10); - Assert.AreEqual(3, list.UniqueCount); - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); + Assert.That(list.UniqueCount, Is.EqualTo(3)); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); } [Test] public void Test_DeleteMinMax() { - list.AddAll(new int[] { 7, 9, 9, 7 }); - Assert.AreEqual(2, list.UniqueCount); - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); + list.AddAll([7, 9, 9, 7]); + Assert.That(list.UniqueCount, Is.EqualTo(2)); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); list.DeleteMin(); - Assert.AreEqual(2, list.UniqueCount); - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); + Assert.That(list.UniqueCount, Is.EqualTo(2)); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); list.DeleteMax(); - Assert.AreEqual(2, list.UniqueCount); - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); + Assert.That(list.UniqueCount, Is.EqualTo(2)); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); list.DeleteMax(); - Assert.AreEqual(1, list.UniqueCount); - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); + Assert.That(list.UniqueCount, Is.EqualTo(1)); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); } [Test] @@ -927,50 +1007,62 @@ public void Test_ByIndex() int n = list.Count; i = list[10]; - Assert.AreEqual(17, list.RemoveAt(10)); - Assert.IsTrue(list.Check("")); - Assert.IsTrue(list.Contains(i)); - Assert.AreEqual(n - 1, list.Count); - Assert.AreEqual(17, list.RemoveAt(9)); - Assert.IsTrue(list.Check("")); - Assert.IsFalse(list.Contains(i)); - Assert.AreEqual(n - 2, list.Count); + Assert.Multiple(() => + { + Assert.That(list.RemoveAt(10), Is.EqualTo(17)); + Assert.That(list.Check(""), Is.True); + Assert.That(list.Contains(i), Is.True); + Assert.That(list, Has.Count.EqualTo(n - 1)); + }); + Assert.That(list.RemoveAt(9), Is.EqualTo(17)); + Assert.That(list.Check(""), Is.True); + Assert.That(list.Contains(i), Is.False); + Assert.That(list, Has.Count.EqualTo(n - 2)); - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); //Low end i = list.FindMin(); list.RemoveAt(0); - Assert.IsTrue(list.Check("")); - Assert.IsFalse(list.Contains(i)); - Assert.AreEqual(n - 3, list.Count); + Assert.Multiple(() => + { + Assert.That(list.Check(""), Is.True); + Assert.That(list.Contains(i), Is.False); + Assert.That(list, Has.Count.EqualTo(n - 3)); + }); - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); //high end i = list.FindMax(); list.RemoveAt(list.Count - 1); - Assert.IsTrue(list.Check("")); - Assert.IsFalse(list.Contains(i)); - Assert.AreEqual(n - 4, list.Count); + Assert.Multiple(() => + { + Assert.That(list.Check(""), Is.True); + Assert.That(list.Contains(i), Is.False); + Assert.That(list, Has.Count.EqualTo(n - 4)); + }); - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); //Some leaf //list.dump(); i = 18; - Assert.AreEqual(i, list.RemoveAt(9)); - Assert.IsTrue(list.Check("")); - Assert.AreEqual(i, list.RemoveAt(8)); - Assert.IsTrue(list.Check("")); - Assert.IsFalse(list.Contains(i)); - Assert.AreEqual(n - 6, list.Count); + Assert.Multiple(() => + { + Assert.That(list.RemoveAt(9), Is.EqualTo(i)); + Assert.That(list.Check(""), Is.True); + Assert.That(list.RemoveAt(8), Is.EqualTo(i)); + }); + Assert.That(list.Check(""), Is.True); + Assert.That(list.Contains(i), Is.False); + Assert.That(list, Has.Count.EqualTo(n - 6)); - Assert.AreEqual(list.UniqueItems().Count, list.UniqueCount); - Assert.AreEqual(list.ItemMultiplicities().Count, list.UniqueCount); + Assert.That(list.UniqueCount, Is.EqualTo(list.UniqueItems().Count)); + Assert.That(list.UniqueCount, Is.EqualTo(list.ItemMultiplicities().Count)); } } @@ -996,7 +1088,7 @@ public void Init() [TearDown] - public void Dispose() { tree = null; } + public void Dispose() { tree.Dispose(); } private string aeq(int[] a, params int[] b) @@ -1021,11 +1113,11 @@ private string aeq(int[] a, params int[] b) [Test] public void ToArray() { - Assert.AreEqual("Alles klar", aeq(tree.ToArray())); + Assert.That(aeq(tree.ToArray()), Is.EqualTo("Alles klar")); tree.Add(4); tree.Add(7); tree.Add(4); - Assert.AreEqual("Alles klar", aeq(tree.ToArray(), 4, 4, 7)); + Assert.That(aeq(tree.ToArray(), 4, 4, 7), Is.EqualTo("Alles klar")); } @@ -1033,19 +1125,19 @@ public void ToArray() public void CopyTo() { tree.CopyTo(a, 1); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009), Is.EqualTo("Alles klar")); tree.Add(6); tree.Add(6); tree.CopyTo(a, 2); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 6, 1004, 1005, 1006, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 6, 6, 1004, 1005, 1006, 1007, 1008, 1009), Is.EqualTo("Alles klar")); tree.Add(4); tree.Add(9); tree.CopyTo(a, 4); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 6, 4, 6, 6, 9, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 6, 6, 4, 6, 6, 9, 1008, 1009), Is.EqualTo("Alles klar")); tree.Clear(); tree.Add(7); tree.CopyTo(a, 9); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 6, 4, 6, 6, 9, 1008, 7)); + Assert.That(aeq(a, 1000, 1001, 6, 6, 4, 6, 6, 9, 1008, 7), Is.EqualTo("Alles klar")); } @@ -1098,8 +1190,11 @@ public void SmallTrees() tree.Add(9); tree.Add(7); tree.Add(9); - Assert.IsTrue(tree.Remove(7)); - Assert.IsTrue(tree.Check("")); + Assert.Multiple(() => + { + Assert.That(tree.Remove(7), Is.True); + Assert.That(tree.Check(""), Is.True); + }); } @@ -1110,38 +1205,53 @@ public void ByIndex() int n = tree.Count; int i = tree[10]; - Assert.AreEqual(17, tree.RemoveAt(10)); - Assert.IsTrue(tree.Check("")); - Assert.IsTrue(tree.Contains(i)); - Assert.AreEqual(n - 1, tree.Count); - Assert.AreEqual(17, tree.RemoveAt(9)); - Assert.IsTrue(tree.Check("")); - Assert.IsFalse(tree.Contains(i)); - Assert.AreEqual(n - 2, tree.Count); + Assert.Multiple(() => + { + Assert.That(tree.RemoveAt(10), Is.EqualTo(17)); + Assert.That(tree.Check(""), Is.True); + Assert.That(tree.Contains(i), Is.True); + Assert.That(tree, Has.Count.EqualTo(n - 1)); + }); + Assert.Multiple(() => + { + Assert.That(tree.RemoveAt(9), Is.EqualTo(17)); + Assert.That(tree.Check(""), Is.True); + Assert.That(tree.Contains(i), Is.False); + Assert.That(tree, Has.Count.EqualTo(n - 2)); + }); //Low end i = tree.FindMin(); tree.RemoveAt(0); - Assert.IsTrue(tree.Check("")); - Assert.IsFalse(tree.Contains(i)); - Assert.AreEqual(n - 3, tree.Count); + Assert.Multiple(() => + { + Assert.That(tree.Check(""), Is.True); + Assert.That(tree.Contains(i), Is.False); + Assert.That(tree, Has.Count.EqualTo(n - 3)); + }); //high end i = tree.FindMax(); tree.RemoveAt(tree.Count - 1); - Assert.IsTrue(tree.Check("")); - Assert.IsFalse(tree.Contains(i)); - Assert.AreEqual(n - 4, tree.Count); + Assert.Multiple(() => + { + Assert.That(tree.Check(""), Is.True); + Assert.That(tree.Contains(i), Is.False); + Assert.That(tree, Has.Count.EqualTo(n - 4)); + }); //Some leaf //tree.dump(); i = 18; - Assert.AreEqual(i, tree.RemoveAt(9)); - Assert.IsTrue(tree.Check("")); - Assert.AreEqual(i, tree.RemoveAt(8)); - Assert.IsTrue(tree.Check("")); - Assert.IsFalse(tree.Contains(i)); - Assert.AreEqual(n - 6, tree.Count); + Assert.Multiple(() => + { + Assert.That(tree.RemoveAt(9), Is.EqualTo(i)); + Assert.That(tree.Check(""), Is.True); + Assert.That(tree.RemoveAt(8), Is.EqualTo(i)); + }); + Assert.That(tree.Check(""), Is.True); + Assert.That(tree.Contains(i), Is.False); + Assert.That(tree, Has.Count.EqualTo(n - 6)); } @@ -1152,9 +1262,12 @@ public void AlmostEmpty() tree.Clear(); tree.Add(3); tree.RemoveAt(0); - Assert.IsTrue(tree.Check("")); - Assert.IsFalse(tree.Contains(3)); - Assert.AreEqual(0, tree.Count); + Assert.Multiple(() => + { + Assert.That(tree.Check(""), Is.True); + Assert.That(tree.Contains(3), Is.False); + Assert.That(tree, Is.Empty); + }); } @@ -1165,7 +1278,7 @@ public void Empty() var exception = Assert.Throws(() => tree.RemoveAt(0)); - Assert.AreEqual("Index out of range for sequenced collectionvalue", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Index out of range for sequenced collectionvalue")); } @@ -1174,7 +1287,7 @@ public void HighIndex() { var exception = Assert.Throws(() => tree.RemoveAt(tree.Count)); - Assert.AreEqual("Index out of range for sequenced collectionvalue", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Index out of range for sequenced collectionvalue")); } @@ -1183,55 +1296,64 @@ public void LowIndex() { var exception = Assert.Throws(() => tree.RemoveAt(-1)); - Assert.AreEqual("Index out of range for sequenced collectionvalue", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Index out of range for sequenced collectionvalue")); } [Test] public void Normal() { - //Note: ids does not match for bag - Assert.IsFalse(tree.Remove(-20)); + Assert.Multiple(() => + { + //Note: ids does not match for bag + Assert.That(tree.Remove(-20), Is.False); - //1b - Assert.IsTrue(tree.Remove(20)); - Assert.IsTrue(tree.Check("T1")); - Assert.IsFalse(tree.Remove(20)); + //1b + Assert.That(tree.Remove(20), Is.True); + Assert.That(tree.Check("T1"), Is.True); + }); + Assert.That(tree.Remove(20), Is.False); //1b - Assert.IsTrue(tree.Remove(10)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); + Assert.That(tree.Remove(10), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); //case 1c - Assert.IsTrue(tree.Remove(24)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); + Assert.That(tree.Remove(24), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); //1a (terminating) - Assert.IsTrue(tree.Remove(16)); - Assert.IsTrue(tree.Remove(16)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); + Assert.That(tree.Remove(16), Is.True); + Assert.Multiple(() => + { + Assert.That(tree.Remove(16), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); - //2 - Assert.IsTrue(tree.Remove(18)); - Assert.IsTrue(tree.Remove(17)); - Assert.IsTrue(tree.Remove(18)); - Assert.IsTrue(tree.Remove(17)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); + //2 + Assert.That(tree.Remove(18), Is.True); + Assert.That(tree.Remove(17), Is.True); + }); + Assert.That(tree.Remove(18), Is.True); + Assert.That(tree.Remove(17), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); //2+1b - Assert.IsTrue(tree.Remove(15)); - Assert.IsTrue(tree.Remove(15)); + Assert.That(tree.Remove(15), Is.True); + Assert.That(tree.Remove(15), Is.True); for (int i = 0; i < 5; i++) { tree.Add(17 + i); } - Assert.IsTrue(tree.Remove(23)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); + Assert.Multiple(() => + { + Assert.That(tree.Remove(23), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); - //1a+1b - Assert.IsTrue(tree.Remove(11)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); + //1a+1b + Assert.That(tree.Remove(11), Is.True); + }); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); //2+1c for (int i = 0; i < 10; i++) @@ -1239,10 +1361,13 @@ public void Normal() tree.Add(50 - 2 * i); } - Assert.IsTrue(tree.Remove(42)); - Assert.IsTrue(tree.Remove(38)); - Assert.IsTrue(tree.Remove(22)); - Assert.IsTrue(tree.Remove(40)); + Assert.Multiple(() => + { + Assert.That(tree.Remove(42), Is.True); + Assert.That(tree.Remove(38), Is.True); + Assert.That(tree.Remove(22), Is.True); + Assert.That(tree.Remove(40), Is.True); + }); // for (int i = 0; i < 48; i++) @@ -1250,21 +1375,24 @@ public void Normal() tree.Remove(i); } - //Almost empty tree:* - Assert.IsFalse(tree.Remove(26)); - Assert.IsTrue(tree.Remove(48)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); + Assert.Multiple(() => + { + //Almost empty tree:* + Assert.That(tree.Remove(26), Is.False); + Assert.That(tree.Remove(48), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + }); //Empty tree:* - Assert.IsFalse(tree.Remove(26)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); + Assert.That(tree.Remove(26), Is.False); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); } [TearDown] public void Dispose() { - tree = null; + tree.Dispose(); } } @@ -1298,14 +1426,17 @@ private void loadup() public void Predecessor() { loadup(); - Assert.AreEqual(6, tree.Predecessor(7)); - Assert.AreEqual(6, tree.Predecessor(8)); + Assert.Multiple(() => + { + Assert.That(tree.Predecessor(7), Is.EqualTo(6)); + Assert.That(tree.Predecessor(8), Is.EqualTo(6)); - //The bottom - Assert.AreEqual(0, tree.Predecessor(1)); + //The bottom + Assert.That(tree.Predecessor(1), Is.EqualTo(0)); - //The top - Assert.AreEqual(38, tree.Predecessor(39)); + //The top + Assert.That(tree.Predecessor(39), Is.EqualTo(38)); + }); } @@ -1327,16 +1458,19 @@ public void PredecessorTooLow2() public void WeakPredecessor() { loadup(); - Assert.AreEqual(6, tree.WeakPredecessor(7)); - Assert.AreEqual(8, tree.WeakPredecessor(8)); + Assert.Multiple(() => + { + Assert.That(tree.WeakPredecessor(7), Is.EqualTo(6)); + Assert.That(tree.WeakPredecessor(8), Is.EqualTo(8)); - //The bottom - Assert.AreEqual(0, tree.WeakPredecessor(1)); - Assert.AreEqual(0, tree.WeakPredecessor(0)); + //The bottom + Assert.That(tree.WeakPredecessor(1), Is.EqualTo(0)); + Assert.That(tree.WeakPredecessor(0), Is.EqualTo(0)); - //The top - Assert.AreEqual(38, tree.WeakPredecessor(39)); - Assert.AreEqual(38, tree.WeakPredecessor(38)); + //The top + Assert.That(tree.WeakPredecessor(39), Is.EqualTo(38)); + Assert.That(tree.WeakPredecessor(38), Is.EqualTo(38)); + }); } @@ -1351,15 +1485,18 @@ public void WeakPredecessorTooLow1() public void Successor() { loadup(); - Assert.AreEqual(8, tree.Successor(7)); - Assert.AreEqual(10, tree.Successor(8)); + Assert.Multiple(() => + { + Assert.That(tree.Successor(7), Is.EqualTo(8)); + Assert.That(tree.Successor(8), Is.EqualTo(10)); - //The bottom - Assert.AreEqual(2, tree.Successor(0)); - Assert.AreEqual(0, tree.Successor(-1)); + //The bottom + Assert.That(tree.Successor(0), Is.EqualTo(2)); + Assert.That(tree.Successor(-1), Is.EqualTo(0)); - //The top - Assert.AreEqual(38, tree.Successor(37)); + //The top + Assert.That(tree.Successor(37), Is.EqualTo(38)); + }); } @@ -1381,16 +1518,19 @@ public void SuccessorTooHigh2() public void WeakSuccessor() { loadup(); - Assert.AreEqual(6, tree.WeakSuccessor(6)); - Assert.AreEqual(8, tree.WeakSuccessor(7)); + Assert.Multiple(() => + { + Assert.That(tree.WeakSuccessor(6), Is.EqualTo(6)); + Assert.That(tree.WeakSuccessor(7), Is.EqualTo(8)); - //The bottom - Assert.AreEqual(0, tree.WeakSuccessor(-1)); - Assert.AreEqual(0, tree.WeakSuccessor(0)); + //The bottom + Assert.That(tree.WeakSuccessor(-1), Is.EqualTo(0)); + Assert.That(tree.WeakSuccessor(0), Is.EqualTo(0)); - //The top - Assert.AreEqual(38, tree.WeakSuccessor(37)); - Assert.AreEqual(38, tree.WeakSuccessor(38)); + //The top + Assert.That(tree.WeakSuccessor(37), Is.EqualTo(38)); + Assert.That(tree.WeakSuccessor(38), Is.EqualTo(38)); + }); } @@ -1404,7 +1544,7 @@ public void WeakSuccessorTooHigh1() [TearDown] public void Dispose() { - tree = null; + tree.Dispose(); } } @@ -1435,16 +1575,19 @@ private void loadup() public void Normal() { loadup(); - Assert.AreEqual(1, tree.FindMin()); - Assert.AreEqual(4, tree.FindMax()); - Assert.AreEqual(1, tree.DeleteMin()); - Assert.AreEqual(4, tree.DeleteMax()); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.AreEqual(1, tree.FindMin()); - Assert.AreEqual(3, tree.FindMax()); - Assert.AreEqual(1, tree.DeleteMin()); - Assert.AreEqual(3, tree.DeleteMax()); - Assert.IsTrue(tree.Check("Normal test 2"), "Bad tree"); + Assert.Multiple(() => + { + Assert.That(tree.FindMin(), Is.EqualTo(1)); + Assert.That(tree.FindMax(), Is.EqualTo(4)); + Assert.That(tree.DeleteMin(), Is.EqualTo(1)); + Assert.That(tree.DeleteMax(), Is.EqualTo(4)); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + }); + Assert.That(tree.FindMin(), Is.EqualTo(1)); + Assert.That(tree.FindMax(), Is.EqualTo(3)); + Assert.That(tree.DeleteMin(), Is.EqualTo(1)); + Assert.That(tree.DeleteMax(), Is.EqualTo(3)); + Assert.That(tree.Check("Normal test 2"), Is.True, "Bad tree"); } @@ -1479,7 +1622,7 @@ public void Empty4() [TearDown] public void Dispose() { - tree = null; + tree.Dispose(); } } @@ -1516,42 +1659,51 @@ public void ToArray() int[] a = tree.ToArray(); - Assert.AreEqual(6, a.Length); - Assert.AreEqual(10, a[0]); - Assert.AreEqual(30, a[1]); - Assert.AreEqual(30, a[2]); - Assert.AreEqual(50, a[3]); - Assert.AreEqual(70, a[4]); - Assert.AreEqual(70, a[5]); + Assert.That(a.Length, Is.EqualTo(6)); + Assert.Multiple(() => + { + Assert.That(a[0], Is.EqualTo(10)); + Assert.That(a[1], Is.EqualTo(30)); + Assert.That(a[2], Is.EqualTo(30)); + Assert.That(a[3], Is.EqualTo(50)); + Assert.That(a[4], Is.EqualTo(70)); + Assert.That(a[5], Is.EqualTo(70)); + }); } [Test] public void GoodIndex() { - Assert.AreEqual(-1, tree.IndexOf(20)); - Assert.AreEqual(-1, tree.LastIndexOf(20)); + Assert.Multiple(() => + { + Assert.That(tree.IndexOf(20), Is.EqualTo(-1)); + Assert.That(tree.LastIndexOf(20), Is.EqualTo(-1)); + }); populate(); - Assert.AreEqual(10, tree[0]); - Assert.AreEqual(30, tree[1]); - Assert.AreEqual(30, tree[2]); - Assert.AreEqual(50, tree[3]); - Assert.AreEqual(70, tree[4]); - Assert.AreEqual(70, tree[5]); - Assert.AreEqual(0, tree.IndexOf(10)); - Assert.AreEqual(1, tree.IndexOf(30)); - Assert.AreEqual(3, tree.IndexOf(50)); - Assert.AreEqual(4, tree.IndexOf(70)); - Assert.AreEqual(~1, tree.IndexOf(20)); - Assert.AreEqual(~0, tree.IndexOf(0)); - Assert.AreEqual(~6, tree.IndexOf(90)); - Assert.AreEqual(0, tree.LastIndexOf(10)); - Assert.AreEqual(2, tree.LastIndexOf(30)); - Assert.AreEqual(3, tree.LastIndexOf(50)); - Assert.AreEqual(5, tree.LastIndexOf(70)); - Assert.AreEqual(~1, tree.LastIndexOf(20)); - Assert.AreEqual(~0, tree.LastIndexOf(0)); - Assert.AreEqual(~6, tree.LastIndexOf(90)); + Assert.Multiple(() => + { + Assert.That(tree[0], Is.EqualTo(10)); + Assert.That(tree[1], Is.EqualTo(30)); + Assert.That(tree[2], Is.EqualTo(30)); + Assert.That(tree[3], Is.EqualTo(50)); + Assert.That(tree[4], Is.EqualTo(70)); + Assert.That(tree[5], Is.EqualTo(70)); + Assert.That(tree.IndexOf(10), Is.EqualTo(0)); + Assert.That(tree.IndexOf(30), Is.EqualTo(1)); + Assert.That(tree.IndexOf(50), Is.EqualTo(3)); + Assert.That(tree.IndexOf(70), Is.EqualTo(4)); + Assert.That(tree.IndexOf(20), Is.EqualTo(~1)); + Assert.That(tree.IndexOf(0), Is.EqualTo(~0)); + Assert.That(tree.IndexOf(90), Is.EqualTo(~6)); + Assert.That(tree.LastIndexOf(10), Is.EqualTo(0)); + Assert.That(tree.LastIndexOf(30), Is.EqualTo(2)); + Assert.That(tree.LastIndexOf(50), Is.EqualTo(3)); + Assert.That(tree.LastIndexOf(70), Is.EqualTo(5)); + Assert.That(tree.LastIndexOf(20), Is.EqualTo(~1)); + Assert.That(tree.LastIndexOf(0), Is.EqualTo(~0)); + Assert.That(tree.LastIndexOf(90), Is.EqualTo(~6)); + }); } @@ -1575,13 +1727,16 @@ public void IndexTooSmall() public void FilledTreeOutsideInput() { populate(); - Assert.AreEqual(0, tree.CountFrom(90)); - Assert.AreEqual(0, tree.CountFromTo(-20, 0)); - Assert.AreEqual(0, tree.CountFromTo(80, 100)); - Assert.AreEqual(0, tree.CountTo(0)); - Assert.AreEqual(6, tree.CountTo(90)); - Assert.AreEqual(6, tree.CountFromTo(-20, 90)); - Assert.AreEqual(6, tree.CountFrom(0)); + Assert.Multiple(() => + { + Assert.That(tree.CountFrom(90), Is.EqualTo(0)); + Assert.That(tree.CountFromTo(-20, 0), Is.EqualTo(0)); + Assert.That(tree.CountFromTo(80, 100), Is.EqualTo(0)); + Assert.That(tree.CountTo(0), Is.EqualTo(0)); + Assert.That(tree.CountTo(90), Is.EqualTo(6)); + Assert.That(tree.CountFromTo(-20, 90), Is.EqualTo(6)); + Assert.That(tree.CountFrom(0), Is.EqualTo(6)); + }); } @@ -1589,9 +1744,12 @@ public void FilledTreeOutsideInput() public void FilledTreeIntermediateInput() { populate(); - Assert.AreEqual(5, tree.CountFrom(20)); - Assert.AreEqual(2, tree.CountFromTo(20, 40)); - Assert.AreEqual(3, tree.CountTo(40)); + Assert.Multiple(() => + { + Assert.That(tree.CountFrom(20), Is.EqualTo(5)); + Assert.That(tree.CountFromTo(20, 40), Is.EqualTo(2)); + Assert.That(tree.CountTo(40), Is.EqualTo(3)); + }); } @@ -1599,28 +1757,34 @@ public void FilledTreeIntermediateInput() public void FilledTreeMatchingInput() { populate(); - Assert.AreEqual(5, tree.CountFrom(30)); - Assert.AreEqual(3, tree.CountFromTo(30, 70)); - Assert.AreEqual(0, tree.CountFromTo(50, 30)); - Assert.AreEqual(0, tree.CountFromTo(50, 50)); - Assert.AreEqual(0, tree.CountTo(10)); - Assert.AreEqual(3, tree.CountTo(50)); + Assert.Multiple(() => + { + Assert.That(tree.CountFrom(30), Is.EqualTo(5)); + Assert.That(tree.CountFromTo(30, 70), Is.EqualTo(3)); + Assert.That(tree.CountFromTo(50, 30), Is.EqualTo(0)); + Assert.That(tree.CountFromTo(50, 50), Is.EqualTo(0)); + Assert.That(tree.CountTo(10), Is.EqualTo(0)); + Assert.That(tree.CountTo(50), Is.EqualTo(3)); + }); } [Test] public void CountEmptyTree() { - Assert.AreEqual(0, tree.CountFrom(20)); - Assert.AreEqual(0, tree.CountFromTo(20, 40)); - Assert.AreEqual(0, tree.CountTo(40)); + Assert.Multiple(() => + { + Assert.That(tree.CountFrom(20), Is.EqualTo(0)); + Assert.That(tree.CountFromTo(20, 40), Is.EqualTo(0)); + Assert.That(tree.CountTo(40), Is.EqualTo(0)); + }); } [TearDown] public void Dispose() { - tree = null; + tree.Dispose(); } } @@ -1654,7 +1818,7 @@ public void CurrentAfterModification() { e.MoveNext(); tree.Add(34); - Assert.AreEqual(0, e.Current); + Assert.That(e.Current, Is.EqualTo(0)); } @@ -1685,8 +1849,8 @@ public void MoveNextAfterClear() [TearDown] public void Dispose() { - tree = null; - e = null; + tree.Dispose(); + e.Dispose(); } } @@ -1718,7 +1882,7 @@ public void CurrentAfterModification() { e.MoveNext(); tree.Add(34); - Assert.AreEqual(3, e.Current); + Assert.That(e.Current, Is.EqualTo(3)); } @@ -1749,8 +1913,8 @@ public void MoveNextAfterClear() [TearDown] public void Dispose() { - tree = null; - e = null; + tree.Dispose(); + e.Dispose(); } } } @@ -1793,7 +1957,7 @@ private bool twomodeleven(int i) [Test] public void InternalEnum() { - Assert.IsTrue(IC.Eq(snap.FindAll(new Func(twomodeleven)), 13, 13, 35)); + Assert.That(IC.Eq(snap.FindAll(new Func(twomodeleven)), 13, 13, 35), Is.True); } @@ -1807,93 +1971,114 @@ public void MoreCut() public void Cut() { - Assert.IsFalse(snap.Cut(new HigherOrder.CubeRoot(64), out int lo, out bool lv, out int hi, out bool hv)); - Assert.IsTrue(lv && hv); - Assert.AreEqual(5, hi); - Assert.AreEqual(3, lo); - Assert.IsTrue(snap.Cut(new HigherOrder.CubeRoot(125), out lo, out lv, out hi, out hv)); - Assert.IsTrue(lv && hv); - Assert.AreEqual(7, hi); - Assert.AreEqual(3, lo); - Assert.IsFalse(snap.Cut(new HigherOrder.CubeRoot(125000), out lo, out lv, out _, out hv)); - Assert.IsTrue(lv && !hv); - Assert.AreEqual(41, lo); - Assert.IsFalse(snap.Cut(new HigherOrder.CubeRoot(-27), out _, out lv, out hi, out hv)); - Assert.IsTrue(!lv && hv); - Assert.AreEqual(1, hi); + Assert.Multiple(() => + { + Assert.That(snap.Cut(new HigherOrder.CubeRoot(64), out int lo, out bool lv, out int hi, out bool hv), Is.False); + Assert.That(lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(5)); + Assert.That(lo, Is.EqualTo(3)); + Assert.That(snap.Cut(new HigherOrder.CubeRoot(125), out lo, out lv, out hi, out hv), Is.True); + Assert.That(lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(7)); + Assert.That(lo, Is.EqualTo(3)); + Assert.That(snap.Cut(new HigherOrder.CubeRoot(125000), out lo, out lv, out _, out hv), Is.False); + Assert.That(lv && !hv, Is.True); + Assert.That(lo, Is.EqualTo(41)); + Assert.That(snap.Cut(new HigherOrder.CubeRoot(-27), out _, out lv, out hi, out hv), Is.False); + Assert.That(!lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(1)); + }); } [Test] public void Range() { - Assert.IsTrue(IC.Eq(snap.RangeFromTo(5, 16), 5, 7, 9, 11, 13, 13, 15)); - Assert.IsTrue(IC.Eq(snap.RangeFromTo(5, 17), 5, 7, 9, 11, 13, 13, 15)); - Assert.IsTrue(IC.Eq(snap.RangeFromTo(6, 16), 7, 9, 11, 13, 13, 15)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(snap.RangeFromTo(5, 16), 5, 7, 9, 11, 13, 13, 15), Is.True); + Assert.That(IC.Eq(snap.RangeFromTo(5, 17), 5, 7, 9, 11, 13, 13, 15), Is.True); + Assert.That(IC.Eq(snap.RangeFromTo(6, 16), 7, 9, 11, 13, 13, 15), Is.True); + }); } [Test] public void Contains() { - Assert.IsTrue(snap.Contains(5)); - Assert.IsTrue(snap.Contains(13)); - Assert.AreEqual(1, snap.ContainsCount(5)); - Assert.AreEqual(2, snap.ContainsCount(13)); + Assert.Multiple(() => + { + Assert.That(snap.Contains(5), Is.True); + Assert.That(snap.Contains(13), Is.True); + Assert.That(snap.ContainsCount(5), Is.EqualTo(1)); + Assert.That(snap.ContainsCount(13), Is.EqualTo(2)); + }); } [Test] public void FindMin() { - Assert.AreEqual(1, snap.FindMin()); + Assert.That(snap.FindMin(), Is.EqualTo(1)); } [Test] public void FindMax() { - Assert.AreEqual(41, snap.FindMax()); + Assert.That(snap.FindMax(), Is.EqualTo(41)); } [Test] public void Predecessor() { - Assert.AreEqual(13, snap.Predecessor(15)); - Assert.AreEqual(15, snap.Predecessor(16)); - Assert.AreEqual(15, snap.Predecessor(17)); - Assert.AreEqual(17, snap.Predecessor(18)); + Assert.Multiple(() => + { + Assert.That(snap.Predecessor(15), Is.EqualTo(13)); + Assert.That(snap.Predecessor(16), Is.EqualTo(15)); + Assert.That(snap.Predecessor(17), Is.EqualTo(15)); + Assert.That(snap.Predecessor(18), Is.EqualTo(17)); + }); } [Test] public void Successor() { - Assert.AreEqual(17, snap.Successor(15)); - Assert.AreEqual(17, snap.Successor(16)); - Assert.AreEqual(19, snap.Successor(17)); - Assert.AreEqual(19, snap.Successor(18)); + Assert.Multiple(() => + { + Assert.That(snap.Successor(15), Is.EqualTo(17)); + Assert.That(snap.Successor(16), Is.EqualTo(17)); + Assert.That(snap.Successor(17), Is.EqualTo(19)); + Assert.That(snap.Successor(18), Is.EqualTo(19)); + }); } [Test] public void WeakPredecessor() { - Assert.AreEqual(15, snap.WeakPredecessor(15)); - Assert.AreEqual(15, snap.WeakPredecessor(16)); - Assert.AreEqual(17, snap.WeakPredecessor(17)); - Assert.AreEqual(17, snap.WeakPredecessor(18)); + Assert.Multiple(() => + { + Assert.That(snap.WeakPredecessor(15), Is.EqualTo(15)); + Assert.That(snap.WeakPredecessor(16), Is.EqualTo(15)); + Assert.That(snap.WeakPredecessor(17), Is.EqualTo(17)); + Assert.That(snap.WeakPredecessor(18), Is.EqualTo(17)); + }); } [Test] public void WeakSuccessor() { - Assert.AreEqual(15, snap.WeakSuccessor(15)); - Assert.AreEqual(17, snap.WeakSuccessor(16)); - Assert.AreEqual(17, snap.WeakSuccessor(17)); - Assert.AreEqual(19, snap.WeakSuccessor(18)); + Assert.Multiple(() => + { + Assert.That(snap.WeakSuccessor(15), Is.EqualTo(15)); + Assert.That(snap.WeakSuccessor(16), Is.EqualTo(17)); + Assert.That(snap.WeakSuccessor(17), Is.EqualTo(17)); + Assert.That(snap.WeakSuccessor(18), Is.EqualTo(19)); + }); } @@ -1904,7 +2089,7 @@ public void CountTo() { int j = snap.CountTo(15); }); - Assert.AreEqual("Indexing not supported for snapshots", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Indexing not supported for snapshots")); } @@ -1915,7 +2100,7 @@ public void Indexing() { int j = snap[4]; }); - Assert.AreEqual("Indexing not supported for snapshots", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Indexing not supported for snapshots")); } @@ -1927,7 +2112,7 @@ public void Indexing2() { int j = snap.IndexOf(5); }); - Assert.AreEqual("Indexing not supported for snapshots", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Indexing not supported for snapshots")); } @@ -1935,7 +2120,7 @@ public void Indexing2() [TearDown] public void Dispose() { - tree = null; + tree.Dispose(); ic = null; } } @@ -1966,7 +2151,7 @@ public void Bug20120422_1() var coll = new C5.TreeBag() { "C" }; _ = coll.Snapshot(); coll.Add("C"); - Assert.AreEqual(2, coll.ContainsCount("C")); + Assert.That(coll.ContainsCount("C"), Is.EqualTo(2)); } [Test] @@ -1980,48 +2165,66 @@ public void Bug20120422_2() }; _ = coll.Snapshot(); coll.Add("C"); - Assert.AreEqual(2, coll.ContainsCount("C")); - Assert.IsTrue(coll.Check()); + Assert.Multiple(() => + { + Assert.That(coll.ContainsCount("C"), Is.EqualTo(2)); + Assert.That(coll.Check(), Is.True); + }); coll.Add("A"); - Assert.AreEqual(2, coll.ContainsCount("A")); - Assert.AreEqual(2, coll.ContainsCount("C")); - Assert.IsTrue(coll.Check()); + Assert.Multiple(() => + { + Assert.That(coll.ContainsCount("A"), Is.EqualTo(2)); + Assert.That(coll.ContainsCount("C"), Is.EqualTo(2)); + Assert.That(coll.Check(), Is.True); + }); coll.Add("B"); - Assert.IsTrue(coll.Check()); - Assert.AreEqual(2, coll.ContainsCount("B")); - Assert.AreEqual(2, coll.ContainsCount("A")); - Assert.AreEqual(2, coll.ContainsCount("C")); + Assert.Multiple(() => + { + Assert.That(coll.Check(), Is.True); + Assert.That(coll.ContainsCount("B"), Is.EqualTo(2)); + Assert.That(coll.ContainsCount("A"), Is.EqualTo(2)); + Assert.That(coll.ContainsCount("C"), Is.EqualTo(2)); + }); _ = coll.Snapshot(); coll.Add("C"); - Assert.AreEqual(3, coll.ContainsCount("C")); - Assert.IsTrue(coll.Check()); + Assert.That(coll.ContainsCount("C"), Is.EqualTo(3)); + Assert.That(coll.Check(), Is.True); coll.Add("A"); - Assert.AreEqual(3, coll.ContainsCount("A")); - Assert.AreEqual(3, coll.ContainsCount("C")); - Assert.IsTrue(coll.Check()); + Assert.Multiple(() => + { + Assert.That(coll.ContainsCount("A"), Is.EqualTo(3)); + Assert.That(coll.ContainsCount("C"), Is.EqualTo(3)); + Assert.That(coll.Check(), Is.True); + }); coll.Add("B"); - Assert.IsTrue(coll.Check()); - Assert.AreEqual(3, coll.ContainsCount("B")); - Assert.AreEqual(3, coll.ContainsCount("A")); - Assert.AreEqual(3, coll.ContainsCount("C")); + Assert.Multiple(() => + { + Assert.That(coll.Check(), Is.True); + Assert.That(coll.ContainsCount("B"), Is.EqualTo(3)); + Assert.That(coll.ContainsCount("A"), Is.EqualTo(3)); + Assert.That(coll.ContainsCount("C"), Is.EqualTo(3)); + }); coll.RemoveAt(8); - Assert.AreEqual(2, coll.ContainsCount("C")); + Assert.That(coll.ContainsCount("C"), Is.EqualTo(2)); } [Test] public void EnumerationWithAdd() { - int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 }; + int[] orig = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]; int i = 0; TreeBag snap = (TreeBag)tree.Snapshot(); foreach (int j in snap) { - Assert.AreEqual(1 + 2 * i++, j); + Assert.That(j, Is.EqualTo(1 + 2 * i++)); tree.Add(21 - j); - Assert.IsTrue(snap.Check("M"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - Assert.IsTrue(tree.Check("Tree"), "Bad tree!"); + Assert.Multiple(() => + { + Assert.That(snap.Check("M"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + Assert.That(tree.Check("Tree"), Is.True, "Bad tree!"); + }); } } @@ -2029,15 +2232,21 @@ public void EnumerationWithAdd() [Test] public void Remove() { - int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 }; + int[] orig = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]; TreeBag snap = (TreeBag)tree.Snapshot(); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.Multiple(() => + { + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + }); tree.Remove(19); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(tree.Check("Tree"), "Bad tree!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.Multiple(() => + { + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(tree.Check("Tree"), Is.True, "Bad tree!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + }); } @@ -2052,68 +2261,77 @@ public void RemoveNormal() } tree.Add(15); - int[] orig = new int[] { 10, 11, 12, 13, 14, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 }; + int[] orig = [10, 11, 12, 13, 14, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]; TreeBag snap = (TreeBag)tree.Snapshot(); - Assert.IsFalse(tree.Remove(-20)); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.Multiple(() => + { + Assert.That(tree.Remove(-20), Is.False); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); - //decrease items case - Assert.IsTrue(tree.Remove(15)); - Assert.IsTrue(tree.Check("T1")); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); + //decrease items case + Assert.That(tree.Remove(15), Is.True); + Assert.That(tree.Check("T1"), Is.True); + }); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); //snap.dump(); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); //No demote case, with move_item - Assert.IsTrue(tree.Remove(20)); - Assert.IsTrue(tree.Check("T1")); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - Assert.IsFalse(tree.Remove(20)); + Assert.That(tree.Remove(20), Is.True); + Assert.That(tree.Check("T1"), Is.True); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + Assert.That(tree.Remove(20), Is.False); //plain case 2 tree.Snapshot(); - Assert.IsTrue(tree.Remove(14)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.Multiple(() => + { + Assert.That(tree.Remove(14), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); - //case 1b - Assert.IsTrue(tree.Remove(25)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + //case 1b + Assert.That(tree.Remove(25), Is.True); + }); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); //case 1c - Assert.IsTrue(tree.Remove(29)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.That(tree.Remove(29), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); //1a (terminating) - Assert.IsTrue(tree.Remove(10)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.That(tree.Remove(10), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); //2+1b - Assert.IsTrue(tree.Remove(12)); + Assert.That(tree.Remove(12), Is.True); tree.Snapshot(); - Assert.IsTrue(tree.Remove(11)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - - //1a+1b - Assert.IsTrue(tree.Remove(18)); - Assert.IsTrue(tree.Remove(13)); - Assert.IsTrue(tree.Remove(15)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.Multiple(() => + { + Assert.That(tree.Remove(11), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + + //1a+1b + Assert.That(tree.Remove(18), Is.True); + Assert.That(tree.Remove(13), Is.True); + Assert.That(tree.Remove(15), Is.True); + }); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); //2+1c for (int i = 0; i < 10; i++) @@ -2121,100 +2339,130 @@ public void RemoveNormal() tree.Add(50 - 2 * i); } - Assert.IsTrue(tree.Remove(42)); - Assert.IsTrue(tree.Remove(38)); - Assert.IsTrue(tree.Remove(28)); - Assert.IsTrue(tree.Remove(40)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - - // - Assert.IsTrue(tree.Remove(16)); - Assert.IsTrue(tree.Remove(23)); - Assert.IsTrue(tree.Remove(17)); - Assert.IsTrue(tree.Remove(19)); - Assert.IsTrue(tree.Remove(50)); - Assert.IsTrue(tree.Remove(26)); - Assert.IsTrue(tree.Remove(21)); - Assert.IsTrue(tree.Remove(22)); - Assert.IsTrue(tree.Remove(24)); + Assert.Multiple(() => + { + Assert.That(tree.Remove(42), Is.True); + Assert.That(tree.Remove(38), Is.True); + Assert.That(tree.Remove(28), Is.True); + Assert.That(tree.Remove(40), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + + // + Assert.That(tree.Remove(16), Is.True); + Assert.That(tree.Remove(23), Is.True); + Assert.That(tree.Remove(17), Is.True); + Assert.That(tree.Remove(19), Is.True); + Assert.That(tree.Remove(50), Is.True); + Assert.That(tree.Remove(26), Is.True); + Assert.That(tree.Remove(21), Is.True); + Assert.That(tree.Remove(22), Is.True); + Assert.That(tree.Remove(24), Is.True); + }); for (int i = 0; i < 48; i++) { tree.Remove(i); } - //Almost empty tree: - Assert.IsFalse(tree.Remove(26)); - Assert.IsTrue(tree.Remove(48)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.Multiple(() => + { + //Almost empty tree: + Assert.That(tree.Remove(26), Is.False); + Assert.That(tree.Remove(48), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + }); //Empty tree: - Assert.IsFalse(tree.Remove(26)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.That(tree.Remove(26), Is.False); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); } [Test] public void Add() { - int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 }; + int[] orig = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]; TreeBag snap = (TreeBag)tree.Snapshot(); - Assert.IsTrue(snap.Check("M"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - Assert.IsTrue(tree.Check("Tree"), "Bad tree!"); + Assert.Multiple(() => + { + Assert.That(snap.Check("M"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + Assert.That(tree.Check("Tree"), Is.True, "Bad tree!"); + }); tree.Add(10); - Assert.IsTrue(snap.Check("M"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - Assert.IsTrue(tree.Check("Tree"), "Bad tree!"); + Assert.Multiple(() => + { + Assert.That(snap.Check("M"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + Assert.That(tree.Check("Tree"), Is.True, "Bad tree!"); + }); tree.Add(16); - Assert.IsTrue(snap.Check("M"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - Assert.IsTrue(tree.Check("Tree"), "Bad tree!"); + Assert.Multiple(() => + { + Assert.That(snap.Check("M"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + Assert.That(tree.Check("Tree"), Is.True, "Bad tree!"); + }); tree.Add(9); - Assert.IsTrue(snap.Check("M"), "Bad snap!"); - Assert.IsTrue(tree.Check("Tree"), "Bad tree!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.Multiple(() => + { + Assert.That(snap.Check("M"), Is.True, "Bad snap!"); + Assert.That(tree.Check("Tree"), Is.True, "Bad tree!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + }); //Promote+zigzig tree.Add(40); - Assert.IsTrue(snap.Check("M"), "Bad snap!"); - Assert.IsTrue(tree.Check("Tree"), "Bad tree!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.Multiple(() => + { + Assert.That(snap.Check("M"), Is.True, "Bad snap!"); + Assert.That(tree.Check("Tree"), Is.True, "Bad tree!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + }); for (int i = 1; i < 4; i++) { tree.Add(40 - 2 * i); } - Assert.IsTrue(snap.Check("M"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - Assert.IsTrue(tree.Check("Tree"), "Bad tree!"); + Assert.Multiple(() => + { + Assert.That(snap.Check("M"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + Assert.That(tree.Check("Tree"), Is.True, "Bad tree!"); + }); //Zigzag: tree.Add(32); - Assert.IsTrue(snap.Check("M"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - Assert.IsTrue(tree.Check("Tree"), "Bad tree!"); + Assert.Multiple(() => + { + Assert.That(snap.Check("M"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + Assert.That(tree.Check("Tree"), Is.True, "Bad tree!"); + }); } [Test] public void Clear() { - int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 }; + int[] orig = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]; TreeBag snap = (TreeBag)tree.Snapshot(); tree.Clear(); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(tree.Check("Tree"), "Bad tree!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - Assert.AreEqual(0, tree.Count); + Assert.Multiple(() => + { + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(tree.Check("Tree"), Is.True, "Bad tree!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + Assert.That(tree, Is.Empty); + }); } @@ -2224,14 +2472,14 @@ public void SnapSnap() TreeBag snap = (TreeBag)tree.Snapshot(); var exception = Assert.Throws(() => snap.Snapshot()); - Assert.AreEqual("Cannot snapshot a snapshot", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Cannot snapshot a snapshot")); } [TearDown] public void Dispose() { - tree = null; + tree.Dispose(); ic = null; } } @@ -2241,24 +2489,12 @@ public void Dispose() [TestFixture] public class Multiple { +#pragma warning disable NUnit1032 // TODO: Breaks tests private TreeBag tree; +#pragma warning restore NUnit1032 // An IDisposable field/property should be Disposed in a TearDown method private SCG.IComparer ic; - - - /* private bool eq(SCG.IEnumerable me, int[] that) - { - int i = 0, maxind = that.Length - 1; - - foreach (int item in me) - if (i > maxind || ic.Compare(item, that[i++]) != 0) - return false; - - return true; - } */ - - [SetUp] public void Init() { @@ -2284,7 +2520,7 @@ public void First() for (int i = 0; i < 10; i++) { - Assert.AreEqual(i + 10, snaps[i].Count); + Assert.That(snaps[i], Has.Count.EqualTo(i + 10)); } snaps[5] = null; @@ -2293,16 +2529,19 @@ public void First() snaps[8].Dispose(); tree.Remove(14); - int[] res = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19 }; - int[] snap7 = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19 }; - int[] snap3 = new int[] { 0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 15, 17, 19 }; + int[] res = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19]; + int[] snap7 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19]; + int[] snap3 = [0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 15, 17, 19]; - Assert.IsTrue(IC.Eq(snaps[3], snap3), "Snap 3 was changed!"); - Assert.IsTrue(IC.Eq(snaps[7], snap7), "Snap 7 was changed!"); - Assert.IsTrue(IC.Eq(tree, res)); - Assert.IsTrue(tree.Check("B")); - Assert.IsTrue(snaps[3].Check("B")); - Assert.IsTrue(snaps[7].Check("B")); + Assert.Multiple(() => + { + Assert.That(IC.Eq(snaps[3], snap3), Is.True, "Snap 3 was changed!"); + Assert.That(IC.Eq(snaps[7], snap7), Is.True, "Snap 7 was changed!"); + Assert.That(IC.Eq(tree, res), Is.True); + Assert.That(tree.Check("B"), Is.True); + Assert.That(snaps[3].Check("B"), Is.True); + Assert.That(snaps[7].Check("B"), Is.True); + }); } @@ -2321,7 +2560,7 @@ public void CollectingTheMaster() GC.Collect(); for (int i = 0; i < 10; i++) { - Assert.AreEqual(i + 10, snaps[i].Count); + Assert.That(snaps[i], Has.Count.EqualTo(i + 10)); } snaps[5] = null; @@ -2329,28 +2568,28 @@ public void CollectingTheMaster() GC.Collect(); snaps[8].Dispose(); - int[] snap7 = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19 }; - int[] snap3 = new int[] { 0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 15, 17, 19 }; + int[] snap7 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19]; + int[] snap3 = [0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 15, 17, 19]; - Assert.IsTrue(IC.Eq(snaps[3], snap3), "Snap 3 was changed!"); - Assert.IsTrue(IC.Eq(snaps[7], snap7), "Snap 7 was changed!"); - Assert.IsTrue(snaps[3].Check("B")); - Assert.IsTrue(snaps[7].Check("B")); + Assert.Multiple(() => + { + Assert.That(IC.Eq(snaps[3], snap3), Is.True, "Snap 3 was changed!"); + Assert.That(IC.Eq(snaps[7], snap7), Is.True, "Snap 7 was changed!"); + Assert.That(snaps[3].Check("B"), Is.True); + Assert.That(snaps[7].Check("B"), Is.True); + }); } [TearDown] public void Dispose() { - tree = null; + //tree.Dispose(); ic = null; } } } - - - namespace HigherOrder { internal class CubeRoot : IComparable @@ -2421,13 +2660,16 @@ public void Init() [Test] public void Apply() { - Simple simple1 = new Simple(); + Simple simple1 = new(); tree.Apply(new Action(simple1.apply)); - Assert.AreEqual(0, simple1.appfield1); - Assert.AreEqual(0, simple1.appfield2); + Assert.Multiple(() => + { + Assert.That(simple1.appfield1, Is.EqualTo(0)); + Assert.That(simple1.appfield2, Is.EqualTo(0)); + }); - Simple simple2 = new Simple(); + Simple simple2 = new(); for (int i = 0; i < 10; i++) { @@ -2437,85 +2679,112 @@ public void Apply() tree.Add(2); tree.Apply(new Action(simple2.apply)); - Assert.AreEqual(11, simple2.appfield1); - Assert.AreEqual(289, simple2.appfield2); + Assert.Multiple(() => + { + Assert.That(simple2.appfield1, Is.EqualTo(11)); + Assert.That(simple2.appfield2, Is.EqualTo(289)); + }); } [Test] public void All() { - Assert.IsTrue(tree.All(new Func(never))); - Assert.IsTrue(tree.All(new Func(even))); - Assert.IsTrue(tree.All(new Func(always))); + Assert.Multiple(() => + { + Assert.That(tree.All(new Func(never)), Is.True); + Assert.That(tree.All(new Func(even)), Is.True); + Assert.That(tree.All(new Func(always)), Is.True); + }); for (int i = 0; i < 10; i++) { tree.Add(i); } - Assert.IsFalse(tree.All(new Func(never))); - Assert.IsFalse(tree.All(new Func(even))); - Assert.IsTrue(tree.All(new Func(always))); + Assert.Multiple(() => + { + Assert.That(tree.All(new Func(never)), Is.False); + Assert.That(tree.All(new Func(even)), Is.False); + Assert.That(tree.All(new Func(always)), Is.True); + }); tree.Clear(); for (int i = 0; i < 10; i++) { tree.Add(i * 2); } - Assert.IsFalse(tree.All(new Func(never))); - Assert.IsTrue(tree.All(new Func(even))); - Assert.IsTrue(tree.All(new Func(always))); + Assert.Multiple(() => + { + Assert.That(tree.All(new Func(never)), Is.False); + Assert.That(tree.All(new Func(even)), Is.True); + Assert.That(tree.All(new Func(always)), Is.True); + }); tree.Clear(); for (int i = 0; i < 10; i++) { tree.Add(i * 2 + 1); } - Assert.IsFalse(tree.All(new Func(never))); - Assert.IsFalse(tree.All(new Func(even))); - Assert.IsTrue(tree.All(new Func(always))); + Assert.Multiple(() => + { + Assert.That(tree.All(new Func(never)), Is.False); + Assert.That(tree.All(new Func(even)), Is.False); + Assert.That(tree.All(new Func(always)), Is.True); + }); } [Test] public void Exists() { - Assert.IsFalse(tree.Exists(new Func(never))); - Assert.IsFalse(tree.Exists(new Func(even))); - Assert.IsFalse(tree.Exists(new Func(always))); + Assert.Multiple(() => + { + Assert.That(tree.Exists(new Func(never)), Is.False); + Assert.That(tree.Exists(new Func(even)), Is.False); + Assert.That(tree.Exists(new Func(always)), Is.False); + }); for (int i = 0; i < 10; i++) { tree.Add(i); } - Assert.IsFalse(tree.Exists(new Func(never))); - Assert.IsTrue(tree.Exists(new Func(even))); - Assert.IsTrue(tree.Exists(new Func(always))); + Assert.Multiple(() => + { + Assert.That(tree.Exists(new Func(never)), Is.False); + Assert.That(tree.Exists(new Func(even)), Is.True); + Assert.That(tree.Exists(new Func(always)), Is.True); + }); tree.Clear(); for (int i = 0; i < 10; i++) { tree.Add(i * 2); } - Assert.IsFalse(tree.Exists(new Func(never))); - Assert.IsTrue(tree.Exists(new Func(even))); - Assert.IsTrue(tree.Exists(new Func(always))); + Assert.Multiple(() => + { + Assert.That(tree.Exists(new Func(never)), Is.False); + Assert.That(tree.Exists(new Func(even)), Is.True); + Assert.That(tree.Exists(new Func(always)), Is.True); + }); tree.Clear(); for (int i = 0; i < 10; i++) { tree.Add(i * 2 + 1); } - Assert.IsFalse(tree.Exists(new Func(never))); - Assert.IsFalse(tree.Exists(new Func(even))); - Assert.IsTrue(tree.Exists(new Func(always))); + Assert.Multiple(() => + { + Assert.That(tree.Exists(new Func(never)), Is.False); + Assert.That(tree.Exists(new Func(even)), Is.False); + Assert.That(tree.Exists(new Func(always)), Is.True); + }); } [Test] public void FindAll() { - Assert.AreEqual(0, tree.FindAll(new Func(never)).Count); + Assert.That(tree.FindAll(new Func(never)), Is.Empty); for (int i = 0; i < 10; i++) { tree.Add(i); @@ -2523,17 +2792,20 @@ public void FindAll() tree.Add(2); - Assert.AreEqual(0, tree.FindAll(new Func(never)).Count); - Assert.AreEqual(11, tree.FindAll(new Func(always)).Count); - Assert.AreEqual(6, tree.FindAll(new Func(even)).Count); - Assert.IsTrue(((TreeBag)tree.FindAll(new Func(even))).Check("R")); + Assert.Multiple(() => + { + Assert.That(tree.FindAll(new Func(never)), Is.Empty); + Assert.That(tree.FindAll(new Func(always)), Has.Count.EqualTo(11)); + Assert.That(tree.FindAll(new Func(even)), Has.Count.EqualTo(6)); + Assert.That(((TreeBag)tree.FindAll(new Func(even))).Check("R"), Is.True); + }); } [Test] public void Map() { - Assert.AreEqual(0, tree.Map(new Func(themap), new SC()).Count); + Assert.That(tree.Map(new Func(themap), new SC()), Is.Empty); for (int i = 0; i < 14; i++) { tree.Add(i * i * i); @@ -2543,15 +2815,21 @@ public void Map() IIndexedSorted res = tree.Map(new Func(themap), new SC()); - Assert.IsTrue(((TreeBag)res).Check("R")); - Assert.AreEqual(15, res.Count); - Assert.AreEqual("AA 0 BB", res[0]); - Assert.AreEqual("AA 1 BB", res[1]); - Assert.AreEqual("AA 1 BB", res[2]); - Assert.AreEqual("AA 8 BB", res[3]); - Assert.AreEqual("AA 27 BB", res[4]); - Assert.AreEqual("AA 125 BB", res[6]); - Assert.AreEqual("AA 1000 BB", res[11]); + Assert.Multiple(() => + { + Assert.That(((TreeBag)res).Check("R"), Is.True); + Assert.That(res, Has.Count.EqualTo(15)); + }); + Assert.Multiple(() => + { + Assert.That(res[0], Is.EqualTo("AA 0 BB")); + Assert.That(res[1], Is.EqualTo("AA 1 BB")); + Assert.That(res[2], Is.EqualTo("AA 1 BB")); + Assert.That(res[3], Is.EqualTo("AA 8 BB")); + Assert.That(res[4], Is.EqualTo("AA 27 BB")); + Assert.That(res[6], Is.EqualTo("AA 125 BB")); + Assert.That(res[11], Is.EqualTo("AA 1000 BB")); + }); } @@ -2568,7 +2846,7 @@ public void BadMap() ISorted res = tree.Map(new Func(badmap), new SC()); }); - Assert.AreEqual("mapper not monotonic", exception.Message); + Assert.That(exception.Message, Is.EqualTo("mapper not monotonic")); } @@ -2582,15 +2860,17 @@ public void Cut() tree.Add(3); - - Assert.IsTrue(tree.Cut(new CubeRoot(27), out int low, out bool lval, out int high, out bool hval)); - Assert.IsTrue(lval && hval); - Assert.AreEqual(4, high); - Assert.AreEqual(2, low); - Assert.IsFalse(tree.Cut(new CubeRoot(30), out low, out lval, out high, out hval)); - Assert.IsTrue(lval && hval); - Assert.AreEqual(4, high); - Assert.AreEqual(3, low); + Assert.Multiple(() => + { + Assert.That(tree.Cut(new CubeRoot(27), out int low, out bool lval, out int high, out bool hval), Is.True); + Assert.That(lval && hval, Is.True); + Assert.That(high, Is.EqualTo(4)); + Assert.That(low, Is.EqualTo(2)); + Assert.That(tree.Cut(new CubeRoot(30), out low, out lval, out high, out hval), Is.False); + Assert.That(lval && hval, Is.True); + Assert.That(high, Is.EqualTo(4)); + Assert.That(low, Is.EqualTo(3)); + }); } @@ -2602,14 +2882,17 @@ public void CutInt() tree.Add(2 * i); } - Assert.IsFalse(tree.Cut(new IC(3), out int low, out bool lval, out int high, out bool hval)); - Assert.IsTrue(lval && hval); - Assert.AreEqual(4, high); - Assert.AreEqual(2, low); - Assert.IsTrue(tree.Cut(new IC(6), out low, out lval, out high, out hval)); - Assert.IsTrue(lval && hval); - Assert.AreEqual(8, high); - Assert.AreEqual(4, low); + Assert.Multiple(() => + { + Assert.That(tree.Cut(new IC(3), out int low, out bool lval, out int high, out bool hval), Is.False); + Assert.That(lval && hval, Is.True); + Assert.That(high, Is.EqualTo(4)); + Assert.That(low, Is.EqualTo(2)); + Assert.That(tree.Cut(new IC(6), out low, out lval, out high, out hval), Is.True); + Assert.That(lval && hval, Is.True); + Assert.That(high, Is.EqualTo(8)); + Assert.That(low, Is.EqualTo(4)); + }); } @@ -2621,31 +2904,41 @@ public void CutInterval() tree.Add(2 * i); } - Assert.IsTrue(tree.Cut(new Interval(5, 9), out int lo, out bool lv, out int hi, out bool hv)); - Assert.IsTrue(lv && hv); - Assert.AreEqual(10, hi); - Assert.AreEqual(4, lo); - Assert.IsTrue(tree.Cut(new Interval(6, 10), out lo, out lv, out hi, out hv)); - Assert.IsTrue(lv && hv); - Assert.AreEqual(12, hi); - Assert.AreEqual(4, lo); + Assert.That(tree.Cut(new Interval(5, 9), out int lo, out bool lv, out int hi, out bool hv), Is.True); + Assert.That(lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(10)); + Assert.That(lo, Is.EqualTo(4)); + Assert.That(tree.Cut(new Interval(6, 10), out lo, out lv, out hi, out hv), Is.True); + Assert.That(lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(12)); + Assert.That(lo, Is.EqualTo(4)); + for (int i = 0; i < 100; i++) { tree.Add(2 * i); } tree.Cut(new Interval(77, 105), out lo, out lv, out hi, out hv); - Assert.IsTrue(lv && hv); - Assert.AreEqual(106, hi); - Assert.AreEqual(76, lo); + Assert.Multiple(() => + { + Assert.That(lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(106)); + Assert.That(lo, Is.EqualTo(76)); + }); tree.Cut(new Interval(5, 7), out lo, out lv, out hi, out hv); - Assert.IsTrue(lv && hv); - Assert.AreEqual(8, hi); - Assert.AreEqual(4, lo); + Assert.Multiple(() => + { + Assert.That(lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(8)); + Assert.That(lo, Is.EqualTo(4)); + }); tree.Cut(new Interval(80, 110), out lo, out lv, out hi, out hv); - Assert.IsTrue(lv && hv); - Assert.AreEqual(112, hi); - Assert.AreEqual(78, lo); + Assert.Multiple(() => + { + Assert.That(lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(112)); + Assert.That(lo, Is.EqualTo(78)); + }); } @@ -2657,17 +2950,20 @@ public void UpperCut() tree.Add(i); } - Assert.IsFalse(tree.Cut(new CubeRoot(1000), out int l, out bool lv, out _, out bool hv)); - Assert.IsTrue(lv && !hv); - Assert.AreEqual(9, l); - Assert.IsFalse(tree.Cut(new CubeRoot(-50), out _, out lv, out int h, out hv)); - Assert.IsTrue(!lv && hv); - Assert.AreEqual(0, h); + Assert.Multiple(() => + { + Assert.That(tree.Cut(new CubeRoot(1000), out int l, out bool lv, out _, out bool hv), Is.False); + Assert.That(lv && !hv, Is.True); + Assert.That(l, Is.EqualTo(9)); + Assert.That(tree.Cut(new CubeRoot(-50), out _, out lv, out int h, out hv), Is.False); + Assert.That(!lv && hv, Is.True); + Assert.That(h, Is.EqualTo(0)); + }); } [TearDown] - public void Dispose() { ic = null; tree = null; } + public void Dispose() { ic = null; tree.Dispose(); } } } @@ -2692,8 +2988,8 @@ public class AddAll public void EmptyEmpty() { tree.AddAll(new FunEnumerable(0, new Func(sqr))); - Assert.AreEqual(0, tree.Count); - Assert.IsTrue(tree.Check()); + Assert.That(tree, Is.Empty); + Assert.That(tree.Check(), Is.True); } @@ -2706,8 +3002,8 @@ public void SomeEmpty() } tree.AddAll(new FunEnumerable(0, new Func(sqr))); - Assert.AreEqual(5, tree.Count); - Assert.IsTrue(tree.Check()); + Assert.That(tree, Has.Count.EqualTo(5)); + Assert.That(tree.Check(), Is.True); } @@ -2715,12 +3011,15 @@ public void SomeEmpty() public void EmptySome() { tree.AddAll(new FunEnumerable(4, new Func(sqr))); - Assert.AreEqual(4, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.AreEqual(0, tree[0]); - Assert.AreEqual(1, tree[1]); - Assert.AreEqual(4, tree[2]); - Assert.AreEqual(9, tree[3]); + Assert.That(tree, Has.Count.EqualTo(4)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(tree[0], Is.EqualTo(0)); + Assert.That(tree[1], Is.EqualTo(1)); + Assert.That(tree[2], Is.EqualTo(4)); + Assert.That(tree[3], Is.EqualTo(9)); + }); } @@ -2735,14 +3034,17 @@ public void SomeSome() tree.Add(1); tree.AddAll(new FunEnumerable(4, new Func(sqr))); - Assert.AreEqual(9, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree, 0, 1, 1, 4, 5, 6, 7, 8, 9)); + Assert.That(tree, Has.Count.EqualTo(9)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree, 0, 1, 1, 4, 5, 6, 7, 8, 9), Is.True); + }); } [TearDown] - public void Dispose() { tree = null; } + public void Dispose() { tree.Dispose(); } } @@ -2768,8 +3070,8 @@ public class AddSorted public void EmptyEmpty() { tree.AddSorted(new FunEnumerable(0, new Func(sqr))); - Assert.AreEqual(0, tree.Count); - Assert.IsTrue(tree.Check()); + Assert.That(tree, Is.Empty); + Assert.That(tree.Check(), Is.True); } @@ -2782,8 +3084,8 @@ public void SomeEmpty() } tree.AddSorted(new FunEnumerable(0, new Func(sqr))); - Assert.AreEqual(5, tree.Count); - Assert.IsTrue(tree.Check()); + Assert.That(tree, Has.Count.EqualTo(5)); + Assert.That(tree.Check(), Is.True); } @@ -2791,12 +3093,15 @@ public void SomeEmpty() public void EmptySome() { tree.AddSorted(new FunEnumerable(4, new Func(sqr))); - Assert.AreEqual(4, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.AreEqual(0, tree[0]); - Assert.AreEqual(1, tree[1]); - Assert.AreEqual(4, tree[2]); - Assert.AreEqual(9, tree[3]); + Assert.That(tree, Has.Count.EqualTo(4)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(tree[0], Is.EqualTo(0)); + Assert.That(tree[1], Is.EqualTo(1)); + Assert.That(tree[2], Is.EqualTo(4)); + Assert.That(tree[3], Is.EqualTo(9)); + }); } [Test] @@ -2804,12 +3109,15 @@ public void EmptySome2() { tree.AddSorted(new FunEnumerable(4, new Func(step))); //tree.dump(); - Assert.AreEqual(4, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.AreEqual(0, tree[0]); - Assert.AreEqual(0, tree[1]); - Assert.AreEqual(0, tree[2]); - Assert.AreEqual(1, tree[3]); + Assert.That(tree, Has.Count.EqualTo(4)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(tree[0], Is.EqualTo(0)); + Assert.That(tree[1], Is.EqualTo(0)); + Assert.That(tree[2], Is.EqualTo(0)); + Assert.That(tree[3], Is.EqualTo(1)); + }); } @@ -2824,9 +3132,12 @@ public void SomeSome() tree.Add(1); tree.AddSorted(new FunEnumerable(4, new Func(sqr))); - Assert.AreEqual(9, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree, 0, 1, 1, 4, 5, 6, 7, 8, 9)); + Assert.That(tree, Has.Count.EqualTo(9)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree, 0, 1, 1, 4, 5, 6, 7, 8, 9), Is.True); + }); } @@ -2834,12 +3145,12 @@ public void SomeSome() public void EmptyBad() { var exception = Assert.Throws(() => tree.AddSorted(new FunEnumerable(9, new Func(bad)))); - Assert.AreEqual("Argument not sorted", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Argument not sorted")); } [TearDown] - public void Dispose() { tree = null; } + public void Dispose() { tree.Dispose(); } } @@ -2873,96 +3184,120 @@ public void Init() public void RemoveAll() { tree.RemoveAll(tree2.RangeFromTo(3, 7)); - Assert.AreEqual(9, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree, 0, 1, 2, 3, 4, 5, 7, 8, 9)); + Assert.That(tree, Has.Count.EqualTo(9)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree, 0, 1, 2, 3, 4, 5, 7, 8, 9), Is.True); + }); tree.RemoveAll(tree2.RangeFromTo(3, 7)); - Assert.AreEqual(8, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree, 0, 1, 2, 3, 5, 7, 8, 9)); + Assert.That(tree, Has.Count.EqualTo(8)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree, 0, 1, 2, 3, 5, 7, 8, 9), Is.True); + }); tree.RemoveAll(tree2.RangeFromTo(13, 17)); - Assert.AreEqual(8, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree, 0, 1, 2, 3, 5, 7, 8, 9)); + Assert.That(tree, Has.Count.EqualTo(8)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree, 0, 1, 2, 3, 5, 7, 8, 9), Is.True); + }); tree.RemoveAll(tree2.RangeFromTo(3, 17)); - Assert.AreEqual(7, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree, 0, 1, 2, 3, 5, 7, 9)); + Assert.That(tree, Has.Count.EqualTo(7)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree, 0, 1, 2, 3, 5, 7, 9), Is.True); + }); for (int i = 0; i < 10; i++) { tree2.Add(i); } tree.RemoveAll(tree2.RangeFromTo(-1, 10)); - Assert.AreEqual(0, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree)); - } - - /* - private void pint(SCG.IEnumerable e) - { - foreach (T i in e) - Console.Write("{0} ", i); - - Console.WriteLine(); + Assert.That(tree, Is.Empty); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree), Is.True); + }); } - */ [Test] public void RetainAll() { tree.Add(8); tree2.Add(6); - //pint(tree); - //pint(tree2); tree.RetainAll(tree2.RangeFromTo(3, 17)); - Assert.AreEqual(3, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree, 4, 6, 8)); + Assert.That(tree, Has.Count.EqualTo(3)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree, 4, 6, 8), Is.True); + }); tree.RetainAll(tree2.RangeFromTo(1, 17)); - Assert.AreEqual(3, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree, 4, 6, 8)); + Assert.That(tree, Has.Count.EqualTo(3)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree, 4, 6, 8), Is.True); + }); tree.RetainAll(tree2.RangeFromTo(3, 5)); - Assert.AreEqual(1, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree, 4)); + Assert.That(tree, Has.Count.EqualTo(1)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree, 4), Is.True); + }); tree.RetainAll(tree2.RangeFromTo(7, 17)); - Assert.AreEqual(0, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree)); + Assert.That(tree, Is.Empty); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree), Is.True); + }); for (int i = 0; i < 10; i++) { tree.Add(i); } tree.RetainAll(tree2.RangeFromTo(5, 5)); - Assert.AreEqual(0, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree)); + Assert.That(tree, Is.Empty); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree), Is.True); + }); for (int i = 0; i < 10; i++) { tree.Add(i); } tree.RetainAll(tree2.RangeFromTo(15, 25)); - Assert.AreEqual(0, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree)); + Assert.That(tree, Is.Empty); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree), Is.True); + }); } [Test] public void ContainsAll() { - Assert.IsFalse(tree.ContainsAll(tree2)); - Assert.IsTrue(tree.ContainsAll(tree)); + Assert.Multiple(() => + { + Assert.That(tree.ContainsAll(tree2), Is.False); + Assert.That(tree.ContainsAll(tree), Is.True); + }); tree2.Clear(); - Assert.IsTrue(tree.ContainsAll(tree2)); + Assert.That(tree.ContainsAll(tree2), Is.True); tree.Clear(); - Assert.IsTrue(tree.ContainsAll(tree2)); + Assert.That(tree.ContainsAll(tree2), Is.True); tree2.Add(8); - Assert.IsFalse(tree.ContainsAll(tree2)); + Assert.That(tree.ContainsAll(tree2), Is.False); } @@ -2970,17 +3305,26 @@ public void ContainsAll() public void RemoveInterval() { tree.RemoveInterval(3, 4); - Assert.IsTrue(tree.Check()); - Assert.AreEqual(7, tree.Count); - Assert.IsTrue(IC.Eq(tree, 0, 1, 2, 6, 7, 8, 9)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(tree, Has.Count.EqualTo(7)); + Assert.That(IC.Eq(tree, 0, 1, 2, 6, 7, 8, 9), Is.True); + }); tree.RemoveInterval(2, 3); - Assert.IsTrue(tree.Check()); - Assert.AreEqual(4, tree.Count); - Assert.IsTrue(IC.Eq(tree, 0, 1, 8, 9)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(tree, Has.Count.EqualTo(4)); + Assert.That(IC.Eq(tree, 0, 1, 8, 9), Is.True); + }); tree.RemoveInterval(0, 4); - Assert.IsTrue(tree.Check()); - Assert.AreEqual(0, tree.Count); - Assert.IsTrue(IC.Eq(tree)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(tree, Is.Empty); + Assert.That(IC.Eq(tree), Is.True); + }); } @@ -3008,67 +3352,79 @@ public void RemoveRangeBad3() [Test] public void GetRange() { - Assert.IsTrue(IC.Eq(tree[3, 0])); - Assert.IsTrue(IC.Eq(tree[3, 1], 3)); - Assert.IsTrue(IC.Eq(tree[3, 2], 3, 4)); - Assert.IsTrue(IC.Eq(tree[3, 3], 3, 4, 4)); - Assert.IsTrue(IC.Eq(tree[3, 4], 3, 4, 4, 5)); - Assert.IsTrue(IC.Eq(tree[4, 0])); - Assert.IsTrue(IC.Eq(tree[4, 1], 4)); - Assert.IsTrue(IC.Eq(tree[4, 2], 4, 4)); - Assert.IsTrue(IC.Eq(tree[4, 3], 4, 4, 5)); - Assert.IsTrue(IC.Eq(tree[4, 4], 4, 4, 5, 6)); - Assert.IsTrue(IC.Eq(tree[5, 0])); - Assert.IsTrue(IC.Eq(tree[5, 1], 4)); - Assert.IsTrue(IC.Eq(tree[5, 2], 4, 5)); - Assert.IsTrue(IC.Eq(tree[5, 3], 4, 5, 6)); - Assert.IsTrue(IC.Eq(tree[5, 4], 4, 5, 6, 7)); - Assert.IsTrue(IC.Eq(tree[5, 6], 4, 5, 6, 7, 8, 9)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(tree[3, 0]), Is.True); + Assert.That(IC.Eq(tree[3, 1], 3), Is.True); + Assert.That(IC.Eq(tree[3, 2], 3, 4), Is.True); + Assert.That(IC.Eq(tree[3, 3], 3, 4, 4), Is.True); + Assert.That(IC.Eq(tree[3, 4], 3, 4, 4, 5), Is.True); + Assert.That(IC.Eq(tree[4, 0]), Is.True); + Assert.That(IC.Eq(tree[4, 1], 4), Is.True); + Assert.That(IC.Eq(tree[4, 2], 4, 4), Is.True); + Assert.That(IC.Eq(tree[4, 3], 4, 4, 5), Is.True); + Assert.That(IC.Eq(tree[4, 4], 4, 4, 5, 6), Is.True); + Assert.That(IC.Eq(tree[5, 0]), Is.True); + Assert.That(IC.Eq(tree[5, 1], 4), Is.True); + Assert.That(IC.Eq(tree[5, 2], 4, 5), Is.True); + Assert.That(IC.Eq(tree[5, 3], 4, 5, 6), Is.True); + Assert.That(IC.Eq(tree[5, 4], 4, 5, 6, 7), Is.True); + Assert.That(IC.Eq(tree[5, 6], 4, 5, 6, 7, 8, 9), Is.True); + }); } [Test] public void GetRangeBug20090616() { - C5.TreeBag tree = new C5.TreeBag() { + C5.TreeBag tree = new() { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 3.0, 3.0, 4.0 }; for (int start = 0; start <= tree.Count - 2; start++) { double[] range = tree[start, 2].ToArray(); - Assert.AreEqual(range[0], tree[start]); - Assert.AreEqual(range[1], tree[start + 1]); + Assert.Multiple(() => + { + Assert.That(tree[start], Is.EqualTo(range[0])); + Assert.That(tree[start + 1], Is.EqualTo(range[1])); + }); } } [Test] public void GetRangeBackwards() { - Assert.IsTrue(IC.Eq(tree[3, 0].Backwards())); - Assert.IsTrue(IC.Eq(tree[3, 1].Backwards(), 3)); - Assert.IsTrue(IC.Eq(tree[3, 2].Backwards(), 4, 3)); - Assert.IsTrue(IC.Eq(tree[3, 3].Backwards(), 4, 4, 3)); - Assert.IsTrue(IC.Eq(tree[3, 4].Backwards(), 5, 4, 4, 3)); - Assert.IsTrue(IC.Eq(tree[4, 0].Backwards())); - Assert.IsTrue(IC.Eq(tree[4, 1].Backwards(), 4)); - Assert.IsTrue(IC.Eq(tree[4, 2].Backwards(), 4, 4)); - Assert.IsTrue(IC.Eq(tree[4, 3].Backwards(), 5, 4, 4)); - Assert.IsTrue(IC.Eq(tree[4, 4].Backwards(), 6, 5, 4, 4)); - Assert.IsTrue(IC.Eq(tree[5, 0].Backwards())); - Assert.IsTrue(IC.Eq(tree[5, 1].Backwards(), 4)); - Assert.IsTrue(IC.Eq(tree[5, 2].Backwards(), 5, 4)); - Assert.IsTrue(IC.Eq(tree[5, 3].Backwards(), 6, 5, 4)); - Assert.IsTrue(IC.Eq(tree[5, 4].Backwards(), 7, 6, 5, 4)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(tree[3, 0].Backwards()), Is.True); + Assert.That(IC.Eq(tree[3, 1].Backwards(), 3), Is.True); + Assert.That(IC.Eq(tree[3, 2].Backwards(), 4, 3), Is.True); + Assert.That(IC.Eq(tree[3, 3].Backwards(), 4, 4, 3), Is.True); + Assert.That(IC.Eq(tree[3, 4].Backwards(), 5, 4, 4, 3), Is.True); + Assert.That(IC.Eq(tree[4, 0].Backwards()), Is.True); + Assert.That(IC.Eq(tree[4, 1].Backwards(), 4), Is.True); + Assert.That(IC.Eq(tree[4, 2].Backwards(), 4, 4), Is.True); + Assert.That(IC.Eq(tree[4, 3].Backwards(), 5, 4, 4), Is.True); + Assert.That(IC.Eq(tree[4, 4].Backwards(), 6, 5, 4, 4), Is.True); + Assert.That(IC.Eq(tree[5, 0].Backwards()), Is.True); + Assert.That(IC.Eq(tree[5, 1].Backwards(), 4), Is.True); + Assert.That(IC.Eq(tree[5, 2].Backwards(), 5, 4), Is.True); + Assert.That(IC.Eq(tree[5, 3].Backwards(), 6, 5, 4), Is.True); + Assert.That(IC.Eq(tree[5, 4].Backwards(), 7, 6, 5, 4), Is.True); + }); } [Test] public void GetRangeBackwardsBug20090616() { - C5.TreeBag tree = new C5.TreeBag() { + C5.TreeBag tree = new() { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 3.0, 3.0, 4.0 }; for (int start = 0; start <= tree.Count - 2; start++) { double[] range = tree[start, 2].Backwards().ToArray(); - Assert.AreEqual(range[1], tree[start]); - Assert.AreEqual(range[0], tree[start + 1]); + Assert.Multiple(() => + { + Assert.That(tree[start], Is.EqualTo(range[1])); + Assert.That(tree[start + 1], Is.EqualTo(range[0])); + }); } } @@ -3103,7 +3459,7 @@ public void GetRangeBad3() [TearDown] - public void Dispose() { tree = null; tree2 = null; } + public void Dispose() { tree.Dispose(); tree2.Dispose(); } } } @@ -3113,7 +3469,7 @@ namespace Hashing [TestFixture] public class ISequenced { - private ISequenced dit, dat, dut; + private TreeBag dit, dat, dut; [SetUp] @@ -3128,7 +3484,7 @@ public void Init() [Test] public void EmptyEmpty() { - Assert.IsTrue(dit.SequencedEquals(dat)); + Assert.That(dit.SequencedEquals(dat), Is.True); } @@ -3136,23 +3492,29 @@ public void EmptyEmpty() public void EmptyNonEmpty() { dit.Add(3); - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsFalse(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dat.SequencedEquals(dit), Is.False); + }); } [Test] public void HashVal() { - Assert.AreEqual(CHC.SequencedHashCode(), dit.GetSequencedHashCode()); + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode())); dit.Add(3); - Assert.AreEqual(CHC.SequencedHashCode(3), dit.GetSequencedHashCode()); + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(3))); dit.Add(7); - Assert.AreEqual(CHC.SequencedHashCode(3, 7), dit.GetSequencedHashCode()); - Assert.AreEqual(CHC.SequencedHashCode(), dut.GetSequencedHashCode()); + Assert.Multiple(() => + { + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(3, 7))); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode())); + }); dut.Add(3); - Assert.AreEqual(CHC.SequencedHashCode(3), dut.GetSequencedHashCode()); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(3))); dut.Add(7); - Assert.AreEqual(CHC.SequencedHashCode(7, 3), dut.GetSequencedHashCode()); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(7, 3))); } @@ -3162,11 +3524,17 @@ public void Normal() dit.Add(3); dit.Add(7); dat.Add(3); - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsFalse(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dat.SequencedEquals(dit), Is.False); + }); dat.Add(7); - Assert.IsTrue(dit.SequencedEquals(dat)); - Assert.IsTrue(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.True); + Assert.That(dat.SequencedEquals(dit), Is.True); + }); } @@ -3175,32 +3543,38 @@ public void WrongOrder() { dit.Add(3); dut.Add(3); - Assert.IsTrue(dit.SequencedEquals(dut)); - Assert.IsTrue(dut.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dut), Is.True); + Assert.That(dut.SequencedEquals(dit), Is.True); + }); dit.Add(7); dut.Add(7); - Assert.IsFalse(dit.SequencedEquals(dut)); - Assert.IsFalse(dut.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dut), Is.False); + Assert.That(dut.SequencedEquals(dit), Is.False); + }); } [Test] public void Reflexive() { - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); dit.Add(3); - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); dit.Add(7); - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); } [TearDown] public void Dispose() { - dit = null; - dat = null; - dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); } } @@ -3209,7 +3583,7 @@ public void Dispose() [TestFixture] public class IEditableCollection { - private ICollection dit, dat, dut; + private TreeBag dit, dat, dut; [SetUp] @@ -3224,7 +3598,7 @@ public void Init() [Test] public void EmptyEmpty() { - Assert.IsTrue(dit.UnsequencedEquals(dat)); + Assert.That(dit.UnsequencedEquals(dat), Is.True); } @@ -3232,24 +3606,30 @@ public void EmptyEmpty() public void EmptyNonEmpty() { dit.Add(3); - Assert.IsFalse(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.False); + Assert.That(dat.UnsequencedEquals(dit), Is.False); + }); } [Test] public void HashVal() { - Assert.AreEqual(CHC.UnsequencedHashCode(), dit.GetUnsequencedHashCode()); + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode())); dit.Add(3); - Assert.AreEqual(CHC.UnsequencedHashCode(3), dit.GetUnsequencedHashCode()); + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3))); dit.Add(7); - Assert.AreEqual(CHC.UnsequencedHashCode(3, 7), dit.GetUnsequencedHashCode()); - Assert.AreEqual(CHC.UnsequencedHashCode(), dut.GetUnsequencedHashCode()); + Assert.Multiple(() => + { + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3, 7))); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode())); + }); dut.Add(3); - Assert.AreEqual(CHC.UnsequencedHashCode(3), dut.GetUnsequencedHashCode()); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3))); dut.Add(7); - Assert.AreEqual(CHC.UnsequencedHashCode(7, 3), dut.GetUnsequencedHashCode()); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(7, 3))); } @@ -3259,11 +3639,17 @@ public void Normal() dit.Add(3); dit.Add(7); dat.Add(3); - Assert.IsFalse(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.False); + Assert.That(dat.UnsequencedEquals(dit), Is.False); + }); dat.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsTrue(dat.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dat.UnsequencedEquals(dit), Is.True); + }); } @@ -3272,32 +3658,38 @@ public void WrongOrder() { dit.Add(3); dut.Add(3); - Assert.IsTrue(dit.UnsequencedEquals(dut)); - Assert.IsTrue(dut.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dut), Is.True); + Assert.That(dut.UnsequencedEquals(dit), Is.True); + }); dit.Add(7); dut.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dut)); - Assert.IsTrue(dut.UnsequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dut), Is.True); + Assert.That(dut.UnsequencedEquals(dit), Is.True); + }); } [Test] public void Reflexive() { - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); dit.Add(3); - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); dit.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dit)); + Assert.That(dit.UnsequencedEquals(dit), Is.True); } [TearDown] public void Dispose() { - dit = null; - dat = null; - dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); } } } diff --git a/C5.Tests/Trees/Dictionary.cs b/C5.Tests/Trees/Dictionary.cs index 7ca6796c..50f39811 100644 --- a/C5.Tests/Trees/Dictionary.cs +++ b/C5.Tests/Trees/Dictionary.cs @@ -28,12 +28,15 @@ public class Formatting [Test] public void Format() { - Assert.AreEqual("[ ]", coll.ToString()); + Assert.That(coll.ToString(), Is.EqualTo("[ ]")); coll.Add(23, 67); coll.Add(45, 89); - Assert.AreEqual("[ [23, 67], [45, 89] ]", coll.ToString()); - Assert.AreEqual("[ [17, 43], [2D, 59] ]", coll.ToString(null, rad16)); - Assert.AreEqual("[ [23, 67], ... ]", coll.ToString("L14", null)); - Assert.AreEqual("[ [17, 43], ... ]", coll.ToString("L14", rad16)); + Assert.Multiple(() => + { + Assert.That(coll.ToString(), Is.EqualTo("[ [23, 67], [45, 89] ]")); + Assert.That(coll.ToString(null, rad16), Is.EqualTo("[ [17, 43], [2D, 59] ]")); + Assert.That(coll.ToString("L14", null), Is.EqualTo("[ [23, 67], ... ]")); + Assert.That(coll.ToString("L14", rad16), Is.EqualTo("[ [17, 43], ... ]")); + }); } } @@ -60,7 +63,7 @@ public void NullEqualityComparerinConstructor1() public void Choose() { dict.Add("YES", "NO"); - Assert.AreEqual(new System.Collections.Generic.KeyValuePair("YES", "NO"), dict.Choose()); + Assert.That(dict.Choose(), Is.EqualTo(new System.Collections.Generic.KeyValuePair("YES", "NO"))); } [Test] @@ -75,14 +78,17 @@ public void Pred1() dict.Add("A", "1"); dict.Add("C", "2"); dict.Add("E", "3"); - Assert.AreEqual("1", dict.Predecessor("B").Value); - Assert.AreEqual("1", dict.Predecessor("C").Value); - Assert.AreEqual("1", dict.WeakPredecessor("B").Value); - Assert.AreEqual("2", dict.WeakPredecessor("C").Value); - Assert.AreEqual("2", dict.Successor("B").Value); - Assert.AreEqual("3", dict.Successor("C").Value); - Assert.AreEqual("2", dict.WeakSuccessor("B").Value); - Assert.AreEqual("2", dict.WeakSuccessor("C").Value); + Assert.Multiple(() => + { + Assert.That(dict.Predecessor("B").Value, Is.EqualTo("1")); + Assert.That(dict.Predecessor("C").Value, Is.EqualTo("1")); + Assert.That(dict.WeakPredecessor("B").Value, Is.EqualTo("1")); + Assert.That(dict.WeakPredecessor("C").Value, Is.EqualTo("2")); + Assert.That(dict.Successor("B").Value, Is.EqualTo("2")); + Assert.That(dict.Successor("C").Value, Is.EqualTo("3")); + Assert.That(dict.WeakSuccessor("B").Value, Is.EqualTo("2")); + Assert.That(dict.WeakSuccessor("C").Value, Is.EqualTo("2")); + }); } [Test] @@ -91,72 +97,93 @@ public void Pred2() dict.Add("A", "1"); dict.Add("C", "2"); dict.Add("E", "3"); - Assert.IsTrue(dict.TryPredecessor("B", out System.Collections.Generic.KeyValuePair res)); - Assert.AreEqual("1", res.Value); - Assert.IsTrue(dict.TryPredecessor("C", out res)); - Assert.AreEqual("1", res.Value); - Assert.IsTrue(dict.TryWeakPredecessor("B", out res)); - Assert.AreEqual("1", res.Value); - Assert.IsTrue(dict.TryWeakPredecessor("C", out res)); - Assert.AreEqual("2", res.Value); - Assert.IsTrue(dict.TrySuccessor("B", out res)); - Assert.AreEqual("2", res.Value); - Assert.IsTrue(dict.TrySuccessor("C", out res)); - Assert.AreEqual("3", res.Value); - Assert.IsTrue(dict.TryWeakSuccessor("B", out res)); - Assert.AreEqual("2", res.Value); - Assert.IsTrue(dict.TryWeakSuccessor("C", out res)); - Assert.AreEqual("2", res.Value); - - Assert.IsFalse(dict.TryPredecessor("A", out res)); - Assert.AreEqual(null, res.Key); - Assert.AreEqual(null, res.Value); - - Assert.IsFalse(dict.TryWeakPredecessor("@", out res)); - Assert.AreEqual(null, res.Key); - Assert.AreEqual(null, res.Value); - - Assert.IsFalse(dict.TrySuccessor("E", out res)); - Assert.AreEqual(null, res.Key); - Assert.AreEqual(null, res.Value); - - Assert.IsFalse(dict.TryWeakSuccessor("F", out res)); - Assert.AreEqual(null, res.Key); - Assert.AreEqual(null, res.Value); + Assert.Multiple(() => + { + Assert.That(dict.TryPredecessor("B", out System.Collections.Generic.KeyValuePair res), Is.True); + Assert.That(res.Value, Is.EqualTo("1")); + Assert.That(dict.TryPredecessor("C", out res), Is.True); + Assert.That(res.Value, Is.EqualTo("1")); + Assert.That(dict.TryWeakPredecessor("B", out res), Is.True); + Assert.That(res.Value, Is.EqualTo("1")); + Assert.That(dict.TryWeakPredecessor("C", out res), Is.True); + Assert.That(res.Value, Is.EqualTo("2")); + Assert.That(dict.TrySuccessor("B", out res), Is.True); + Assert.That(res.Value, Is.EqualTo("2")); + Assert.That(dict.TrySuccessor("C", out res), Is.True); + Assert.That(res.Value, Is.EqualTo("3")); + Assert.That(dict.TryWeakSuccessor("B", out res), Is.True); + Assert.That(res.Value, Is.EqualTo("2")); + Assert.That(dict.TryWeakSuccessor("C", out res), Is.True); + Assert.That(res.Value, Is.EqualTo("2")); + + Assert.That(dict.TryPredecessor("A", out res), Is.False); + Assert.That(res.Key, Is.EqualTo(null)); + Assert.That(res.Value, Is.EqualTo(null)); + + Assert.That(dict.TryWeakPredecessor("@", out res), Is.False); + Assert.That(res.Key, Is.EqualTo(null)); + Assert.That(res.Value, Is.EqualTo(null)); + + Assert.That(dict.TrySuccessor("E", out res), Is.False); + Assert.That(res.Key, Is.EqualTo(null)); + Assert.That(res.Value, Is.EqualTo(null)); + + Assert.That(dict.TryWeakSuccessor("F", out res), Is.False); + Assert.That(res.Key, Is.EqualTo(null)); + Assert.That(res.Value, Is.EqualTo(null)); + }); } [Test] public void Initial() { bool res; - Assert.IsFalse(dict.IsReadOnly); + Assert.Multiple(() => + { + Assert.That(dict.IsReadOnly, Is.False); - Assert.AreEqual(dict.Count, 0, "new dict should be empty"); + Assert.That(dict.Count, Is.EqualTo(0), "new dict should be empty"); + }); dict.Add("A", "B"); - Assert.AreEqual(dict.Count, 1, "bad count"); - Assert.AreEqual(dict["A"], "B", "Wrong value for dict[A]"); + Assert.Multiple(() => + { + Assert.That(dict.Count, Is.EqualTo(1), "bad count"); + Assert.That(dict["A"], Is.EqualTo("B"), "Wrong value for dict[A]"); + }); dict.Add("C", "D"); - Assert.AreEqual(dict.Count, 2, "bad count"); - Assert.AreEqual(dict["A"], "B", "Wrong value"); - Assert.AreEqual(dict["C"], "D", "Wrong value"); + Assert.Multiple(() => + { + Assert.That(dict.Count, Is.EqualTo(2), "bad count"); + Assert.That(dict["A"], Is.EqualTo("B"), "Wrong value"); + Assert.That(dict["C"], Is.EqualTo("D"), "Wrong value"); + }); res = dict.Remove("A"); - Assert.IsTrue(res, "bad return value from Remove(A)"); - Assert.IsTrue(dict.Check()); - Assert.AreEqual(dict.Count, 1, "bad count"); - Assert.AreEqual(dict["C"], "D", "Wrong value of dict[C]"); + Assert.Multiple(() => + { + Assert.That(res, Is.True, "bad return value from Remove(A)"); + Assert.That(dict.Check(), Is.True); + Assert.That(dict.Count, Is.EqualTo(1), "bad count"); + Assert.That(dict["C"], Is.EqualTo("D"), "Wrong value of dict[C]"); + }); res = dict.Remove("Z"); - Assert.IsFalse(res, "bad return value from Remove(Z)"); - Assert.AreEqual(dict.Count, 1, "bad count"); - Assert.AreEqual(dict["C"], "D", "Wrong value of dict[C] (2)"); + Assert.Multiple(() => + { + Assert.That(res, Is.False, "bad return value from Remove(Z)"); + Assert.That(dict.Count, Is.EqualTo(1), "bad count"); + Assert.That(dict["C"], Is.EqualTo("D"), "Wrong value of dict[C] (2)"); + }); dict.Clear(); - Assert.AreEqual(dict.Count, 0, "dict should be empty"); + Assert.That(dict.Count, Is.EqualTo(0), "dict should be empty"); } [Test] public void Contains() { dict.Add("C", "D"); - Assert.IsTrue(dict.Contains("C")); - Assert.IsFalse(dict.Contains("D")); + Assert.Multiple(() => + { + Assert.That(dict.Contains("C"), Is.True); + Assert.That(dict.Contains("D"), Is.False); + }); } @@ -166,7 +193,7 @@ public void IllegalAdd() dict.Add("A", "B"); var exception = Assert.Throws(() => dict.Add("A", "B")); - Assert.AreEqual("Key being added: 'A'", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Key being added: 'A'")); } @@ -181,12 +208,15 @@ public void GettingNonExisting() public void Setter() { dict["R"] = "UYGUY"; - Assert.AreEqual(dict["R"], "UYGUY"); + Assert.That(dict["R"], Is.EqualTo("UYGUY")); dict["R"] = "UIII"; - Assert.AreEqual(dict["R"], "UIII"); + Assert.That(dict["R"], Is.EqualTo("UIII")); dict["S"] = "VVV"; - Assert.AreEqual(dict["R"], "UIII"); - Assert.AreEqual(dict["S"], "VVV"); + Assert.Multiple(() => + { + Assert.That(dict["R"], Is.EqualTo("UIII")); + Assert.That(dict["S"], Is.EqualTo("VVV")); + }); //dict.dump(); } } @@ -214,67 +244,79 @@ public void Init() [Test] public void Pred1() { - Assert.AreEqual("1", dict.Predecessor("B").Value); - Assert.AreEqual("1", dict.Predecessor("C").Value); - Assert.AreEqual("1", dict.WeakPredecessor("B").Value); - Assert.AreEqual("2", dict.WeakPredecessor("C").Value); - Assert.AreEqual("2", dict.Successor("B").Value); - Assert.AreEqual("3", dict.Successor("C").Value); - Assert.AreEqual("2", dict.WeakSuccessor("B").Value); - Assert.AreEqual("2", dict.WeakSuccessor("C").Value); + Assert.Multiple(() => + { + Assert.That(dict.Predecessor("B").Value, Is.EqualTo("1")); + Assert.That(dict.Predecessor("C").Value, Is.EqualTo("1")); + Assert.That(dict.WeakPredecessor("B").Value, Is.EqualTo("1")); + Assert.That(dict.WeakPredecessor("C").Value, Is.EqualTo("2")); + Assert.That(dict.Successor("B").Value, Is.EqualTo("2")); + Assert.That(dict.Successor("C").Value, Is.EqualTo("3")); + Assert.That(dict.WeakSuccessor("B").Value, Is.EqualTo("2")); + Assert.That(dict.WeakSuccessor("C").Value, Is.EqualTo("2")); + }); } [Test] public void Pred2() { - Assert.IsTrue(dict.TryPredecessor("B", out System.Collections.Generic.KeyValuePair res)); - Assert.AreEqual("1", res.Value); - Assert.IsTrue(dict.TryPredecessor("C", out res)); - Assert.AreEqual("1", res.Value); - Assert.IsTrue(dict.TryWeakPredecessor("B", out res)); - Assert.AreEqual("1", res.Value); - Assert.IsTrue(dict.TryWeakPredecessor("C", out res)); - Assert.AreEqual("2", res.Value); - Assert.IsTrue(dict.TrySuccessor("B", out res)); - Assert.AreEqual("2", res.Value); - Assert.IsTrue(dict.TrySuccessor("C", out res)); - Assert.AreEqual("3", res.Value); - Assert.IsTrue(dict.TryWeakSuccessor("B", out res)); - Assert.AreEqual("2", res.Value); - Assert.IsTrue(dict.TryWeakSuccessor("C", out res)); - Assert.AreEqual("2", res.Value); - - Assert.IsFalse(dict.TryPredecessor("A", out res)); - Assert.AreEqual(null, res.Key); - Assert.AreEqual(null, res.Value); - - Assert.IsFalse(dict.TryWeakPredecessor("@", out res)); - Assert.AreEqual(null, res.Key); - Assert.AreEqual(null, res.Value); - - Assert.IsFalse(dict.TrySuccessor("E", out res)); - Assert.AreEqual(null, res.Key); - Assert.AreEqual(null, res.Value); - - Assert.IsFalse(dict.TryWeakSuccessor("F", out res)); - Assert.AreEqual(null, res.Key); - Assert.AreEqual(null, res.Value); + Assert.Multiple(() => + { + Assert.That(dict.TryPredecessor("B", out System.Collections.Generic.KeyValuePair res), Is.True); + Assert.That(res.Value, Is.EqualTo("1")); + Assert.That(dict.TryPredecessor("C", out res), Is.True); + Assert.That(res.Value, Is.EqualTo("1")); + Assert.That(dict.TryWeakPredecessor("B", out res), Is.True); + Assert.That(res.Value, Is.EqualTo("1")); + Assert.That(dict.TryWeakPredecessor("C", out res), Is.True); + Assert.That(res.Value, Is.EqualTo("2")); + Assert.That(dict.TrySuccessor("B", out res), Is.True); + Assert.That(res.Value, Is.EqualTo("2")); + Assert.That(dict.TrySuccessor("C", out res), Is.True); + Assert.That(res.Value, Is.EqualTo("3")); + Assert.That(dict.TryWeakSuccessor("B", out res), Is.True); + Assert.That(res.Value, Is.EqualTo("2")); + Assert.That(dict.TryWeakSuccessor("C", out res), Is.True); + Assert.That(res.Value, Is.EqualTo("2")); + + Assert.That(dict.TryPredecessor("A", out res), Is.False); + Assert.That(res.Key, Is.EqualTo(null)); + Assert.That(res.Value, Is.EqualTo(null)); + + Assert.That(dict.TryWeakPredecessor("@", out res), Is.False); + Assert.That(res.Key, Is.EqualTo(null)); + Assert.That(res.Value, Is.EqualTo(null)); + + Assert.That(dict.TrySuccessor("E", out res), Is.False); + Assert.That(res.Key, Is.EqualTo(null)); + Assert.That(res.Value, Is.EqualTo(null)); + + Assert.That(dict.TryWeakSuccessor("F", out res), Is.False); + Assert.That(res.Key, Is.EqualTo(null)); + Assert.That(res.Value, Is.EqualTo(null)); + }); } [Test] public void Initial() { - Assert.IsTrue(dict.IsReadOnly); + Assert.Multiple(() => + { + Assert.That(dict.IsReadOnly, Is.True); - Assert.AreEqual(3, dict.Count); - Assert.AreEqual("1", dict["A"]); + Assert.That(dict, Has.Count.EqualTo(3)); + }); + Assert.That(dict["A"], Is.EqualTo("1")); } [Test] public void Contains() { - Assert.IsTrue(dict.Contains("A")); - Assert.IsFalse(dict.Contains("1")); + Assert.Multiple(() => + { + Assert.That(dict.Contains("A"), Is.True); + Assert.That(dict.Contains("1"), Is.False); + }); } [Test] @@ -312,7 +354,7 @@ public class Enumerators { private TreeDictionary dict; - private SCG.IEnumerator> dictenum; + private SCG.IEnumerator> dictEnum; [SetUp] @@ -324,14 +366,14 @@ public void Init() ["T"] = "B", ["R"] = "C" }; - dictenum = dict.GetEnumerator(); + dictEnum = dict.GetEnumerator(); } [TearDown] public void Dispose() { - dictenum = null; + dictEnum.Dispose(); dict = null; } @@ -339,94 +381,112 @@ public void Dispose() public void KeysEnumerator() { SCG.IEnumerator keys = dict.Keys.GetEnumerator(); - Assert.AreEqual(3, dict.Keys.Count); - Assert.IsTrue(keys.MoveNext()); - Assert.AreEqual("R", keys.Current); - Assert.IsTrue(keys.MoveNext()); - Assert.AreEqual("S", keys.Current); - Assert.IsTrue(keys.MoveNext()); - Assert.AreEqual("T", keys.Current); - Assert.IsFalse(keys.MoveNext()); + Assert.Multiple(() => + { + Assert.That(dict.Keys, Has.Count.EqualTo(3)); + Assert.That(keys.MoveNext(), Is.True); + Assert.That(keys.Current, Is.EqualTo("R")); + }); + Assert.That(keys.MoveNext(), Is.True); + Assert.That(keys.Current, Is.EqualTo("S")); + Assert.That(keys.MoveNext(), Is.True); + Assert.That(keys.Current, Is.EqualTo("T")); + Assert.That(keys.MoveNext(), Is.False); } [Test] public void KeysISorted() { ISorted keys = dict.Keys; - Assert.IsTrue(keys.IsReadOnly); - Assert.AreEqual("R", keys.FindMin()); - Assert.AreEqual("T", keys.FindMax()); - Assert.IsTrue(keys.Contains("S")); - Assert.AreEqual(3, keys.Count); - // This doesn't hold, maybe because the dict uses a special key comparer? - // Assert.IsTrue(keys.SequencedEquals(new WrappedArray(new string[] { "R", "S", "T" }))); - Assert.IsTrue(keys.UniqueItems().All(delegate (String s) { return s == "R" || s == "S" || s == "T"; })); - Assert.IsTrue(keys.All(delegate (String s) { return s == "R" || s == "S" || s == "T"; })); - Assert.IsFalse(keys.Exists(delegate (String s) { return s != "R" && s != "S" && s != "T"; })); - Assert.IsTrue(keys.Find(delegate (String s) { return s == "R"; }, out string res)); - Assert.AreEqual("R", res); - Assert.IsFalse(keys.Find(delegate (String s) { return s == "Q"; }, out res)); - Assert.AreEqual(null, res); + Assert.Multiple(() => + { + Assert.That(keys.IsReadOnly, Is.True); + Assert.That(keys.FindMin(), Is.EqualTo("R")); + Assert.That(keys.FindMax(), Is.EqualTo("T")); + Assert.That(keys.Contains("S"), Is.True); + Assert.That(keys, Has.Count.EqualTo(3)); + }); + Assert.Multiple(() => + { + // This doesn't hold, maybe because the dict uses a special key comparer? + // Assert.IsTrue(keys.SequencedEquals(new WrappedArray(new string[] { "R", "S", "T" }))); + Assert.That(keys.UniqueItems().All(delegate (string s) { return s == "R" || s == "S" || s == "T"; }), Is.True); + Assert.That(keys.All(delegate (string s) { return s == "R" || s == "S" || s == "T"; }), Is.True); + Assert.That(keys.Exists(delegate (string s) { return s != "R" && s != "S" && s != "T"; }), Is.False); + Assert.That(keys.Find(delegate (string s) { return s == "R"; }, out string res), Is.True); + Assert.That(res, Is.EqualTo("R")); + Assert.That(keys.Find(delegate (string s) { return s == "Q"; }, out res), Is.False); + Assert.That(res, Is.EqualTo(null)); + }); } [Test] public void KeysISortedPred() { ISorted keys = dict.Keys; - Assert.IsTrue(keys.TryPredecessor("S", out string res)); - Assert.AreEqual("R", res); - Assert.IsTrue(keys.TryWeakPredecessor("R", out res)); - Assert.AreEqual("R", res); - Assert.IsTrue(keys.TrySuccessor("S", out res)); - Assert.AreEqual("T", res); - Assert.IsTrue(keys.TryWeakSuccessor("T", out res)); - Assert.AreEqual("T", res); - Assert.IsFalse(keys.TryPredecessor("R", out res)); - Assert.AreEqual(null, res); - Assert.IsFalse(keys.TryWeakPredecessor("P", out res)); - Assert.AreEqual(null, res); - Assert.IsFalse(keys.TrySuccessor("T", out res)); - Assert.AreEqual(null, res); - Assert.IsFalse(keys.TryWeakSuccessor("U", out res)); - Assert.AreEqual(null, res); - - Assert.AreEqual("R", keys.Predecessor("S")); - Assert.AreEqual("R", keys.WeakPredecessor("R")); - Assert.AreEqual("T", keys.Successor("S")); - Assert.AreEqual("T", keys.WeakSuccessor("T")); + Assert.Multiple(() => + { + Assert.That(keys.TryPredecessor("S", out string res), Is.True); + Assert.That(res, Is.EqualTo("R")); + Assert.That(keys.TryWeakPredecessor("R", out res), Is.True); + Assert.That(res, Is.EqualTo("R")); + Assert.That(keys.TrySuccessor("S", out res), Is.True); + Assert.That(res, Is.EqualTo("T")); + Assert.That(keys.TryWeakSuccessor("T", out res), Is.True); + Assert.That(res, Is.EqualTo("T")); + Assert.That(keys.TryPredecessor("R", out res), Is.False); + Assert.That(res, Is.EqualTo(null)); + Assert.That(keys.TryWeakPredecessor("P", out res), Is.False); + Assert.That(res, Is.EqualTo(null)); + Assert.That(keys.TrySuccessor("T", out res), Is.False); + Assert.That(res, Is.EqualTo(null)); + Assert.That(keys.TryWeakSuccessor("U", out res), Is.False); + Assert.That(res, Is.EqualTo(null)); + + Assert.That(keys.Predecessor("S"), Is.EqualTo("R")); + Assert.That(keys.WeakPredecessor("R"), Is.EqualTo("R")); + Assert.That(keys.Successor("S"), Is.EqualTo("T")); + Assert.That(keys.WeakSuccessor("T"), Is.EqualTo("T")); + }); } [Test] public void ValuesEnumerator() { SCG.IEnumerator values = dict.Values.GetEnumerator(); - Assert.AreEqual(3, dict.Values.Count); - Assert.IsTrue(values.MoveNext()); - Assert.AreEqual("C", values.Current); - Assert.IsTrue(values.MoveNext()); - Assert.AreEqual("A", values.Current); - Assert.IsTrue(values.MoveNext()); - Assert.AreEqual("B", values.Current); - Assert.IsFalse(values.MoveNext()); + Assert.Multiple(() => + { + Assert.That(dict.Values, Has.Count.EqualTo(3)); + Assert.That(values.MoveNext(), Is.True); + Assert.That(values.Current, Is.EqualTo("C")); + }); + Assert.That(values.MoveNext(), Is.True); + Assert.That(values.Current, Is.EqualTo("A")); + Assert.That(values.MoveNext(), Is.True); + Assert.That(values.Current, Is.EqualTo("B")); + Assert.That(values.MoveNext(), Is.False); } [Test] public void Fun() { - Assert.AreEqual("B", dict.Func("T")); + Assert.That(dict.Func("T"), Is.EqualTo("B")); } [Test] public void NormalUse() { - Assert.IsTrue(dictenum.MoveNext()); - Assert.AreEqual(dictenum.Current, new System.Collections.Generic.KeyValuePair("R", "C")); - Assert.IsTrue(dictenum.MoveNext()); - Assert.AreEqual(dictenum.Current, new System.Collections.Generic.KeyValuePair("S", "A")); - Assert.IsTrue(dictenum.MoveNext()); - Assert.AreEqual(dictenum.Current, new System.Collections.Generic.KeyValuePair("T", "B")); - Assert.IsFalse(dictenum.MoveNext()); + Assert.Multiple(() => + { + Assert.That(dictEnum.MoveNext(), Is.True); + Assert.That(new System.Collections.Generic.KeyValuePair("R", "C"), Is.EqualTo(dictEnum.Current)); + }); + Assert.That(dictEnum.MoveNext(), Is.True); + Assert.That(new System.Collections.Generic.KeyValuePair("S", "A"), Is.EqualTo(dictEnum.Current)); + Assert.That(dictEnum.MoveNext(), Is.True); + Assert.That(new System.Collections.Generic.KeyValuePair("T", "B"), Is.EqualTo(dictEnum.Current)); + Assert.That(dictEnum.MoveNext(), Is.False); } } @@ -459,19 +519,28 @@ public void Init() public void Test() { dict["SS"] = "D"; - Assert.AreEqual(5, dict.Count); - Assert.AreEqual(4, snap.Count); + Assert.Multiple(() => + { + Assert.That(dict, Has.Count.EqualTo(5)); + Assert.That(snap, Has.Count.EqualTo(4)); + }); dict["T"] = "bb"; - Assert.AreEqual(5, dict.Count); - Assert.AreEqual(4, snap.Count); - Assert.AreEqual("B", snap["T"]); - Assert.AreEqual("bb", dict["T"]); - Assert.IsFalse(dict.IsReadOnly); - Assert.IsTrue(snap.IsReadOnly); + Assert.Multiple(() => + { + Assert.That(dict, Has.Count.EqualTo(5)); + Assert.That(snap, Has.Count.EqualTo(4)); + }); + Assert.Multiple(() => + { + Assert.That(snap["T"], Is.EqualTo("B")); + Assert.That(dict["T"], Is.EqualTo("bb")); + Assert.That(dict.IsReadOnly, Is.False); + Assert.That(snap.IsReadOnly, Is.True); + }); //Finally, update of root node: _ = (TreeDictionary)dict.Snapshot(); dict["S"] = "abe"; - Assert.AreEqual("abe", dict["S"]); + Assert.That(dict["S"], Is.EqualTo("abe")); } diff --git a/C5.Tests/Trees/RedBlackTreeSetTests.cs b/C5.Tests/Trees/RedBlackTreeSetTests.cs index 1632051f..7ea79bc1 100644 --- a/C5.Tests/Trees/RedBlackTreeSetTests.cs +++ b/C5.Tests/Trees/RedBlackTreeSetTests.cs @@ -7,24 +7,15 @@ namespace C5.Tests.trees.TreeSet { - using CollectionOfInt = TreeSet; - [TestFixture] public class GenericTesters { [Test] public void TestEvents() { - CollectionOfInt factory() { return new CollectionOfInt(TenEqualityComparer.Default); } - new C5.Tests.Templates.Events.SortedIndexedTester().Test(factory); + TreeSet factory() { return new TreeSet(TenEqualityComparer.Default); } + new C5.Tests.Templates.Events.SortedIndexedTester>().Test(factory); } - - //[Test] - //public void Extensible() - //{ - // C5.Tests.Templates.Extensible.Clone.Tester(); - // C5.Tests.Templates.Extensible.Serialization.Tester(); - //} } internal static class Factory @@ -45,116 +36,143 @@ public class Formatting [Test] public void Format() { - Assert.AreEqual("{ }", coll.ToString()); - coll.AddAll(new int[] { -4, 28, 129, 65530 }); - Assert.AreEqual("{ -4, 28, 129, 65530 }", coll.ToString()); - Assert.AreEqual("{ -4, 1C, 81, FFFA }", coll.ToString(null, rad16)); - Assert.AreEqual("{ -4, 28, 129... }", coll.ToString("L14", null)); - Assert.AreEqual("{ -4, 1C, 81... }", coll.ToString("L14", rad16)); + Assert.That(coll.ToString(), Is.EqualTo("{ }")); + coll.AddAll([-4, 28, 129, 65530]); + Assert.Multiple(() => + { + Assert.That(coll.ToString(), Is.EqualTo("{ -4, 28, 129, 65530 }")); + Assert.That(coll.ToString(null, rad16), Is.EqualTo("{ -4, 1C, 81, FFFA }")); + Assert.That(coll.ToString("L14", null), Is.EqualTo("{ -4, 28, 129... }")); + Assert.That(coll.ToString("L14", rad16), Is.EqualTo("{ -4, 1C, 81... }")); + }); } } [TestFixture] public class Combined { - private IIndexedSorted> lst; + private TreeSet> lst; [SetUp] public void Init() { - lst = new TreeSet>(new KeyValuePairComparer(new IC())); + lst = new TreeSet>(new KeyValuePairComparer(new IC())); for (int i = 0; i < 10; i++) { - lst.Add(new System.Collections.Generic.KeyValuePair(i, i + 30)); + lst.Add(new SCG.KeyValuePair(i, i + 30)); } } [TearDown] - public void Dispose() { lst = null; } + public void Dispose() { lst.Dispose(); } [Test] public void Find() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Find(ref p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); - p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Find(ref p)); + Assert.Multiple(() => + { + Assert.That(lst.Find(ref p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); + p = new SCG.KeyValuePair(13, 78); + Assert.That(lst.Find(ref p), Is.False); } [Test] public void FindOrAdd() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.FindOrAdd(ref p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); - p = new System.Collections.Generic.KeyValuePair(13, 79); - Assert.IsFalse(lst.FindOrAdd(ref p)); - Assert.AreEqual(13, lst[10].Key); - Assert.AreEqual(79, lst[10].Value); + Assert.Multiple(() => + { + Assert.That(lst.FindOrAdd(ref p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + }); + p = new SCG.KeyValuePair(13, 79); + Assert.Multiple(() => + { + Assert.That(lst.FindOrAdd(ref p), Is.False); + Assert.That(lst[10].Key, Is.EqualTo(13)); + Assert.That(lst[10].Value, Is.EqualTo(79)); + }); } [Test] public void Update() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Update(p)); - Assert.AreEqual(3, lst[3].Key); - Assert.AreEqual(78, lst[3].Value); - p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Update(p)); + Assert.Multiple(() => + { + Assert.That(lst.Update(p), Is.True); + Assert.That(lst[3].Key, Is.EqualTo(3)); + Assert.That(lst[3].Value, Is.EqualTo(78)); + }); + p = new SCG.KeyValuePair(13, 78); + Assert.That(lst.Update(p), Is.False); } [Test] public void UpdateOrAdd1() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.UpdateOrAdd(p)); - Assert.AreEqual(3, lst[3].Key); - Assert.AreEqual(78, lst[3].Value); - p = new System.Collections.Generic.KeyValuePair(13, 79); - Assert.IsFalse(lst.UpdateOrAdd(p)); - Assert.AreEqual(13, lst[10].Key); - Assert.AreEqual(79, lst[10].Value); + Assert.Multiple(() => + { + Assert.That(lst.UpdateOrAdd(p), Is.True); + Assert.That(lst[3].Key, Is.EqualTo(3)); + Assert.That(lst[3].Value, Is.EqualTo(78)); + }); + p = new SCG.KeyValuePair(13, 79); + Assert.Multiple(() => + { + Assert.That(lst.UpdateOrAdd(p), Is.False); + Assert.That(lst[10].Key, Is.EqualTo(13)); + Assert.That(lst[10].Value, Is.EqualTo(79)); + }); } [Test] public void UpdateOrAdd2() { - ICollection coll = new TreeSet(); + ICollection coll = new TreeSet(); // s1 and s2 are distinct objects but contain the same text: - String s1 = "abc", s2 = ("def" + s1).Substring(3); - Assert.IsFalse(coll.UpdateOrAdd(s1, out string old)); - Assert.AreEqual(null, old); - Assert.IsTrue(coll.UpdateOrAdd(s2, out old)); - Assert.IsTrue(Object.ReferenceEquals(s1, old)); - Assert.IsFalse(Object.ReferenceEquals(s2, old)); + string s1 = "abc", s2 = ("def" + s1).Substring(3); + Assert.Multiple(() => + { + Assert.That(coll.UpdateOrAdd(s1, out string old), Is.False); + Assert.That(old, Is.EqualTo(null)); + Assert.That(coll.UpdateOrAdd(s2, out old), Is.True); + Assert.That(ReferenceEquals(s1, old), Is.True); + Assert.That(ReferenceEquals(s2, old), Is.False); + }); } [Test] public void RemoveWithReturn() { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(3, 78); + SCG.KeyValuePair p = new(3, 78); - Assert.IsTrue(lst.Remove(p, out p)); - Assert.AreEqual(3, p.Key); - Assert.AreEqual(33, p.Value); - Assert.AreEqual(4, lst[3].Key); - Assert.AreEqual(34, lst[3].Value); - p = new System.Collections.Generic.KeyValuePair(13, 78); - Assert.IsFalse(lst.Remove(p, out _)); + Assert.Multiple(() => + { + Assert.That(lst.Remove(p, out p), Is.True); + Assert.That(p.Key, Is.EqualTo(3)); + Assert.That(p.Value, Is.EqualTo(33)); + Assert.That(lst[3].Key, Is.EqualTo(4)); + Assert.That(lst[3].Value, Is.EqualTo(34)); + }); + p = new SCG.KeyValuePair(13, 78); + Assert.That(lst.Remove(p, out _), Is.False); } } @@ -187,10 +205,10 @@ public void Enumerator() while (e.MoveNext()) { - Assert.AreEqual(2 * i++, e.Current); + Assert.That(e.Current, Is.EqualTo(2 * i++)); } - Assert.AreEqual(9, i); + Assert.That(i, Is.EqualTo(9)); } @@ -219,122 +237,131 @@ public void Enumerator3() [Test] public void Remove() { - int[] all = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 }; + int[] all = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]; tree.RemoveRangeFrom(18); - Assert.IsTrue(IC.Eq(tree, new int[] { 2, 4, 6, 8, 10, 12, 14, 16 })); + Assert.That(IC.Eq(tree, [2, 4, 6, 8, 10, 12, 14, 16]), Is.True); tree.RemoveRangeFrom(28); - Assert.IsTrue(IC.Eq(tree, new int[] { 2, 4, 6, 8, 10, 12, 14, 16 })); + Assert.That(IC.Eq(tree, [2, 4, 6, 8, 10, 12, 14, 16]), Is.True); tree.RemoveRangeFrom(2); - Assert.IsTrue(IC.Eq(tree)); + Assert.That(IC.Eq(tree), Is.True); foreach (int i in all) { tree.Add(i); } tree.RemoveRangeTo(10); - Assert.IsTrue(IC.Eq(tree, new int[] { 10, 12, 14, 16, 18, 20 })); + Assert.That(IC.Eq(tree, [10, 12, 14, 16, 18, 20]), Is.True); tree.RemoveRangeTo(2); - Assert.IsTrue(IC.Eq(tree, new int[] { 10, 12, 14, 16, 18, 20 })); + Assert.That(IC.Eq(tree, [10, 12, 14, 16, 18, 20]), Is.True); tree.RemoveRangeTo(21); - Assert.IsTrue(IC.Eq(tree)); + Assert.That(IC.Eq(tree), Is.True); foreach (int i in all) { tree.Add(i); } tree.RemoveRangeFromTo(4, 8); - Assert.IsTrue(IC.Eq(tree, 2, 8, 10, 12, 14, 16, 18, 20)); + Assert.That(IC.Eq(tree, 2, 8, 10, 12, 14, 16, 18, 20), Is.True); tree.RemoveRangeFromTo(14, 28); - Assert.IsTrue(IC.Eq(tree, 2, 8, 10, 12)); + Assert.That(IC.Eq(tree, 2, 8, 10, 12), Is.True); tree.RemoveRangeFromTo(0, 9); - Assert.IsTrue(IC.Eq(tree, 10, 12)); + Assert.That(IC.Eq(tree, 10, 12), Is.True); tree.RemoveRangeFromTo(0, 81); - Assert.IsTrue(IC.Eq(tree)); + Assert.That(IC.Eq(tree), Is.True); } [Test] public void Normal() { - int[] all = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 }; - - Assert.IsTrue(IC.Eq(tree, all)); - Assert.IsTrue(IC.Eq(tree.RangeAll(), all)); - Assert.AreEqual(10, tree.RangeAll().Count); - Assert.IsTrue(IC.Eq(tree.RangeFrom(11), new int[] { 12, 14, 16, 18, 20 })); - Assert.AreEqual(5, tree.RangeFrom(11).Count); - Assert.IsTrue(IC.Eq(tree.RangeFrom(12), new int[] { 12, 14, 16, 18, 20 })); - Assert.IsTrue(IC.Eq(tree.RangeFrom(2), all)); - Assert.IsTrue(IC.Eq(tree.RangeFrom(1), all)); - Assert.IsTrue(IC.Eq(tree.RangeFrom(21), new int[] { })); - Assert.IsTrue(IC.Eq(tree.RangeFrom(20), new int[] { 20 })); - Assert.IsTrue(IC.Eq(tree.RangeTo(8), new int[] { 2, 4, 6 })); - Assert.IsTrue(IC.Eq(tree.RangeTo(7), new int[] { 2, 4, 6 })); - Assert.AreEqual(3, tree.RangeTo(7).Count); - Assert.IsTrue(IC.Eq(tree.RangeTo(2), new int[] { })); - Assert.IsTrue(IC.Eq(tree.RangeTo(1), new int[] { })); - Assert.IsTrue(IC.Eq(tree.RangeTo(3), new int[] { 2 })); - Assert.IsTrue(IC.Eq(tree.RangeTo(20), new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18 })); - Assert.IsTrue(IC.Eq(tree.RangeTo(21), all)); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(7, 12), new int[] { 8, 10 })); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(6, 11), new int[] { 6, 8, 10 })); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(1, 12), new int[] { 2, 4, 6, 8, 10 })); - Assert.AreEqual(5, tree.RangeFromTo(1, 12).Count); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(2, 12), new int[] { 2, 4, 6, 8, 10 })); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(6, 21), new int[] { 6, 8, 10, 12, 14, 16, 18, 20 })); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(6, 20), new int[] { 6, 8, 10, 12, 14, 16, 18 })); + int[] all = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]; + + Assert.Multiple(() => + { + Assert.That(IC.Eq(tree, all), Is.True); + Assert.That(IC.Eq(tree.RangeAll(), all), Is.True); + Assert.That(tree.RangeAll(), Has.Count.EqualTo(10)); + Assert.That(IC.Eq(tree.RangeFrom(11), [12, 14, 16, 18, 20]), Is.True); + Assert.That(tree.RangeFrom(11), Has.Count.EqualTo(5)); + Assert.That(IC.Eq(tree.RangeFrom(12), [12, 14, 16, 18, 20]), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(2), all), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(1), all), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(21), []), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(20), [20]), Is.True); + Assert.That(IC.Eq(tree.RangeTo(8), [2, 4, 6]), Is.True); + Assert.That(IC.Eq(tree.RangeTo(7), [2, 4, 6]), Is.True); + Assert.That(tree.RangeTo(7), Has.Count.EqualTo(3)); + Assert.That(IC.Eq(tree.RangeTo(2), []), Is.True); + Assert.That(IC.Eq(tree.RangeTo(1), []), Is.True); + Assert.That(IC.Eq(tree.RangeTo(3), [2]), Is.True); + Assert.That(IC.Eq(tree.RangeTo(20), [2, 4, 6, 8, 10, 12, 14, 16, 18]), Is.True); + Assert.That(IC.Eq(tree.RangeTo(21), all), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(7, 12), [8, 10]), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(6, 11), [6, 8, 10]), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(1, 12), [2, 4, 6, 8, 10]), Is.True); + Assert.That(tree.RangeFromTo(1, 12), Has.Count.EqualTo(5)); + Assert.That(IC.Eq(tree.RangeFromTo(2, 12), [2, 4, 6, 8, 10]), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(6, 21), [6, 8, 10, 12, 14, 16, 18, 20]), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(6, 20), [6, 8, 10, 12, 14, 16, 18]), Is.True); + }); } [Test] public void Backwards() { - int[] all = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 }; - int[] lla = new int[] { 20, 18, 16, 14, 12, 10, 8, 6, 4, 2 }; - - Assert.IsTrue(IC.Eq(tree, all)); - Assert.IsTrue(IC.Eq(tree.RangeAll().Backwards(), lla)); - Assert.IsTrue(IC.Eq(tree.RangeFrom(11).Backwards(), new int[] { 20, 18, 16, 14, 12 })); - Assert.IsTrue(IC.Eq(tree.RangeFrom(12).Backwards(), new int[] { 20, 18, 16, 14, 12 })); - Assert.IsTrue(IC.Eq(tree.RangeFrom(2).Backwards(), lla)); - Assert.IsTrue(IC.Eq(tree.RangeFrom(1).Backwards(), lla)); - Assert.IsTrue(IC.Eq(tree.RangeFrom(21).Backwards(), new int[] { })); - Assert.IsTrue(IC.Eq(tree.RangeFrom(20).Backwards(), new int[] { 20 })); - Assert.IsTrue(IC.Eq(tree.RangeTo(8).Backwards(), new int[] { 6, 4, 2 })); - Assert.IsTrue(IC.Eq(tree.RangeTo(7).Backwards(), new int[] { 6, 4, 2 })); - Assert.IsTrue(IC.Eq(tree.RangeTo(2).Backwards(), new int[] { })); - Assert.IsTrue(IC.Eq(tree.RangeTo(1).Backwards(), new int[] { })); - Assert.IsTrue(IC.Eq(tree.RangeTo(3).Backwards(), new int[] { 2 })); - Assert.IsTrue(IC.Eq(tree.RangeTo(20).Backwards(), new int[] { 18, 16, 14, 12, 10, 8, 6, 4, 2 })); - Assert.IsTrue(IC.Eq(tree.RangeTo(21).Backwards(), lla)); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(7, 12).Backwards(), new int[] { 10, 8 })); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(6, 11).Backwards(), new int[] { 10, 8, 6 })); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(1, 12).Backwards(), new int[] { 10, 8, 6, 4, 2 })); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(2, 12).Backwards(), new int[] { 10, 8, 6, 4, 2 })); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(6, 21).Backwards(), new int[] { 20, 18, 16, 14, 12, 10, 8, 6 })); - Assert.IsTrue(IC.Eq(tree.RangeFromTo(6, 20).Backwards(), new int[] { 18, 16, 14, 12, 10, 8, 6 })); + int[] all = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]; + int[] lla = [20, 18, 16, 14, 12, 10, 8, 6, 4, 2]; + + Assert.Multiple(() => + { + Assert.That(IC.Eq(tree, all), Is.True); + Assert.That(IC.Eq(tree.RangeAll().Backwards(), lla), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(11).Backwards(), [20, 18, 16, 14, 12]), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(12).Backwards(), [20, 18, 16, 14, 12]), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(2).Backwards(), lla), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(1).Backwards(), lla), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(21).Backwards(), []), Is.True); + Assert.That(IC.Eq(tree.RangeFrom(20).Backwards(), [20]), Is.True); + Assert.That(IC.Eq(tree.RangeTo(8).Backwards(), [6, 4, 2]), Is.True); + Assert.That(IC.Eq(tree.RangeTo(7).Backwards(), [6, 4, 2]), Is.True); + Assert.That(IC.Eq(tree.RangeTo(2).Backwards(), []), Is.True); + Assert.That(IC.Eq(tree.RangeTo(1).Backwards(), []), Is.True); + Assert.That(IC.Eq(tree.RangeTo(3).Backwards(), [2]), Is.True); + Assert.That(IC.Eq(tree.RangeTo(20).Backwards(), [18, 16, 14, 12, 10, 8, 6, 4, 2]), Is.True); + Assert.That(IC.Eq(tree.RangeTo(21).Backwards(), lla), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(7, 12).Backwards(), [10, 8]), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(6, 11).Backwards(), [10, 8, 6]), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(1, 12).Backwards(), [10, 8, 6, 4, 2]), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(2, 12).Backwards(), [10, 8, 6, 4, 2]), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(6, 21).Backwards(), [20, 18, 16, 14, 12, 10, 8, 6]), Is.True); + Assert.That(IC.Eq(tree.RangeFromTo(6, 20).Backwards(), [18, 16, 14, 12, 10, 8, 6]), Is.True); + }); } [Test] public void Direction() { - Assert.AreEqual(C5.Direction.Forwards, tree.Direction); - Assert.AreEqual(C5.Direction.Forwards, tree.RangeFrom(20).Direction); - Assert.AreEqual(C5.Direction.Forwards, tree.RangeTo(7).Direction); - Assert.AreEqual(C5.Direction.Forwards, tree.RangeFromTo(1, 12).Direction); - Assert.AreEqual(C5.Direction.Forwards, tree.RangeAll().Direction); - Assert.AreEqual(C5.Direction.Backwards, tree.Backwards().Direction); - Assert.AreEqual(C5.Direction.Backwards, tree.RangeFrom(20).Backwards().Direction); - Assert.AreEqual(C5.Direction.Backwards, tree.RangeTo(7).Backwards().Direction); - Assert.AreEqual(C5.Direction.Backwards, tree.RangeFromTo(1, 12).Backwards().Direction); - Assert.AreEqual(C5.Direction.Backwards, tree.RangeAll().Backwards().Direction); + Assert.Multiple(() => + { + Assert.That(tree.Direction, Is.EqualTo(C5.Direction.Forwards)); + Assert.That(tree.RangeFrom(20).Direction, Is.EqualTo(C5.Direction.Forwards)); + Assert.That(tree.RangeTo(7).Direction, Is.EqualTo(C5.Direction.Forwards)); + Assert.That(tree.RangeFromTo(1, 12).Direction, Is.EqualTo(C5.Direction.Forwards)); + Assert.That(tree.RangeAll().Direction, Is.EqualTo(C5.Direction.Forwards)); + Assert.That(tree.Backwards().Direction, Is.EqualTo(C5.Direction.Backwards)); + Assert.That(tree.RangeFrom(20).Backwards().Direction, Is.EqualTo(C5.Direction.Backwards)); + Assert.That(tree.RangeTo(7).Backwards().Direction, Is.EqualTo(C5.Direction.Backwards)); + Assert.That(tree.RangeFromTo(1, 12).Backwards().Direction, Is.EqualTo(C5.Direction.Backwards)); + Assert.That(tree.RangeAll().Backwards().Direction, Is.EqualTo(C5.Direction.Backwards)); + }); } [TearDown] public void Dispose() { - tree = null; + tree.Dispose(); c = null; } } @@ -360,10 +387,13 @@ public void Init() [Test] public void Both() { - Assert.AreEqual(0, tree.ContainsCount(7)); - Assert.AreEqual(1, tree.ContainsCount(10)); + Assert.Multiple(() => + { + Assert.That(tree.ContainsCount(7), Is.EqualTo(0)); + Assert.That(tree.ContainsCount(10), Is.EqualTo(1)); + }); tree.RemoveAllCopies(10); - Assert.AreEqual(0, tree.ContainsCount(10)); + Assert.That(tree.ContainsCount(10), Is.EqualTo(0)); tree.RemoveAllCopies(7); } @@ -371,7 +401,7 @@ public void Both() [TearDown] public void Dispose() { - tree = null; + tree.Dispose(); } } @@ -426,7 +456,7 @@ public void NullEqualityComparerinConstructor5() public void Choose() { tree.Add(7); - Assert.AreEqual(7, tree.Choose()); + Assert.That(tree.Choose(), Is.EqualTo(7)); } [Test] @@ -439,26 +469,32 @@ public void BadChoose() [Test] public void NoDuplicates() { - Assert.IsFalse(tree.AllowsDuplicates); + Assert.That(tree.AllowsDuplicates, Is.False); loadup(); - Assert.IsFalse(tree.AllowsDuplicates); + Assert.That(tree.AllowsDuplicates, Is.False); } [Test] public void Add() { - Assert.IsTrue(tree.Add(17)); - Assert.IsFalse(tree.Add(17)); - Assert.IsTrue(tree.Add(18)); - Assert.IsFalse(tree.Add(18)); - Assert.AreEqual(2, tree.Count); + Assert.That(tree.Add(17), Is.True); + Assert.Multiple(() => + { + Assert.That(tree.Add(17), Is.False); + Assert.That(tree.Add(18), Is.True); + }); + Assert.Multiple(() => + { + Assert.That(tree.Add(18), Is.False); + Assert.That(tree, Has.Count.EqualTo(2)); + }); } [TearDown] public void Dispose() { - tree = null; + tree.Dispose(); } } @@ -466,20 +502,20 @@ public void Dispose() [TestFixture] public class FindOrAdd { - private TreeSet> bag; + private TreeSet> bag; [SetUp] public void Init() { - bag = new TreeSet>(new KeyValuePairComparer(new IC())); + bag = new TreeSet>(new KeyValuePairComparer(new IC())); } [TearDown] public void Dispose() { - bag = null; + bag.Dispose(); } @@ -488,12 +524,15 @@ public void Test() { var p = new SCG.KeyValuePair(3, "tre"); - Assert.IsFalse(bag.FindOrAdd(ref p)); + Assert.That(bag.FindOrAdd(ref p), Is.False); p = new SCG.KeyValuePair(p.Key, "drei"); - Assert.IsTrue(bag.FindOrAdd(ref p)); + Assert.That(bag.FindOrAdd(ref p), Is.True); p = new SCG.KeyValuePair(p.Key, "three"); - Assert.AreEqual(1, bag.ContainsCount(p)); - Assert.AreEqual("tre", bag[0].Value); + Assert.Multiple(() => + { + Assert.That(bag.ContainsCount(p), Is.EqualTo(1)); + Assert.That(bag[0].Value, Is.EqualTo("tre")); + }); } } @@ -511,48 +550,54 @@ public void Init() } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } [Test] public void Find() { - Assert.IsFalse(list.Find(pred, out int i)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(list.Find(pred, out i)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.IsTrue(list.Find(pred, out i)); - Assert.AreEqual(45, i); + Assert.That(list.Find(pred, out int i), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(list.Find(pred, out i), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.Multiple(() => + { + Assert.That(list.Find(pred, out i), Is.True); + Assert.That(i, Is.EqualTo(45)); + }); } [Test] public void FindLast() { - Assert.IsFalse(list.FindLast(pred, out int i)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(list.FindLast(pred, out i)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.IsTrue(list.FindLast(pred, out i)); - Assert.AreEqual(675, i); + Assert.That(list.FindLast(pred, out int i), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(list.FindLast(pred, out i), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.Multiple(() => + { + Assert.That(list.FindLast(pred, out i), Is.True); + Assert.That(i, Is.EqualTo(675)); + }); } [Test] public void FindIndex() { - Assert.IsFalse(0 <= list.FindIndex(pred)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(0 <= list.FindIndex(pred)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.AreEqual(3, list.FindIndex(pred)); + Assert.That(0 <= list.FindIndex(pred), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(0 <= list.FindIndex(pred), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.That(list.FindIndex(pred), Is.EqualTo(3)); } [Test] public void FindLastIndex() { - Assert.IsFalse(0 <= list.FindLastIndex(pred)); - list.AddAll(new int[] { 4, 22, 67, 37 }); - Assert.IsFalse(0 <= list.FindLastIndex(pred)); - list.AddAll(new int[] { 45, 122, 675, 137 }); - Assert.AreEqual(7, list.FindLastIndex(pred)); + Assert.That(0 <= list.FindLastIndex(pred), Is.False); + list.AddAll([4, 22, 67, 37]); + Assert.That(0 <= list.FindLastIndex(pred), Is.False); + list.AddAll([45, 122, 675, 137]); + Assert.That(list.FindLastIndex(pred), Is.EqualTo(7)); } } @@ -565,16 +610,22 @@ public class UniqueItems public void Init() { list = new TreeSet(); } [TearDown] - public void Dispose() { list = null; } + public void Dispose() { list.Dispose(); } [Test] public void Test() { - Assert.IsTrue(IC.SetEq(list.UniqueItems())); - Assert.IsTrue(IC.SetEq(list.ItemMultiplicities())); - list.AddAll(new int[] { 7, 9, 7 }); - Assert.IsTrue(IC.SetEq(list.UniqueItems(), 7, 9)); - Assert.IsTrue(IC.SetEq(list.ItemMultiplicities(), 7, 1, 9, 1)); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(list.UniqueItems()), Is.True); + Assert.That(IC.SetEq(list.ItemMultiplicities()), Is.True); + }); + list.AddAll([7, 9, 7]); + Assert.Multiple(() => + { + Assert.That(IC.SetEq(list.UniqueItems(), 7, 9), Is.True); + Assert.That(IC.SetEq(list.ItemMultiplicities(), 7, 1, 9, 1), Is.True); + }); } } @@ -598,7 +649,7 @@ public void Init() [TearDown] - public void Dispose() { tree = null; } + public void Dispose() { tree.Dispose(); } private string aeq(int[] a, params int[] b) @@ -622,10 +673,10 @@ private string aeq(int[] a, params int[] b) [Test] public void ToArray() { - Assert.AreEqual("Alles klar", aeq(tree.ToArray())); + Assert.That(aeq(tree.ToArray()), Is.EqualTo("Alles klar")); tree.Add(7); tree.Add(4); - Assert.AreEqual("Alles klar", aeq(tree.ToArray(), 4, 7)); + Assert.That(aeq(tree.ToArray(), 4, 7), Is.EqualTo("Alles klar")); } @@ -633,18 +684,18 @@ public void ToArray() public void CopyTo() { tree.CopyTo(a, 1); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009), Is.EqualTo("Alles klar")); tree.Add(6); tree.CopyTo(a, 2); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009), Is.EqualTo("Alles klar")); tree.Add(4); tree.Add(9); tree.CopyTo(a, 4); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 4, 6, 9, 1007, 1008, 1009)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 4, 6, 9, 1007, 1008, 1009), Is.EqualTo("Alles klar")); tree.Clear(); tree.Add(7); tree.CopyTo(a, 9); - Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 4, 6, 9, 1007, 1008, 7)); + Assert.That(aeq(a, 1000, 1001, 6, 1003, 4, 6, 9, 1007, 1008, 7), Is.EqualTo("Alles klar")); } @@ -692,8 +743,11 @@ public void SmallTrees() tree.Clear(); tree.Add(7); tree.Add(9); - Assert.IsTrue(tree.Remove(7)); - Assert.IsTrue(tree.Check("")); + Assert.Multiple(() => + { + Assert.That(tree.Remove(7), Is.True); + Assert.That(tree.Check(""), Is.True); + }); } @@ -705,30 +759,42 @@ public void ByIndex() int i = tree[10]; tree.RemoveAt(10); - Assert.IsTrue(tree.Check("")); - Assert.IsFalse(tree.Contains(i)); - Assert.AreEqual(n - 1, tree.Count); + Assert.Multiple(() => + { + Assert.That(tree.Check(""), Is.True); + Assert.That(tree.Contains(i), Is.False); + Assert.That(tree, Has.Count.EqualTo(n - 1)); + }); //Low end i = tree.FindMin(); tree.RemoveAt(0); - Assert.IsTrue(tree.Check("")); - Assert.IsFalse(tree.Contains(i)); - Assert.AreEqual(n - 2, tree.Count); + Assert.Multiple(() => + { + Assert.That(tree.Check(""), Is.True); + Assert.That(tree.Contains(i), Is.False); + Assert.That(tree, Has.Count.EqualTo(n - 2)); + }); //high end i = tree.FindMax(); tree.RemoveAt(tree.Count - 1); - Assert.IsTrue(tree.Check("")); - Assert.IsFalse(tree.Contains(i)); - Assert.AreEqual(n - 3, tree.Count); + Assert.Multiple(() => + { + Assert.That(tree.Check(""), Is.True); + Assert.That(tree.Contains(i), Is.False); + Assert.That(tree, Has.Count.EqualTo(n - 3)); + }); //Some leaf i = 18; tree.RemoveAt(7); - Assert.IsTrue(tree.Check("")); - Assert.IsFalse(tree.Contains(i)); - Assert.AreEqual(n - 4, tree.Count); + Assert.Multiple(() => + { + Assert.That(tree.Check(""), Is.True); + Assert.That(tree.Contains(i), Is.False); + Assert.That(tree, Has.Count.EqualTo(n - 4)); + }); } @@ -739,9 +805,12 @@ public void AlmostEmpty() tree.Clear(); tree.Add(3); tree.RemoveAt(0); - Assert.IsTrue(tree.Check("")); - Assert.IsFalse(tree.Contains(3)); - Assert.AreEqual(0, tree.Count); + Assert.Multiple(() => + { + Assert.That(tree.Check(""), Is.True); + Assert.That(tree.Contains(3), Is.False); + Assert.That(tree, Is.Empty); + }); } @@ -750,7 +819,7 @@ public void Empty() { tree.Clear(); var exception = Assert.Throws(() => tree.RemoveAt(0)); - Assert.AreEqual("Index out of range for sequenced collectionvalue", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Index out of range for sequenced collectionvalue")); } @@ -758,7 +827,7 @@ public void Empty() public void HighIndex() { var exception = Assert.Throws(() => tree.RemoveAt(tree.Count)); - Assert.AreEqual("Index out of range for sequenced collectionvalue", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Index out of range for sequenced collectionvalue")); } @@ -766,44 +835,47 @@ public void HighIndex() public void LowIndex() { var exception = Assert.Throws(() => tree.RemoveAt(-1)); - Assert.AreEqual("Index out of range for sequenced collectionvalue", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Index out of range for sequenced collectionvalue")); } [Test] public void Normal() { - Assert.IsFalse(tree.Remove(-20)); + Assert.Multiple(() => + { + Assert.That(tree.Remove(-20), Is.False); - //No demote case, with move_item - Assert.IsTrue(tree.Remove(20)); - Assert.IsTrue(tree.Check("T1")); - Assert.IsFalse(tree.Remove(20)); + //No demote case, with move_item + Assert.That(tree.Remove(20), Is.True); + Assert.That(tree.Check("T1"), Is.True); + }); + Assert.That(tree.Remove(20), Is.False); //plain case 2 - Assert.IsTrue(tree.Remove(14)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); + Assert.That(tree.Remove(14), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); //case 1b - Assert.IsTrue(tree.Remove(25)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); + Assert.That(tree.Remove(25), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); //case 1c - Assert.IsTrue(tree.Remove(29)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); + Assert.That(tree.Remove(29), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); //1a (terminating) - Assert.IsTrue(tree.Remove(10)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); + Assert.That(tree.Remove(10), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); //2+1b - Assert.IsTrue(tree.Remove(12)); - Assert.IsTrue(tree.Remove(11)); + Assert.That(tree.Remove(12), Is.True); + Assert.That(tree.Remove(11), Is.True); //1a+1b - Assert.IsTrue(tree.Remove(18)); - Assert.IsTrue(tree.Remove(13)); - Assert.IsTrue(tree.Remove(15)); + Assert.That(tree.Remove(18), Is.True); + Assert.That(tree.Remove(13), Is.True); + Assert.That(tree.Remove(15), Is.True); //2+1c for (int i = 0; i < 10; i++) @@ -811,41 +883,47 @@ public void Normal() tree.Add(50 - 2 * i); } - Assert.IsTrue(tree.Remove(42)); - Assert.IsTrue(tree.Remove(38)); - Assert.IsTrue(tree.Remove(28)); - Assert.IsTrue(tree.Remove(40)); - - // - Assert.IsTrue(tree.Remove(16)); - Assert.IsTrue(tree.Remove(23)); - Assert.IsTrue(tree.Remove(17)); - Assert.IsTrue(tree.Remove(19)); - Assert.IsTrue(tree.Remove(50)); - Assert.IsTrue(tree.Remove(26)); - Assert.IsTrue(tree.Remove(21)); - Assert.IsTrue(tree.Remove(22)); - Assert.IsTrue(tree.Remove(24)); + Assert.Multiple(() => + { + Assert.That(tree.Remove(42), Is.True); + Assert.That(tree.Remove(38), Is.True); + Assert.That(tree.Remove(28), Is.True); + Assert.That(tree.Remove(40), Is.True); + + // + Assert.That(tree.Remove(16), Is.True); + Assert.That(tree.Remove(23), Is.True); + Assert.That(tree.Remove(17), Is.True); + Assert.That(tree.Remove(19), Is.True); + Assert.That(tree.Remove(50), Is.True); + Assert.That(tree.Remove(26), Is.True); + Assert.That(tree.Remove(21), Is.True); + Assert.That(tree.Remove(22), Is.True); + Assert.That(tree.Remove(24), Is.True); + }); for (int i = 0; i < 48; i++) { tree.Remove(i); } - //Almost empty tree: - Assert.IsFalse(tree.Remove(26)); - Assert.IsTrue(tree.Remove(48)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); + Assert.Multiple(() => + { + //Almost empty tree: + Assert.That(tree.Remove(26), Is.False); + Assert.That(tree.Remove(48), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + }); //Empty tree: - Assert.IsFalse(tree.Remove(26)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); + Assert.That(tree.Remove(26), Is.False); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); } [TearDown] public void Dispose() { - tree = null; + tree.Dispose(); } } @@ -876,93 +954,117 @@ private void loadup() public void FindPredecessor() { loadup(); - Assert.IsTrue(tree.TryPredecessor(7, out int res) && res == 6); - Assert.IsTrue(tree.TryPredecessor(8, out res) && res == 6); + Assert.Multiple(() => + { + Assert.That(tree.TryPredecessor(7, out int res) && res == 6, Is.True); + Assert.That(tree.TryPredecessor(8, out res) && res == 6, Is.True); - //The bottom - Assert.IsTrue(tree.TryPredecessor(1, out res) && res == 0); + //The bottom + Assert.That(tree.TryPredecessor(1, out res) && res == 0, Is.True); - //The top - Assert.IsTrue(tree.TryPredecessor(39, out res) && res == 38); + //The top + Assert.That(tree.TryPredecessor(39, out res) && res == 38, Is.True); + }); } [Test] public void FindPredecessorTooLow1() { - Assert.IsFalse(tree.TryPredecessor(-2, out int res)); - Assert.AreEqual(0, res); - Assert.IsFalse(tree.TryPredecessor(0, out res)); - Assert.AreEqual(0, res); + Assert.Multiple(() => + { + Assert.That(tree.TryPredecessor(-2, out int res), Is.False); + Assert.That(res, Is.EqualTo(0)); + Assert.That(tree.TryPredecessor(0, out res), Is.False); + Assert.That(res, Is.EqualTo(0)); + }); } [Test] public void FindWeakPredecessor() { loadup(); - Assert.IsTrue(tree.TryWeakPredecessor(7, out int res) && res == 6); - Assert.IsTrue(tree.TryWeakPredecessor(8, out res) && res == 8); + Assert.Multiple(() => + { + Assert.That(tree.TryWeakPredecessor(7, out int res) && res == 6, Is.True); + Assert.That(tree.TryWeakPredecessor(8, out res) && res == 8, Is.True); - //The bottom - Assert.IsTrue(tree.TryWeakPredecessor(1, out res) && res == 0); - Assert.IsTrue(tree.TryWeakPredecessor(0, out res) && res == 0); + //The bottom + Assert.That(tree.TryWeakPredecessor(1, out res) && res == 0, Is.True); + Assert.That(tree.TryWeakPredecessor(0, out res) && res == 0, Is.True); - //The top - Assert.IsTrue(tree.TryWeakPredecessor(39, out res) && res == 38); - Assert.IsTrue(tree.TryWeakPredecessor(38, out res) && res == 38); + //The top + Assert.That(tree.TryWeakPredecessor(39, out res) && res == 38, Is.True); + Assert.That(tree.TryWeakPredecessor(38, out res) && res == 38, Is.True); + }); } [Test] public void FindWeakPredecessorTooLow1() { - Assert.IsFalse(tree.TryWeakPredecessor(-1, out int res)); - Assert.AreEqual(0, res); + Assert.Multiple(() => + { + Assert.That(tree.TryWeakPredecessor(-1, out int res), Is.False); + Assert.That(res, Is.EqualTo(0)); + }); } [Test] public void FindSuccessor() { loadup(); - Assert.IsTrue(tree.TrySuccessor(7, out int res) && res == 8); - Assert.IsTrue(tree.TrySuccessor(8, out res) && res == 10); + Assert.Multiple(() => + { + Assert.That(tree.TrySuccessor(7, out int res) && res == 8, Is.True); + Assert.That(tree.TrySuccessor(8, out res) && res == 10, Is.True); - //The bottom - Assert.IsTrue(tree.TrySuccessor(0, out res) && res == 2); - Assert.IsTrue(tree.TrySuccessor(-1, out res) && res == 0); + //The bottom + Assert.That(tree.TrySuccessor(0, out res) && res == 2, Is.True); + Assert.That(tree.TrySuccessor(-1, out res) && res == 0, Is.True); - //The top - Assert.IsTrue(tree.TrySuccessor(37, out res) && res == 38); + //The top + Assert.That(tree.TrySuccessor(37, out res) && res == 38, Is.True); + }); } [Test] public void FindSuccessorTooHigh() { - Assert.IsFalse(tree.TrySuccessor(38, out int res)); - Assert.AreEqual(0, res); - Assert.IsFalse(tree.TrySuccessor(39, out res)); - Assert.AreEqual(0, res); + Assert.Multiple(() => + { + Assert.That(tree.TrySuccessor(38, out int res), Is.False); + Assert.That(res, Is.EqualTo(0)); + Assert.That(tree.TrySuccessor(39, out res), Is.False); + Assert.That(res, Is.EqualTo(0)); + }); } [Test] public void FindWeakSuccessor() { loadup(); - Assert.IsTrue(tree.TryWeakSuccessor(6, out int res) && res == 6); - Assert.IsTrue(tree.TryWeakSuccessor(7, out res) && res == 8); + Assert.Multiple(() => + { + Assert.That(tree.TryWeakSuccessor(6, out int res) && res == 6, Is.True); + Assert.That(tree.TryWeakSuccessor(7, out res) && res == 8, Is.True); - //The bottom - Assert.IsTrue(tree.TryWeakSuccessor(-1, out res) && res == 0); - Assert.IsTrue(tree.TryWeakSuccessor(0, out res) && res == 0); + //The bottom + Assert.That(tree.TryWeakSuccessor(-1, out res) && res == 0, Is.True); + Assert.That(tree.TryWeakSuccessor(0, out res) && res == 0, Is.True); - //The top - Assert.IsTrue(tree.TryWeakSuccessor(37, out res) && res == 38); - Assert.IsTrue(tree.TryWeakSuccessor(38, out res) && res == 38); + //The top + Assert.That(tree.TryWeakSuccessor(37, out res) && res == 38, Is.True); + Assert.That(tree.TryWeakSuccessor(38, out res) && res == 38, Is.True); + }); } [Test] public void FindWeakSuccessorTooHigh1() { - Assert.IsFalse(tree.TryWeakSuccessor(39, out int res)); - Assert.AreEqual(0, res); + Assert.Multiple(() => + { + Assert.That(tree.TryWeakSuccessor(39, out int res), Is.False); + Assert.That(res, Is.EqualTo(0)); + }); } @@ -970,14 +1072,17 @@ public void FindWeakSuccessorTooHigh1() public void Predecessor() { loadup(); - Assert.AreEqual(6, tree.Predecessor(7)); - Assert.AreEqual(6, tree.Predecessor(8)); + Assert.Multiple(() => + { + Assert.That(tree.Predecessor(7), Is.EqualTo(6)); + Assert.That(tree.Predecessor(8), Is.EqualTo(6)); - //The bottom - Assert.AreEqual(0, tree.Predecessor(1)); + //The bottom + Assert.That(tree.Predecessor(1), Is.EqualTo(0)); - //The top - Assert.AreEqual(38, tree.Predecessor(39)); + //The top + Assert.That(tree.Predecessor(39), Is.EqualTo(38)); + }); } @@ -998,16 +1103,19 @@ public void PredecessorTooLow2() public void WeakPredecessor() { loadup(); - Assert.AreEqual(6, tree.WeakPredecessor(7)); - Assert.AreEqual(8, tree.WeakPredecessor(8)); + Assert.Multiple(() => + { + Assert.That(tree.WeakPredecessor(7), Is.EqualTo(6)); + Assert.That(tree.WeakPredecessor(8), Is.EqualTo(8)); - //The bottom - Assert.AreEqual(0, tree.WeakPredecessor(1)); - Assert.AreEqual(0, tree.WeakPredecessor(0)); + //The bottom + Assert.That(tree.WeakPredecessor(1), Is.EqualTo(0)); + Assert.That(tree.WeakPredecessor(0), Is.EqualTo(0)); - //The top - Assert.AreEqual(38, tree.WeakPredecessor(39)); - Assert.AreEqual(38, tree.WeakPredecessor(38)); + //The top + Assert.That(tree.WeakPredecessor(39), Is.EqualTo(38)); + Assert.That(tree.WeakPredecessor(38), Is.EqualTo(38)); + }); } [Test] @@ -1021,15 +1129,18 @@ public void WeakPredecessorTooLow1() public void Successor() { loadup(); - Assert.AreEqual(8, tree.Successor(7)); - Assert.AreEqual(10, tree.Successor(8)); + Assert.Multiple(() => + { + Assert.That(tree.Successor(7), Is.EqualTo(8)); + Assert.That(tree.Successor(8), Is.EqualTo(10)); - //The bottom - Assert.AreEqual(2, tree.Successor(0)); - Assert.AreEqual(0, tree.Successor(-1)); + //The bottom + Assert.That(tree.Successor(0), Is.EqualTo(2)); + Assert.That(tree.Successor(-1), Is.EqualTo(0)); - //The top - Assert.AreEqual(38, tree.Successor(37)); + //The top + Assert.That(tree.Successor(37), Is.EqualTo(38)); + }); } @@ -1049,16 +1160,19 @@ public void SuccessorTooHigh2() public void WeakSuccessor() { loadup(); - Assert.AreEqual(6, tree.WeakSuccessor(6)); - Assert.AreEqual(8, tree.WeakSuccessor(7)); + Assert.Multiple(() => + { + Assert.That(tree.WeakSuccessor(6), Is.EqualTo(6)); + Assert.That(tree.WeakSuccessor(7), Is.EqualTo(8)); - //The bottom - Assert.AreEqual(0, tree.WeakSuccessor(-1)); - Assert.AreEqual(0, tree.WeakSuccessor(0)); + //The bottom + Assert.That(tree.WeakSuccessor(-1), Is.EqualTo(0)); + Assert.That(tree.WeakSuccessor(0), Is.EqualTo(0)); - //The top - Assert.AreEqual(38, tree.WeakSuccessor(37)); - Assert.AreEqual(38, tree.WeakSuccessor(38)); + //The top + Assert.That(tree.WeakSuccessor(37), Is.EqualTo(38)); + Assert.That(tree.WeakSuccessor(38), Is.EqualTo(38)); + }); } @@ -1072,7 +1186,7 @@ public void WeakSuccessorTooHigh1() [TearDown] public void Dispose() { - tree = null; + tree.Dispose(); } } @@ -1100,16 +1214,19 @@ private void loadup() public void Normal() { loadup(); - Assert.AreEqual(1, tree.FindMin()); - Assert.AreEqual(4, tree.FindMax()); - Assert.AreEqual(1, tree.DeleteMin()); - Assert.AreEqual(4, tree.DeleteMax()); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.AreEqual(2, tree.FindMin()); - Assert.AreEqual(3, tree.FindMax()); - Assert.AreEqual(2, tree.DeleteMin()); - Assert.AreEqual(3, tree.DeleteMax()); - Assert.IsTrue(tree.Check("Normal test 2"), "Bad tree"); + Assert.Multiple(() => + { + Assert.That(tree.FindMin(), Is.EqualTo(1)); + Assert.That(tree.FindMax(), Is.EqualTo(4)); + Assert.That(tree.DeleteMin(), Is.EqualTo(1)); + Assert.That(tree.DeleteMax(), Is.EqualTo(4)); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + }); + Assert.That(tree.FindMin(), Is.EqualTo(2)); + Assert.That(tree.FindMax(), Is.EqualTo(3)); + Assert.That(tree.DeleteMin(), Is.EqualTo(2)); + Assert.That(tree.DeleteMax(), Is.EqualTo(3)); + Assert.That(tree.Check("Normal test 2"), Is.True, "Bad tree"); } [Test] @@ -1139,7 +1256,7 @@ public void Empty4() [TearDown] public void Dispose() { - tree = null; + tree.Dispose(); } } @@ -1169,38 +1286,47 @@ public void ToArray() int[] a = tree.ToArray(); - Assert.AreEqual(4, a.Length); - Assert.AreEqual(10, a[0]); - Assert.AreEqual(30, a[1]); - Assert.AreEqual(50, a[2]); - Assert.AreEqual(70, a[3]); + Assert.That(a.Length, Is.EqualTo(4)); + Assert.Multiple(() => + { + Assert.That(a[0], Is.EqualTo(10)); + Assert.That(a[1], Is.EqualTo(30)); + Assert.That(a[2], Is.EqualTo(50)); + Assert.That(a[3], Is.EqualTo(70)); + }); } [Test] public void GoodIndex() { - Assert.AreEqual(-1, tree.IndexOf(20)); - Assert.AreEqual(-1, tree.LastIndexOf(20)); + Assert.Multiple(() => + { + Assert.That(tree.IndexOf(20), Is.EqualTo(-1)); + Assert.That(tree.LastIndexOf(20), Is.EqualTo(-1)); + }); populate(); - Assert.AreEqual(10, tree[0]); - Assert.AreEqual(30, tree[1]); - Assert.AreEqual(50, tree[2]); - Assert.AreEqual(70, tree[3]); - Assert.AreEqual(0, tree.IndexOf(10)); - Assert.AreEqual(1, tree.IndexOf(30)); - Assert.AreEqual(2, tree.IndexOf(50)); - Assert.AreEqual(3, tree.IndexOf(70)); - Assert.AreEqual(~1, tree.IndexOf(20)); - Assert.AreEqual(~0, tree.IndexOf(0)); - Assert.AreEqual(~4, tree.IndexOf(90)); - Assert.AreEqual(0, tree.LastIndexOf(10)); - Assert.AreEqual(1, tree.LastIndexOf(30)); - Assert.AreEqual(2, tree.LastIndexOf(50)); - Assert.AreEqual(3, tree.LastIndexOf(70)); - Assert.AreEqual(~1, tree.LastIndexOf(20)); - Assert.AreEqual(~0, tree.LastIndexOf(0)); - Assert.AreEqual(~4, tree.LastIndexOf(90)); + Assert.Multiple(() => + { + Assert.That(tree[0], Is.EqualTo(10)); + Assert.That(tree[1], Is.EqualTo(30)); + Assert.That(tree[2], Is.EqualTo(50)); + Assert.That(tree[3], Is.EqualTo(70)); + Assert.That(tree.IndexOf(10), Is.EqualTo(0)); + Assert.That(tree.IndexOf(30), Is.EqualTo(1)); + Assert.That(tree.IndexOf(50), Is.EqualTo(2)); + Assert.That(tree.IndexOf(70), Is.EqualTo(3)); + Assert.That(tree.IndexOf(20), Is.EqualTo(~1)); + Assert.That(tree.IndexOf(0), Is.EqualTo(~0)); + Assert.That(tree.IndexOf(90), Is.EqualTo(~4)); + Assert.That(tree.LastIndexOf(10), Is.EqualTo(0)); + Assert.That(tree.LastIndexOf(30), Is.EqualTo(1)); + Assert.That(tree.LastIndexOf(50), Is.EqualTo(2)); + Assert.That(tree.LastIndexOf(70), Is.EqualTo(3)); + Assert.That(tree.LastIndexOf(20), Is.EqualTo(~1)); + Assert.That(tree.LastIndexOf(0), Is.EqualTo(~0)); + Assert.That(tree.LastIndexOf(90), Is.EqualTo(~4)); + }); } @@ -1224,13 +1350,16 @@ public void IndexTooSmall() public void FilledTreeOutsideInput() { populate(); - Assert.AreEqual(0, tree.CountFrom(90)); - Assert.AreEqual(0, tree.CountFromTo(-20, 0)); - Assert.AreEqual(0, tree.CountFromTo(80, 100)); - Assert.AreEqual(0, tree.CountTo(0)); - Assert.AreEqual(4, tree.CountTo(90)); - Assert.AreEqual(4, tree.CountFromTo(-20, 90)); - Assert.AreEqual(4, tree.CountFrom(0)); + Assert.Multiple(() => + { + Assert.That(tree.CountFrom(90), Is.EqualTo(0)); + Assert.That(tree.CountFromTo(-20, 0), Is.EqualTo(0)); + Assert.That(tree.CountFromTo(80, 100), Is.EqualTo(0)); + Assert.That(tree.CountTo(0), Is.EqualTo(0)); + Assert.That(tree.CountTo(90), Is.EqualTo(4)); + Assert.That(tree.CountFromTo(-20, 90), Is.EqualTo(4)); + Assert.That(tree.CountFrom(0), Is.EqualTo(4)); + }); } @@ -1238,9 +1367,12 @@ public void FilledTreeOutsideInput() public void FilledTreeIntermediateInput() { populate(); - Assert.AreEqual(3, tree.CountFrom(20)); - Assert.AreEqual(1, tree.CountFromTo(20, 40)); - Assert.AreEqual(2, tree.CountTo(40)); + Assert.Multiple(() => + { + Assert.That(tree.CountFrom(20), Is.EqualTo(3)); + Assert.That(tree.CountFromTo(20, 40), Is.EqualTo(1)); + Assert.That(tree.CountTo(40), Is.EqualTo(2)); + }); } @@ -1248,26 +1380,32 @@ public void FilledTreeIntermediateInput() public void FilledTreeMatchingInput() { populate(); - Assert.AreEqual(3, tree.CountFrom(30)); - Assert.AreEqual(2, tree.CountFromTo(30, 70)); - Assert.AreEqual(0, tree.CountFromTo(50, 30)); - Assert.AreEqual(0, tree.CountFromTo(50, 50)); - Assert.AreEqual(0, tree.CountTo(10)); - Assert.AreEqual(2, tree.CountTo(50)); + Assert.Multiple(() => + { + Assert.That(tree.CountFrom(30), Is.EqualTo(3)); + Assert.That(tree.CountFromTo(30, 70), Is.EqualTo(2)); + Assert.That(tree.CountFromTo(50, 30), Is.EqualTo(0)); + Assert.That(tree.CountFromTo(50, 50), Is.EqualTo(0)); + Assert.That(tree.CountTo(10), Is.EqualTo(0)); + Assert.That(tree.CountTo(50), Is.EqualTo(2)); + }); } [Test] public void CountEmptyTree() { - Assert.AreEqual(0, tree.CountFrom(20)); - Assert.AreEqual(0, tree.CountFromTo(20, 40)); - Assert.AreEqual(0, tree.CountTo(40)); + Assert.Multiple(() => + { + Assert.That(tree.CountFrom(20), Is.EqualTo(0)); + Assert.That(tree.CountFromTo(20, 40), Is.EqualTo(0)); + Assert.That(tree.CountTo(40), Is.EqualTo(0)); + }); } [TearDown] public void Dispose() { - tree = null; + tree.Dispose(); } } @@ -1299,7 +1437,7 @@ public void CurrentAfterModification() { e.MoveNext(); tree.Add(34); - Assert.AreEqual(0, e.Current); + Assert.That(e.Current, Is.EqualTo(0)); } @@ -1332,8 +1470,8 @@ public void MoveNextAfterClear() [TearDown] public void Dispose() { - tree = null; - e = null; + tree.Dispose(); + e.Dispose(); } } @@ -1361,7 +1499,7 @@ public void CurrentAfterModification() { e.MoveNext(); tree.Add(34); - Assert.AreEqual(3, e.Current); + Assert.That(e.Current, Is.EqualTo(3)); } @@ -1394,8 +1532,8 @@ public void MoveNextAfterClear() [TearDown] public void Dispose() { - tree = null; - e = null; + tree.Dispose(); + e.Dispose(); } } } @@ -1436,7 +1574,7 @@ private bool twomodeleven(int i) [Test] public void InternalEnum() { - Assert.IsTrue(IC.Eq(snap.FindAll(new Func(twomodeleven)), 13, 35)); + Assert.That(IC.Eq(snap.FindAll(new Func(twomodeleven)), 13, 35), Is.True); } @@ -1446,147 +1584,177 @@ public void MoreCut() { } public void Cut() { - Assert.IsFalse(snap.Cut(new HigherOrder.CubeRoot(64), out int lo, out bool lv, out int hi, out bool hv)); - Assert.IsTrue(lv && hv); - Assert.AreEqual(5, hi); - Assert.AreEqual(3, lo); - Assert.IsTrue(snap.Cut(new HigherOrder.CubeRoot(125), out lo, out lv, out hi, out hv)); - Assert.IsTrue(lv && hv); - Assert.AreEqual(7, hi); - Assert.AreEqual(3, lo); - Assert.IsFalse(snap.Cut(new HigherOrder.CubeRoot(125000), out lo, out lv, out _, out hv)); - Assert.IsTrue(lv && !hv); - Assert.AreEqual(41, lo); - Assert.IsFalse(snap.Cut(new HigherOrder.CubeRoot(-27), out _, out lv, out hi, out hv)); - Assert.IsTrue(!lv && hv); - Assert.AreEqual(1, hi); + Assert.Multiple(() => + { + Assert.That(snap.Cut(new HigherOrder.CubeRoot(64), out int lo, out bool lv, out int hi, out bool hv), Is.False); + Assert.That(lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(5)); + Assert.That(lo, Is.EqualTo(3)); + Assert.That(snap.Cut(new HigherOrder.CubeRoot(125), out lo, out lv, out hi, out hv), Is.True); + Assert.That(lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(7)); + Assert.That(lo, Is.EqualTo(3)); + Assert.That(snap.Cut(new HigherOrder.CubeRoot(125000), out lo, out lv, out _, out hv), Is.False); + Assert.That(lv && !hv, Is.True); + Assert.That(lo, Is.EqualTo(41)); + Assert.That(snap.Cut(new HigherOrder.CubeRoot(-27), out _, out lv, out hi, out hv), Is.False); + Assert.That(!lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(1)); + }); } [Test] public void Range() { - Assert.IsTrue(IC.Eq(snap.RangeFromTo(5, 16), 5, 7, 9, 11, 13, 15)); - Assert.IsTrue(IC.Eq(snap.RangeFromTo(5, 17), 5, 7, 9, 11, 13, 15)); - Assert.IsTrue(IC.Eq(snap.RangeFromTo(6, 16), 7, 9, 11, 13, 15)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(snap.RangeFromTo(5, 16), 5, 7, 9, 11, 13, 15), Is.True); + Assert.That(IC.Eq(snap.RangeFromTo(5, 17), 5, 7, 9, 11, 13, 15), Is.True); + Assert.That(IC.Eq(snap.RangeFromTo(6, 16), 7, 9, 11, 13, 15), Is.True); + }); //Assert.AreEqual(snap.RangeFromTo(6, 16).Count, 5); } [Test] public void Contains() { - Assert.IsTrue(snap.Contains(5)); + Assert.That(snap.Contains(5), Is.True); } [Test] public void FindMin() { - Assert.AreEqual(1, snap.FindMin()); + Assert.That(snap.FindMin(), Is.EqualTo(1)); } [Test] public void FindMax() { - Assert.AreEqual(41, snap.FindMax()); + Assert.That(snap.FindMax(), Is.EqualTo(41)); } [Test] public void FindPredecessor() { - Assert.IsTrue(snap.TryPredecessor(15, out int res) && res == 13); - Assert.IsTrue(snap.TryPredecessor(16, out res) && res == 15); - Assert.IsTrue(snap.TryPredecessor(17, out res) && res == 15); - Assert.IsTrue(snap.TryPredecessor(18, out res) && res == 17); + Assert.Multiple(() => + { + Assert.That(snap.TryPredecessor(15, out int res) && res == 13, Is.True); + Assert.That(snap.TryPredecessor(16, out res) && res == 15, Is.True); + Assert.That(snap.TryPredecessor(17, out res) && res == 15, Is.True); + Assert.That(snap.TryPredecessor(18, out res) && res == 17, Is.True); - Assert.IsTrue(snap.TryPredecessor(2, out res) && res == 1); + Assert.That(snap.TryPredecessor(2, out res) && res == 1, Is.True); - Assert.IsFalse(snap.TryPredecessor(1, out res)); - Assert.AreEqual(0, res); + Assert.That(snap.TryPredecessor(1, out res), Is.False); + Assert.That(res, Is.EqualTo(0)); + }); } [Test] public void FindSuccessor() { - Assert.IsTrue(snap.TrySuccessor(15, out int res) && res == 17); - Assert.IsTrue(snap.TrySuccessor(16, out res) && res == 17); - Assert.IsTrue(snap.TrySuccessor(17, out res) && res == 19); - Assert.IsTrue(snap.TrySuccessor(18, out res) && res == 19); + Assert.Multiple(() => + { + Assert.That(snap.TrySuccessor(15, out int res) && res == 17, Is.True); + Assert.That(snap.TrySuccessor(16, out res) && res == 17, Is.True); + Assert.That(snap.TrySuccessor(17, out res) && res == 19, Is.True); + Assert.That(snap.TrySuccessor(18, out res) && res == 19, Is.True); - Assert.IsTrue(snap.TrySuccessor(40, out res) && res == 41); + Assert.That(snap.TrySuccessor(40, out res) && res == 41, Is.True); - Assert.IsFalse(snap.TrySuccessor(41, out res)); - Assert.AreEqual(0, res); + Assert.That(snap.TrySuccessor(41, out res), Is.False); + Assert.That(res, Is.EqualTo(0)); + }); } [Test] public void FindWeakPredecessor() { - Assert.IsTrue(snap.TryWeakPredecessor(15, out int res) && res == 15); - Assert.IsTrue(snap.TryWeakPredecessor(16, out res) && res == 15); - Assert.IsTrue(snap.TryWeakPredecessor(17, out res) && res == 17); - Assert.IsTrue(snap.TryWeakPredecessor(18, out res) && res == 17); + Assert.Multiple(() => + { + Assert.That(snap.TryWeakPredecessor(15, out int res) && res == 15, Is.True); + Assert.That(snap.TryWeakPredecessor(16, out res) && res == 15, Is.True); + Assert.That(snap.TryWeakPredecessor(17, out res) && res == 17, Is.True); + Assert.That(snap.TryWeakPredecessor(18, out res) && res == 17, Is.True); - Assert.IsTrue(snap.TryWeakPredecessor(1, out res) && res == 1); + Assert.That(snap.TryWeakPredecessor(1, out res) && res == 1, Is.True); - Assert.IsFalse(snap.TryWeakPredecessor(0, out res)); - Assert.AreEqual(0, res); + Assert.That(snap.TryWeakPredecessor(0, out res), Is.False); + Assert.That(res, Is.EqualTo(0)); + }); } [Test] public void FindWeakSuccessor() { - Assert.IsTrue(snap.TryWeakSuccessor(15, out int res) && res == 15); - Assert.IsTrue(snap.TryWeakSuccessor(16, out res) && res == 17); - Assert.IsTrue(snap.TryWeakSuccessor(17, out res) && res == 17); - Assert.IsTrue(snap.TryWeakSuccessor(18, out res) && res == 19); + Assert.Multiple(() => + { + Assert.That(snap.TryWeakSuccessor(15, out int res) && res == 15, Is.True); + Assert.That(snap.TryWeakSuccessor(16, out res) && res == 17, Is.True); + Assert.That(snap.TryWeakSuccessor(17, out res) && res == 17, Is.True); + Assert.That(snap.TryWeakSuccessor(18, out res) && res == 19, Is.True); - Assert.IsTrue(snap.TryWeakSuccessor(41, out res) && res == 41); + Assert.That(snap.TryWeakSuccessor(41, out res) && res == 41, Is.True); - Assert.IsFalse(snap.TryWeakSuccessor(42, out res)); - Assert.AreEqual(0, res); + Assert.That(snap.TryWeakSuccessor(42, out res), Is.False); + Assert.That(res, Is.EqualTo(0)); + }); } [Test] public void Predecessor() { - Assert.AreEqual(13, snap.Predecessor(15)); - Assert.AreEqual(15, snap.Predecessor(16)); - Assert.AreEqual(15, snap.Predecessor(17)); - Assert.AreEqual(17, snap.Predecessor(18)); + Assert.Multiple(() => + { + Assert.That(snap.Predecessor(15), Is.EqualTo(13)); + Assert.That(snap.Predecessor(16), Is.EqualTo(15)); + Assert.That(snap.Predecessor(17), Is.EqualTo(15)); + Assert.That(snap.Predecessor(18), Is.EqualTo(17)); + }); } [Test] public void Successor() { - Assert.AreEqual(17, snap.Successor(15)); - Assert.AreEqual(17, snap.Successor(16)); - Assert.AreEqual(19, snap.Successor(17)); - Assert.AreEqual(19, snap.Successor(18)); + Assert.Multiple(() => + { + Assert.That(snap.Successor(15), Is.EqualTo(17)); + Assert.That(snap.Successor(16), Is.EqualTo(17)); + Assert.That(snap.Successor(17), Is.EqualTo(19)); + Assert.That(snap.Successor(18), Is.EqualTo(19)); + }); } [Test] public void WeakPredecessor() { - Assert.AreEqual(15, snap.WeakPredecessor(15)); - Assert.AreEqual(15, snap.WeakPredecessor(16)); - Assert.AreEqual(17, snap.WeakPredecessor(17)); - Assert.AreEqual(17, snap.WeakPredecessor(18)); + Assert.Multiple(() => + { + Assert.That(snap.WeakPredecessor(15), Is.EqualTo(15)); + Assert.That(snap.WeakPredecessor(16), Is.EqualTo(15)); + Assert.That(snap.WeakPredecessor(17), Is.EqualTo(17)); + Assert.That(snap.WeakPredecessor(18), Is.EqualTo(17)); + }); } [Test] public void WeakSuccessor() { - Assert.AreEqual(15, snap.WeakSuccessor(15)); - Assert.AreEqual(17, snap.WeakSuccessor(16)); - Assert.AreEqual(17, snap.WeakSuccessor(17)); - Assert.AreEqual(19, snap.WeakSuccessor(18)); + Assert.Multiple(() => + { + Assert.That(snap.WeakSuccessor(15), Is.EqualTo(15)); + Assert.That(snap.WeakSuccessor(16), Is.EqualTo(17)); + Assert.That(snap.WeakSuccessor(17), Is.EqualTo(17)); + Assert.That(snap.WeakSuccessor(18), Is.EqualTo(19)); + }); } @@ -1597,7 +1765,7 @@ public void CountTo() { int j = snap.CountTo(15); }); - Assert.AreEqual("Indexing not supported for snapshots", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Indexing not supported for snapshots")); } [Test] @@ -1607,7 +1775,7 @@ public void Indexing() { int j = snap[4]; }); - Assert.AreEqual("Indexing not supported for snapshots", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Indexing not supported for snapshots")); } [Test] @@ -1617,13 +1785,13 @@ public void Indexing2() { int j = snap.IndexOf(5); }); - Assert.AreEqual("Indexing not supported for snapshots", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Indexing not supported for snapshots")); } [TearDown] public void Dispose() { - tree = null; + tree.Dispose(); ic = null; } } @@ -1651,17 +1819,20 @@ public void Init() [Test] public void EnumerationWithAdd() { - int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 }; + int[] orig = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]; int i = 0; TreeSet snap = (TreeSet)tree.Snapshot(); foreach (int j in snap) { - Assert.AreEqual(1 + 2 * i++, j); + Assert.That(j, Is.EqualTo(1 + 2 * i++)); tree.Add(21 - j); - Assert.IsTrue(snap.Check("M"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - Assert.IsTrue(tree.Check("Tree"), "Bad tree!"); + Assert.Multiple(() => + { + Assert.That(snap.Check("M"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + Assert.That(tree.Check("Tree"), Is.True, "Bad tree!"); + }); } } @@ -1669,15 +1840,21 @@ public void EnumerationWithAdd() [Test] public void Remove() { - int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 }; + int[] orig = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]; TreeSet snap = (TreeSet)tree.Snapshot(); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.Multiple(() => + { + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + }); tree.Remove(19); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(tree.Check("Tree"), "Bad tree!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.Multiple(() => + { + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(tree.Check("Tree"), Is.True, "Bad tree!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + }); } @@ -1691,60 +1868,69 @@ public void RemoveNormal() tree.Add(i + 10); } - int[] orig = new int[] { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 }; + int[] orig = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]; TreeSet snap = (TreeSet)tree.Snapshot(); - Assert.IsFalse(tree.Remove(-20)); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.Multiple(() => + { + Assert.That(tree.Remove(-20), Is.False); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); - //No demote case, with move_item - Assert.IsTrue(tree.Remove(20)); - Assert.IsTrue(tree.Check("T1")); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - Assert.IsFalse(tree.Remove(20)); + //No demote case, with move_item + Assert.That(tree.Remove(20), Is.True); + Assert.That(tree.Check("T1"), Is.True); + }); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + Assert.That(tree.Remove(20), Is.False); //plain case 2 tree.Snapshot(); - Assert.IsTrue(tree.Remove(14)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.Multiple(() => + { + Assert.That(tree.Remove(14), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); - //case 1b - Assert.IsTrue(tree.Remove(25)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + //case 1b + Assert.That(tree.Remove(25), Is.True); + }); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); //case 1c - Assert.IsTrue(tree.Remove(29)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.That(tree.Remove(29), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); //1a (terminating) - Assert.IsTrue(tree.Remove(10)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.That(tree.Remove(10), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); //2+1b - Assert.IsTrue(tree.Remove(12)); + Assert.That(tree.Remove(12), Is.True); tree.Snapshot(); - Assert.IsTrue(tree.Remove(11)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - - //1a+1b - Assert.IsTrue(tree.Remove(18)); - Assert.IsTrue(tree.Remove(13)); - Assert.IsTrue(tree.Remove(15)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.Multiple(() => + { + Assert.That(tree.Remove(11), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + + //1a+1b + Assert.That(tree.Remove(18), Is.True); + Assert.That(tree.Remove(13), Is.True); + Assert.That(tree.Remove(15), Is.True); + }); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); //2+1c for (int i = 0; i < 10; i++) @@ -1752,95 +1938,122 @@ public void RemoveNormal() tree.Add(50 - 2 * i); } - Assert.IsTrue(tree.Remove(42)); - Assert.IsTrue(tree.Remove(38)); - Assert.IsTrue(tree.Remove(28)); - Assert.IsTrue(tree.Remove(40)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - - // - Assert.IsTrue(tree.Remove(16)); - Assert.IsTrue(tree.Remove(23)); - Assert.IsTrue(tree.Remove(17)); - Assert.IsTrue(tree.Remove(19)); - Assert.IsTrue(tree.Remove(50)); - Assert.IsTrue(tree.Remove(26)); - Assert.IsTrue(tree.Remove(21)); - Assert.IsTrue(tree.Remove(22)); - Assert.IsTrue(tree.Remove(24)); + Assert.Multiple(() => + { + Assert.That(tree.Remove(42), Is.True); + Assert.That(tree.Remove(38), Is.True); + Assert.That(tree.Remove(28), Is.True); + Assert.That(tree.Remove(40), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + + // + Assert.That(tree.Remove(16), Is.True); + Assert.That(tree.Remove(23), Is.True); + Assert.That(tree.Remove(17), Is.True); + Assert.That(tree.Remove(19), Is.True); + Assert.That(tree.Remove(50), Is.True); + Assert.That(tree.Remove(26), Is.True); + Assert.That(tree.Remove(21), Is.True); + Assert.That(tree.Remove(22), Is.True); + Assert.That(tree.Remove(24), Is.True); + }); for (int i = 0; i < 48; i++) { tree.Remove(i); } - //Almost empty tree: - Assert.IsFalse(tree.Remove(26)); - Assert.IsTrue(tree.Remove(48)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.Multiple(() => + { + //Almost empty tree: + Assert.That(tree.Remove(26), Is.False); + Assert.That(tree.Remove(48), Is.True); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + }); //Empty tree: - Assert.IsFalse(tree.Remove(26)); - Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree"); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.That(tree.Remove(26), Is.False); + Assert.That(tree.Check("Normal test 1"), Is.True, "Bad tree"); + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); } [Test] public void Add() { - int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 }; + int[] orig = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]; TreeSet snap = (TreeSet)tree.Snapshot(); - Assert.IsTrue(snap.Check("M"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - Assert.IsTrue(tree.Check("Tree"), "Bad tree!"); + Assert.Multiple(() => + { + Assert.That(snap.Check("M"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + Assert.That(tree.Check("Tree"), Is.True, "Bad tree!"); + }); tree.Add(10); - Assert.IsTrue(snap.Check("M"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - Assert.IsTrue(tree.Check("Tree"), "Bad tree!"); + Assert.Multiple(() => + { + Assert.That(snap.Check("M"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + Assert.That(tree.Check("Tree"), Is.True, "Bad tree!"); + }); tree.Add(16); - Assert.IsTrue(snap.Check("M"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - Assert.IsTrue(tree.Check("Tree"), "Bad tree!"); + Assert.Multiple(() => + { + Assert.That(snap.Check("M"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + Assert.That(tree.Check("Tree"), Is.True, "Bad tree!"); + }); //Promote+zigzig tree.Add(40); - Assert.IsTrue(snap.Check("M"), "Bad snap!"); - Assert.IsTrue(tree.Check("Tree"), "Bad tree!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); + Assert.Multiple(() => + { + Assert.That(snap.Check("M"), Is.True, "Bad snap!"); + Assert.That(tree.Check("Tree"), Is.True, "Bad tree!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + }); for (int i = 1; i < 4; i++) { tree.Add(40 - 2 * i); } - Assert.IsTrue(snap.Check("M"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - Assert.IsTrue(tree.Check("Tree"), "Bad tree!"); + Assert.Multiple(() => + { + Assert.That(snap.Check("M"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + Assert.That(tree.Check("Tree"), Is.True, "Bad tree!"); + }); //Zigzag: tree.Add(32); - Assert.IsTrue(snap.Check("M"), "Bad snap!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - Assert.IsTrue(tree.Check("Tree"), "Bad tree!"); + Assert.Multiple(() => + { + Assert.That(snap.Check("M"), Is.True, "Bad snap!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + Assert.That(tree.Check("Tree"), Is.True, "Bad tree!"); + }); } [Test] public void Clear() { - int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 }; + int[] orig = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]; TreeSet snap = (TreeSet)tree.Snapshot(); tree.Clear(); - Assert.IsTrue(snap.Check("Snap"), "Bad snap!"); - Assert.IsTrue(tree.Check("Tree"), "Bad tree!"); - Assert.IsTrue(IC.Eq(snap, orig), "Snap was changed!"); - Assert.AreEqual(0, tree.Count); + Assert.Multiple(() => + { + Assert.That(snap.Check("Snap"), Is.True, "Bad snap!"); + Assert.That(tree.Check("Tree"), Is.True, "Bad tree!"); + Assert.That(IC.Eq(snap, orig), Is.True, "Snap was changed!"); + Assert.That(tree, Is.Empty); + }); } @@ -1850,13 +2063,13 @@ public void SnapSnap() TreeSet snap = (TreeSet)tree.Snapshot(); var exception = Assert.Throws(() => snap.Snapshot()); - Assert.AreEqual("Cannot snapshot a snapshot", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Cannot snapshot a snapshot")); } [TearDown] public void Dispose() { - tree = null; + tree.Dispose(); ic = null; } } @@ -1864,7 +2077,9 @@ public void Dispose() [TestFixture] public class Multiple { +#pragma warning disable NUnit1032 // TODO: Breaks tests private TreeSet tree; +#pragma warning restore NUnit1032 // An IDisposable field/property should be Disposed in a TearDown method private SCG.IComparer ic; @@ -1903,7 +2118,7 @@ public void First() for (int i = 0; i < 10; i++) { - Assert.AreEqual(i + 10, snaps[i].Count); + Assert.That(snaps[i], Has.Count.EqualTo(i + 10)); } snaps[5] = null; @@ -1912,16 +2127,19 @@ public void First() snaps[8].Dispose(); tree.Remove(14); - int[] res = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19 }; - int[] snap7 = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19 }; - int[] snap3 = new int[] { 0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 15, 17, 19 }; + int[] res = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19]; + int[] snap7 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19]; + int[] snap3 = [0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 15, 17, 19]; - Assert.IsTrue(IC.Eq(snaps[3], snap3), "Snap 3 was changed!"); - Assert.IsTrue(IC.Eq(snaps[7], snap7), "Snap 7 was changed!"); - Assert.IsTrue(IC.Eq(tree, res)); - Assert.IsTrue(tree.Check("B")); - Assert.IsTrue(snaps[3].Check("B")); - Assert.IsTrue(snaps[7].Check("B")); + Assert.Multiple(() => + { + Assert.That(IC.Eq(snaps[3], snap3), Is.True, "Snap 3 was changed!"); + Assert.That(IC.Eq(snaps[7], snap7), Is.True, "Snap 7 was changed!"); + Assert.That(IC.Eq(tree, res), Is.True); + Assert.That(tree.Check("B"), Is.True); + Assert.That(snaps[3].Check("B"), Is.True); + Assert.That(snaps[7].Check("B"), Is.True); + }); } @@ -1940,7 +2158,7 @@ public void CollectingTheMaster() GC.Collect(); for (int i = 0; i < 10; i++) { - Assert.AreEqual(i + 10, snaps[i].Count); + Assert.That(snaps[i], Has.Count.EqualTo(i + 10)); } snaps[5] = null; @@ -1948,28 +2166,28 @@ public void CollectingTheMaster() GC.Collect(); snaps[8].Dispose(); - int[] snap7 = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19 }; - int[] snap3 = new int[] { 0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 15, 17, 19 }; + int[] snap7 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19]; + int[] snap3 = [0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 15, 17, 19]; - Assert.IsTrue(IC.Eq(snaps[3], snap3), "Snap 3 was changed!"); - Assert.IsTrue(IC.Eq(snaps[7], snap7), "Snap 7 was changed!"); - Assert.IsTrue(snaps[3].Check("B")); - Assert.IsTrue(snaps[7].Check("B")); + Assert.Multiple(() => + { + Assert.That(IC.Eq(snaps[3], snap3), Is.True, "Snap 3 was changed!"); + Assert.That(IC.Eq(snaps[7], snap7), Is.True, "Snap 7 was changed!"); + Assert.That(snaps[3].Check("B"), Is.True); + Assert.That(snaps[7].Check("B"), Is.True); + }); } [TearDown] public void Dispose() { - tree = null; + //tree.Dispose(); ic = null; } } } - - - namespace HigherOrder { internal class CubeRoot : IComparable @@ -2040,13 +2258,16 @@ public void Init() [Test] public void Apply() { - Simple simple1 = new Simple(); + Simple simple1 = new(); tree.Apply(new Action(simple1.apply)); - Assert.AreEqual(0, simple1.appfield1); - Assert.AreEqual(0, simple1.appfield2); + Assert.Multiple(() => + { + Assert.That(simple1.appfield1, Is.EqualTo(0)); + Assert.That(simple1.appfield2, Is.EqualTo(0)); + }); - Simple simple2 = new Simple(); + Simple simple2 = new(); for (int i = 0; i < 10; i++) { @@ -2054,101 +2275,131 @@ public void Apply() } tree.Apply(new Action(simple2.apply)); - Assert.AreEqual(10, simple2.appfield1); - Assert.AreEqual(285, simple2.appfield2); + Assert.Multiple(() => + { + Assert.That(simple2.appfield1, Is.EqualTo(10)); + Assert.That(simple2.appfield2, Is.EqualTo(285)); + }); } [Test] public void All() { - Assert.IsTrue(tree.All(new Func(never))); - Assert.IsTrue(tree.All(new Func(even))); - Assert.IsTrue(tree.All(new Func(always))); + Assert.Multiple(() => + { + Assert.That(tree.All(new Func(never)), Is.True); + Assert.That(tree.All(new Func(even)), Is.True); + Assert.That(tree.All(new Func(always)), Is.True); + }); for (int i = 0; i < 10; i++) { tree.Add(i); } - Assert.IsFalse(tree.All(new Func(never))); - Assert.IsFalse(tree.All(new Func(even))); - Assert.IsTrue(tree.All(new Func(always))); + Assert.Multiple(() => + { + Assert.That(tree.All(new Func(never)), Is.False); + Assert.That(tree.All(new Func(even)), Is.False); + Assert.That(tree.All(new Func(always)), Is.True); + }); tree.Clear(); for (int i = 0; i < 10; i++) { tree.Add(i * 2); } - Assert.IsFalse(tree.All(new Func(never))); - Assert.IsTrue(tree.All(new Func(even))); - Assert.IsTrue(tree.All(new Func(always))); + Assert.Multiple(() => + { + Assert.That(tree.All(new Func(never)), Is.False); + Assert.That(tree.All(new Func(even)), Is.True); + Assert.That(tree.All(new Func(always)), Is.True); + }); tree.Clear(); for (int i = 0; i < 10; i++) { tree.Add(i * 2 + 1); } - Assert.IsFalse(tree.All(new Func(never))); - Assert.IsFalse(tree.All(new Func(even))); - Assert.IsTrue(tree.All(new Func(always))); + Assert.Multiple(() => + { + Assert.That(tree.All(new Func(never)), Is.False); + Assert.That(tree.All(new Func(even)), Is.False); + Assert.That(tree.All(new Func(always)), Is.True); + }); } [Test] public void Exists() { - Assert.IsFalse(tree.Exists(new Func(never))); - Assert.IsFalse(tree.Exists(new Func(even))); - Assert.IsFalse(tree.Exists(new Func(always))); + Assert.Multiple(() => + { + Assert.That(tree.Exists(new Func(never)), Is.False); + Assert.That(tree.Exists(new Func(even)), Is.False); + Assert.That(tree.Exists(new Func(always)), Is.False); + }); for (int i = 0; i < 10; i++) { tree.Add(i); } - Assert.IsFalse(tree.Exists(new Func(never))); - Assert.IsTrue(tree.Exists(new Func(even))); - Assert.IsTrue(tree.Exists(new Func(always))); + Assert.Multiple(() => + { + Assert.That(tree.Exists(new Func(never)), Is.False); + Assert.That(tree.Exists(new Func(even)), Is.True); + Assert.That(tree.Exists(new Func(always)), Is.True); + }); tree.Clear(); for (int i = 0; i < 10; i++) { tree.Add(i * 2); } - Assert.IsFalse(tree.Exists(new Func(never))); - Assert.IsTrue(tree.Exists(new Func(even))); - Assert.IsTrue(tree.Exists(new Func(always))); + Assert.Multiple(() => + { + Assert.That(tree.Exists(new Func(never)), Is.False); + Assert.That(tree.Exists(new Func(even)), Is.True); + Assert.That(tree.Exists(new Func(always)), Is.True); + }); tree.Clear(); for (int i = 0; i < 10; i++) { tree.Add(i * 2 + 1); } - Assert.IsFalse(tree.Exists(new Func(never))); - Assert.IsFalse(tree.Exists(new Func(even))); - Assert.IsTrue(tree.Exists(new Func(always))); + Assert.Multiple(() => + { + Assert.That(tree.Exists(new Func(never)), Is.False); + Assert.That(tree.Exists(new Func(even)), Is.False); + Assert.That(tree.Exists(new Func(always)), Is.True); + }); } [Test] public void FindAll() { - Assert.AreEqual(0, tree.FindAll(new Func(never)).Count); + Assert.That(tree.FindAll(new Func(never)), Is.Empty); for (int i = 0; i < 10; i++) { tree.Add(i); } - Assert.AreEqual(0, tree.FindAll(new Func(never)).Count); - Assert.AreEqual(10, tree.FindAll(new Func(always)).Count); - Assert.AreEqual(5, tree.FindAll(new Func(even)).Count); - Assert.IsTrue(((TreeSet)tree.FindAll(new Func(even))).Check("R")); + Assert.Multiple(() => + { + Assert.That(tree.FindAll(new Func(never)), Is.Empty); + Assert.That(tree.FindAll(new Func(always)), Has.Count.EqualTo(10)); + Assert.That(tree.FindAll(new Func(even)), Has.Count.EqualTo(5)); + Assert.That(((TreeSet)tree.FindAll(new Func(even))).Check("R"), Is.True); + }); } [Test] public void Map() { - Assert.AreEqual(0, tree.Map(new Func(themap), new SC()).Count); + Assert.That(tree.Map(new Func(themap), new SC()), Is.Empty); for (int i = 0; i < 11; i++) { tree.Add(i * i * i); @@ -2156,12 +2407,18 @@ public void Map() IIndexedSorted res = tree.Map(new Func(themap), new SC()); - Assert.IsTrue(((TreeSet)res).Check("R")); - Assert.AreEqual(11, res.Count); - Assert.AreEqual("AA 0 BB", res[0]); - Assert.AreEqual("AA 27 BB", res[3]); - Assert.AreEqual("AA 125 BB", res[5]); - Assert.AreEqual("AA 1000 BB", res[10]); + Assert.Multiple(() => + { + Assert.That(((TreeSet)res).Check("R"), Is.True); + Assert.That(res, Has.Count.EqualTo(11)); + }); + Assert.Multiple(() => + { + Assert.That(res[0], Is.EqualTo("AA 0 BB")); + Assert.That(res[3], Is.EqualTo("AA 27 BB")); + Assert.That(res[5], Is.EqualTo("AA 125 BB")); + Assert.That(res[10], Is.EqualTo("AA 1000 BB")); + }); } @@ -2177,7 +2434,7 @@ public void BadMap() { ISorted res = tree.Map(new Func(badmap), new SC()); }); - Assert.AreEqual("mapper not monotonic", exception.Message); + Assert.That(exception.Message, Is.EqualTo("mapper not monotonic")); } @@ -2189,17 +2446,19 @@ public void Cut() tree.Add(i); } - Assert.IsTrue(tree.Cut(new CubeRoot(27), out int low, out bool lval, out int high, out bool hval)); - Assert.IsTrue(lval && hval); - Assert.AreEqual(4, high); - Assert.AreEqual(2, low); - Assert.IsFalse(tree.Cut(new CubeRoot(30), out low, out lval, out high, out hval)); - Assert.IsTrue(lval && hval); - Assert.AreEqual(4, high); - Assert.AreEqual(3, low); + Assert.Multiple(() => + { + Assert.That(tree.Cut(new CubeRoot(27), out int low, out bool lval, out int high, out bool hval), Is.True); + Assert.That(lval && hval, Is.True); + Assert.That(high, Is.EqualTo(4)); + Assert.That(low, Is.EqualTo(2)); + Assert.That(tree.Cut(new CubeRoot(30), out low, out lval, out high, out hval), Is.False); + Assert.That(lval && hval, Is.True); + Assert.That(high, Is.EqualTo(4)); + Assert.That(low, Is.EqualTo(3)); + }); } - [Test] public void CutInt() { @@ -2208,17 +2467,19 @@ public void CutInt() tree.Add(2 * i); } - Assert.IsFalse(tree.Cut(new IC(3), out int low, out bool lval, out int high, out bool hval)); - Assert.IsTrue(lval && hval); - Assert.AreEqual(4, high); - Assert.AreEqual(2, low); - Assert.IsTrue(tree.Cut(new IC(6), out low, out lval, out high, out hval)); - Assert.IsTrue(lval && hval); - Assert.AreEqual(8, high); - Assert.AreEqual(4, low); + Assert.Multiple(() => + { + Assert.That(tree.Cut(new IC(3), out int low, out bool lval, out int high, out bool hval), Is.False); + Assert.That(lval && hval, Is.True); + Assert.That(high, Is.EqualTo(4)); + Assert.That(low, Is.EqualTo(2)); + Assert.That(tree.Cut(new IC(6), out low, out lval, out high, out hval), Is.True); + Assert.That(lval && hval, Is.True); + Assert.That(high, Is.EqualTo(8)); + Assert.That(low, Is.EqualTo(4)); + }); } - [Test] public void CutInterval() { @@ -2227,31 +2488,41 @@ public void CutInterval() tree.Add(2 * i); } - Assert.IsTrue(tree.Cut(new Interval(5, 9), out int lo, out bool lv, out int hi, out bool hv)); - Assert.IsTrue(lv && hv); - Assert.AreEqual(10, hi); - Assert.AreEqual(4, lo); - Assert.IsTrue(tree.Cut(new Interval(6, 10), out lo, out lv, out hi, out hv)); - Assert.IsTrue(lv && hv); - Assert.AreEqual(12, hi); - Assert.AreEqual(4, lo); + Assert.That(tree.Cut(new Interval(5, 9), out int lo, out bool lv, out int hi, out bool hv), Is.True); + Assert.That(lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(10)); + Assert.That(lo, Is.EqualTo(4)); + Assert.That(tree.Cut(new Interval(6, 10), out lo, out lv, out hi, out hv), Is.True); + Assert.That(lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(12)); + Assert.That(lo, Is.EqualTo(4)); + for (int i = 0; i < 100; i++) { tree.Add(2 * i); } tree.Cut(new Interval(77, 105), out lo, out lv, out hi, out hv); - Assert.IsTrue(lv && hv); - Assert.AreEqual(106, hi); - Assert.AreEqual(76, lo); + Assert.Multiple(() => + { + Assert.That(lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(106)); + Assert.That(lo, Is.EqualTo(76)); + }); tree.Cut(new Interval(5, 7), out lo, out lv, out hi, out hv); - Assert.IsTrue(lv && hv); - Assert.AreEqual(8, hi); - Assert.AreEqual(4, lo); + Assert.Multiple(() => + { + Assert.That(lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(8)); + Assert.That(lo, Is.EqualTo(4)); + }); tree.Cut(new Interval(80, 110), out lo, out lv, out hi, out hv); - Assert.IsTrue(lv && hv); - Assert.AreEqual(112, hi); - Assert.AreEqual(78, lo); + Assert.Multiple(() => + { + Assert.That(lv && hv, Is.True); + Assert.That(hi, Is.EqualTo(112)); + Assert.That(lo, Is.EqualTo(78)); + }); } @@ -2263,17 +2534,20 @@ public void UpperCut() tree.Add(i); } - Assert.IsFalse(tree.Cut(new CubeRoot(1000), out int l, out bool lv, out _, out bool hv)); - Assert.IsTrue(lv && !hv); - Assert.AreEqual(9, l); - Assert.IsFalse(tree.Cut(new CubeRoot(-50), out _, out lv, out int h, out hv)); - Assert.IsTrue(!lv && hv); - Assert.AreEqual(0, h); + Assert.Multiple(() => + { + Assert.That(tree.Cut(new CubeRoot(1000), out int l, out bool lv, out _, out bool hv), Is.False); + Assert.That(lv && !hv, Is.True); + Assert.That(l, Is.EqualTo(9)); + Assert.That(tree.Cut(new CubeRoot(-50), out _, out lv, out int h, out hv), Is.False); + Assert.That(!lv && hv, Is.True); + Assert.That(h, Is.EqualTo(0)); + }); } [TearDown] - public void Dispose() { ic = null; tree = null; } + public void Dispose() { ic = null; tree.Dispose(); } } } @@ -2298,8 +2572,8 @@ public class AddAll public void EmptyEmpty() { tree.AddAll(new FunEnumerable(0, new Func(sqr))); - Assert.AreEqual(0, tree.Count); - Assert.IsTrue(tree.Check()); + Assert.That(tree, Is.Empty); + Assert.That(tree.Check(), Is.True); } @@ -2312,8 +2586,8 @@ public void SomeEmpty() } tree.AddAll(new FunEnumerable(0, new Func(sqr))); - Assert.AreEqual(5, tree.Count); - Assert.IsTrue(tree.Check()); + Assert.That(tree, Has.Count.EqualTo(5)); + Assert.That(tree.Check(), Is.True); } @@ -2321,12 +2595,15 @@ public void SomeEmpty() public void EmptySome() { tree.AddAll(new FunEnumerable(4, new Func(sqr))); - Assert.AreEqual(4, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.AreEqual(0, tree[0]); - Assert.AreEqual(1, tree[1]); - Assert.AreEqual(4, tree[2]); - Assert.AreEqual(9, tree[3]); + Assert.That(tree, Has.Count.EqualTo(4)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(tree[0], Is.EqualTo(0)); + Assert.That(tree[1], Is.EqualTo(1)); + Assert.That(tree[2], Is.EqualTo(4)); + Assert.That(tree[3], Is.EqualTo(9)); + }); } @@ -2339,14 +2616,17 @@ public void SomeSome() } tree.AddAll(new FunEnumerable(4, new Func(sqr))); - Assert.AreEqual(8, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree, 0, 1, 4, 5, 6, 7, 8, 9)); + Assert.That(tree, Has.Count.EqualTo(8)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree, 0, 1, 4, 5, 6, 7, 8, 9), Is.True); + }); } [TearDown] - public void Dispose() { tree = null; } + public void Dispose() { tree.Dispose(); } } @@ -2370,8 +2650,8 @@ public class AddSorted public void EmptyEmpty() { tree.AddSorted(new FunEnumerable(0, new Func(sqr))); - Assert.AreEqual(0, tree.Count); - Assert.IsTrue(tree.Check()); + Assert.That(tree, Is.Empty); + Assert.That(tree.Check(), Is.True); } @@ -2385,8 +2665,8 @@ public void SomeEmpty() } tree.AddSorted(new FunEnumerable(0, new Func(sqr))); - Assert.AreEqual(5, tree.Count); - Assert.IsTrue(tree.Check()); + Assert.That(tree, Has.Count.EqualTo(5)); + Assert.That(tree.Check(), Is.True); } @@ -2395,12 +2675,15 @@ public void SomeEmpty() public void EmptySome() { tree.AddSorted(new FunEnumerable(4, new Func(sqr))); - Assert.AreEqual(4, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.AreEqual(0, tree[0]); - Assert.AreEqual(1, tree[1]); - Assert.AreEqual(4, tree[2]); - Assert.AreEqual(9, tree[3]); + Assert.That(tree, Has.Count.EqualTo(4)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(tree[0], Is.EqualTo(0)); + Assert.That(tree[1], Is.EqualTo(1)); + Assert.That(tree[2], Is.EqualTo(4)); + Assert.That(tree[3], Is.EqualTo(9)); + }); } @@ -2414,21 +2697,24 @@ public void SomeSome() } tree.AddSorted(new FunEnumerable(4, new Func(sqr))); - Assert.AreEqual(8, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree, 0, 1, 4, 5, 6, 7, 8, 9)); + Assert.That(tree, Has.Count.EqualTo(8)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree, 0, 1, 4, 5, 6, 7, 8, 9), Is.True); + }); } [Test] public void EmptyBad() { var exception = Assert.Throws(() => tree.AddSorted(new FunEnumerable(9, new Func(bad)))); - Assert.AreEqual("Argument not sorted", exception.Message); + Assert.That(exception.Message, Is.EqualTo("Argument not sorted")); } [TearDown] - public void Dispose() { tree = null; } + public void Dispose() { tree.Dispose(); } } [TestFixture] @@ -2458,30 +2744,45 @@ public void Init() public void RemoveAll() { tree.RemoveAll(tree2.RangeFromTo(3, 7)); - Assert.AreEqual(8, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree, 0, 1, 2, 3, 5, 7, 8, 9)); + Assert.That(tree, Has.Count.EqualTo(8)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree, 0, 1, 2, 3, 5, 7, 8, 9), Is.True); + }); tree.RemoveAll(tree2.RangeFromTo(3, 7)); - Assert.AreEqual(8, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree, 0, 1, 2, 3, 5, 7, 8, 9)); + Assert.That(tree, Has.Count.EqualTo(8)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree, 0, 1, 2, 3, 5, 7, 8, 9), Is.True); + }); tree.RemoveAll(tree2.RangeFromTo(13, 17)); - Assert.AreEqual(8, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree, 0, 1, 2, 3, 5, 7, 8, 9)); + Assert.That(tree, Has.Count.EqualTo(8)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree, 0, 1, 2, 3, 5, 7, 8, 9), Is.True); + }); tree.RemoveAll(tree2.RangeFromTo(3, 17)); - Assert.AreEqual(7, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree, 0, 1, 2, 3, 5, 7, 9)); + Assert.That(tree, Has.Count.EqualTo(7)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree, 0, 1, 2, 3, 5, 7, 9), Is.True); + }); for (int i = 0; i < 10; i++) { tree2.Add(i); } tree.RemoveAll(tree2.RangeFromTo(-1, 10)); - Assert.AreEqual(0, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree)); + Assert.That(tree, Is.Empty); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree), Is.True); + }); } @@ -2489,53 +2790,74 @@ public void RemoveAll() public void RetainAll() { tree.RetainAll(tree2.RangeFromTo(3, 17)); - Assert.AreEqual(3, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree, 4, 6, 8)); + Assert.That(tree, Has.Count.EqualTo(3)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree, 4, 6, 8), Is.True); + }); tree.RetainAll(tree2.RangeFromTo(1, 17)); - Assert.AreEqual(3, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree, 4, 6, 8)); + Assert.That(tree, Has.Count.EqualTo(3)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree, 4, 6, 8), Is.True); + }); tree.RetainAll(tree2.RangeFromTo(3, 5)); - Assert.AreEqual(1, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree, 4)); + Assert.That(tree, Has.Count.EqualTo(1)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree, 4), Is.True); + }); tree.RetainAll(tree2.RangeFromTo(7, 17)); - Assert.AreEqual(0, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree)); + Assert.That(tree, Is.Empty); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree), Is.True); + }); for (int i = 0; i < 10; i++) { tree.Add(i); } tree.RetainAll(tree2.RangeFromTo(5, 5)); - Assert.AreEqual(0, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree)); + Assert.That(tree, Is.Empty); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree), Is.True); + }); for (int i = 0; i < 10; i++) { tree.Add(i); } tree.RetainAll(tree2.RangeFromTo(15, 25)); - Assert.AreEqual(0, tree.Count); - Assert.IsTrue(tree.Check()); - Assert.IsTrue(IC.Eq(tree)); + Assert.That(tree, Is.Empty); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(IC.Eq(tree), Is.True); + }); } [Test] public void ContainsAll() { - Assert.IsFalse(tree.ContainsAll(tree2)); - Assert.IsTrue(tree.ContainsAll(tree)); + Assert.Multiple(() => + { + Assert.That(tree.ContainsAll(tree2), Is.False); + Assert.That(tree.ContainsAll(tree), Is.True); + }); tree2.Clear(); - Assert.IsTrue(tree.ContainsAll(tree2)); + Assert.That(tree.ContainsAll(tree2), Is.True); tree.Clear(); - Assert.IsTrue(tree.ContainsAll(tree2)); + Assert.That(tree.ContainsAll(tree2), Is.True); tree2.Add(8); - Assert.IsFalse(tree.ContainsAll(tree2)); + Assert.That(tree.ContainsAll(tree2), Is.False); } @@ -2543,17 +2865,26 @@ public void ContainsAll() public void RemoveInterval() { tree.RemoveInterval(3, 4); - Assert.IsTrue(tree.Check()); - Assert.AreEqual(6, tree.Count); - Assert.IsTrue(IC.Eq(tree, 0, 1, 2, 7, 8, 9)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(tree, Has.Count.EqualTo(6)); + Assert.That(IC.Eq(tree, 0, 1, 2, 7, 8, 9), Is.True); + }); tree.RemoveInterval(2, 3); - Assert.IsTrue(tree.Check()); - Assert.AreEqual(3, tree.Count); - Assert.IsTrue(IC.Eq(tree, 0, 1, 9)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(tree, Has.Count.EqualTo(3)); + Assert.That(IC.Eq(tree, 0, 1, 9), Is.True); + }); tree.RemoveInterval(0, 3); - Assert.IsTrue(tree.Check()); - Assert.AreEqual(0, tree.Count); - Assert.IsTrue(IC.Eq(tree)); + Assert.Multiple(() => + { + Assert.That(tree.Check(), Is.True); + Assert.That(tree, Is.Empty); + Assert.That(IC.Eq(tree), Is.True); + }); } @@ -2582,9 +2913,9 @@ public void RemoveRangeBad3() public void GetRange() { SCG.IEnumerable e = tree[3, 3]; - Assert.IsTrue(IC.Eq(e, 3, 4, 5)); + Assert.That(IC.Eq(e, 3, 4, 5), Is.True); e = tree[3, 0]; - Assert.IsTrue(IC.Eq(e)); + Assert.That(IC.Eq(e), Is.True); } [Test] @@ -2615,7 +2946,7 @@ public void GetRangeBad3() } [TearDown] - public void Dispose() { tree = null; tree2 = null; } + public void Dispose() { tree.Dispose(); tree2.Dispose(); } } } @@ -2628,22 +2959,22 @@ namespace Sync public class SyncRoot { private TreeSet tree; - private readonly Object mySyncRoot = new Object(); + private readonly object mySyncRoot = new(); private readonly int sz = 5000; [Test] public void Safe() { - System.Threading.Thread t1 = new System.Threading.Thread(new System.Threading.ThreadStart(safe1)); - System.Threading.Thread t2 = new System.Threading.Thread(new System.Threading.ThreadStart(safe2)); + System.Threading.Thread t1 = new(new System.Threading.ThreadStart(safe1)); + System.Threading.Thread t2 = new(new System.Threading.ThreadStart(safe2)); t1.Start(); t2.Start(); t1.Join(); t2.Join(); - Assert.AreEqual(2 * sz + 1, tree.Count); - Assert.IsTrue(tree.Check()); + Assert.That(tree, Has.Count.EqualTo(2 * sz + 1)); + Assert.That(tree.Check(), Is.True); } @@ -2654,8 +2985,8 @@ public void UnSafe() for (int i = 0; i < 10; i++) { - System.Threading.Thread t1 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe1)); - System.Threading.Thread t2 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe2)); + System.Threading.Thread t1 = new(new System.Threading.ThreadStart(unsafe1)); + System.Threading.Thread t2 = new(new System.Threading.ThreadStart(unsafe2)); t1.Start(); t2.Start(); @@ -2668,21 +2999,21 @@ public void UnSafe() } } - Assert.IsTrue(bad, "No sync problems!"); + Assert.That(bad, Is.True, "No sync problems!"); } [Test] public void SafeUnSafe() { - System.Threading.Thread t1 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe1)); - System.Threading.Thread t2 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe2)); + System.Threading.Thread t1 = new(new System.Threading.ThreadStart(unsafe1)); + System.Threading.Thread t2 = new(new System.Threading.ThreadStart(unsafe2)); t1.Start(); t1.Join(); t2.Start(); t2.Join(); - Assert.AreEqual(2 * sz + 1, tree.Count); + Assert.That(tree, Has.Count.EqualTo(2 * sz + 1)); } @@ -2759,7 +3090,7 @@ private void safe2() [TearDown] - public void Dispose() { tree = null; } + public void Dispose() { tree.Dispose(); } } @@ -2802,10 +3133,10 @@ private class A [Test] public void Safe() { - A a = new A(tree); + A a = new(tree); a.traverse(); - Assert.AreEqual(sz, a.count); + Assert.That(a.count, Is.EqualTo(sz)); } @@ -2832,13 +3163,13 @@ public void RegrettablyUnsafe() for (int i = 0; i < 10; i++) { - Assert.AreEqual(sz, a[i].count); + Assert.That(a[i].count, Is.EqualTo(sz)); } } [TearDown] - public void Dispose() { tree = null; } + public void Dispose() { tree.Dispose(); } } } @@ -2850,7 +3181,7 @@ namespace Hashing [TestFixture] public class ISequenced { - private ISequenced dit, dat, dut; + private TreeSet dit, dat, dut; [SetUp] @@ -2865,7 +3196,7 @@ public void Init() [Test] public void EmptyEmpty() { - Assert.IsTrue(dit.SequencedEquals(dat)); + Assert.That(dit.SequencedEquals(dat), Is.True); } @@ -2873,23 +3204,29 @@ public void EmptyEmpty() public void EmptyNonEmpty() { dit.Add(3); - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsFalse(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dat.SequencedEquals(dit), Is.False); + }); } [Test] public void HashVal() { - Assert.AreEqual(CHC.SequencedHashCode(), dit.GetSequencedHashCode()); + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode())); dit.Add(3); - Assert.AreEqual(CHC.SequencedHashCode(3), dit.GetSequencedHashCode()); + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(3))); dit.Add(7); - Assert.AreEqual(CHC.SequencedHashCode(3, 7), dit.GetSequencedHashCode()); - Assert.AreEqual(CHC.SequencedHashCode(), dut.GetSequencedHashCode()); + Assert.Multiple(() => + { + Assert.That(dit.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(3, 7))); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode())); + }); dut.Add(3); - Assert.AreEqual(CHC.SequencedHashCode(3), dut.GetSequencedHashCode()); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(3))); dut.Add(7); - Assert.AreEqual(CHC.SequencedHashCode(7, 3), dut.GetSequencedHashCode()); + Assert.That(dut.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(7, 3))); } @@ -2899,11 +3236,17 @@ public void Normal() dit.Add(3); dit.Add(7); dat.Add(3); - Assert.IsFalse(dit.SequencedEquals(dat)); - Assert.IsFalse(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.False); + Assert.That(dat.SequencedEquals(dit), Is.False); + }); dat.Add(7); - Assert.IsTrue(dit.SequencedEquals(dat)); - Assert.IsTrue(dat.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dat), Is.True); + Assert.That(dat.SequencedEquals(dit), Is.True); + }); } @@ -2912,131 +3255,154 @@ public void WrongOrder() { dit.Add(3); dut.Add(3); - Assert.IsTrue(dit.SequencedEquals(dut)); - Assert.IsTrue(dut.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dut), Is.True); + Assert.That(dut.SequencedEquals(dit), Is.True); + }); dit.Add(7); dut.Add(7); - Assert.IsFalse(dit.SequencedEquals(dut)); - Assert.IsFalse(dut.SequencedEquals(dit)); + Assert.Multiple(() => + { + Assert.That(dit.SequencedEquals(dut), Is.False); + Assert.That(dut.SequencedEquals(dit), Is.False); + }); } [Test] public void Reflexive() { - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); dit.Add(3); - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); dit.Add(7); - Assert.IsTrue(dit.SequencedEquals(dit)); + Assert.That(dit.SequencedEquals(dit), Is.True); } [TearDown] public void Dispose() { - dit = null; - dat = null; - dut = null; + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); } - } - [TestFixture] - public class IEditableCollection - { - private ICollection dit, dat, dut; + [TestFixture] + public class IEditableCollection + { + private TreeSet dit, dat, dut; - [SetUp] - public void Init() - { - dit = new TreeSet(SCG.Comparer.Default, EqualityComparer.Default); - dat = new TreeSet(SCG.Comparer.Default, EqualityComparer.Default); - dut = new TreeSet(new RevIC(), EqualityComparer.Default); - } + [SetUp] + public void Init() + { + dit = new TreeSet(SCG.Comparer.Default, EqualityComparer.Default); + dat = new TreeSet(SCG.Comparer.Default, EqualityComparer.Default); + dut = new TreeSet(new RevIC(), EqualityComparer.Default); + } - [Test] - public void EmptyEmpty() - { - Assert.IsTrue(dit.UnsequencedEquals(dat)); - } + [Test] + public void EmptyEmpty() + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + } - [Test] - public void EmptyNonEmpty() - { - dit.Add(3); - Assert.IsFalse(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dat.UnsequencedEquals(dit)); - } + [Test] + public void EmptyNonEmpty() + { + dit.Add(3); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.False); + Assert.That(dat.UnsequencedEquals(dit), Is.False); + }); + } - [Test] - public void HashVal() - { - Assert.AreEqual(CHC.UnsequencedHashCode(), dit.GetUnsequencedHashCode()); - dit.Add(3); - Assert.AreEqual(CHC.UnsequencedHashCode(3), dit.GetUnsequencedHashCode()); - dit.Add(7); - Assert.AreEqual(CHC.UnsequencedHashCode(3, 7), dit.GetUnsequencedHashCode()); - Assert.AreEqual(CHC.UnsequencedHashCode(), dut.GetUnsequencedHashCode()); - dut.Add(3); - Assert.AreEqual(CHC.UnsequencedHashCode(3), dut.GetUnsequencedHashCode()); - dut.Add(7); - Assert.AreEqual(CHC.UnsequencedHashCode(7, 3), dut.GetUnsequencedHashCode()); - } + [Test] + public void HashVal() + { + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode())); + dit.Add(3); + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3))); + dit.Add(7); + Assert.Multiple(() => + { + Assert.That(dit.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3, 7))); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode())); + }); + dut.Add(3); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(3))); + dut.Add(7); + Assert.That(dut.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(7, 3))); + } - [Test] - public void Normal() - { - dit.Add(3); - dit.Add(7); - dat.Add(3); - Assert.IsFalse(dit.UnsequencedEquals(dat)); - Assert.IsFalse(dat.UnsequencedEquals(dit)); - dat.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dat)); - Assert.IsTrue(dat.UnsequencedEquals(dit)); - } + [Test] + public void Normal() + { + dit.Add(3); + dit.Add(7); + dat.Add(3); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.False); + Assert.That(dat.UnsequencedEquals(dit), Is.False); + }); + dat.Add(7); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dat), Is.True); + Assert.That(dat.UnsequencedEquals(dit), Is.True); + }); + } - [Test] - public void WrongOrder() - { - dit.Add(3); - dut.Add(3); - Assert.IsTrue(dit.UnsequencedEquals(dut)); - Assert.IsTrue(dut.UnsequencedEquals(dit)); - dit.Add(7); - dut.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dut)); - Assert.IsTrue(dut.UnsequencedEquals(dit)); - } + [Test] + public void WrongOrder() + { + dit.Add(3); + dut.Add(3); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dut), Is.True); + Assert.That(dut.UnsequencedEquals(dit), Is.True); + }); + dit.Add(7); + dut.Add(7); + Assert.Multiple(() => + { + Assert.That(dit.UnsequencedEquals(dut), Is.True); + Assert.That(dut.UnsequencedEquals(dit), Is.True); + }); + } - [Test] - public void Reflexive() - { - Assert.IsTrue(dit.UnsequencedEquals(dit)); - dit.Add(3); - Assert.IsTrue(dit.UnsequencedEquals(dit)); - dit.Add(7); - Assert.IsTrue(dit.UnsequencedEquals(dit)); - } + [Test] + public void Reflexive() + { + Assert.That(dit.UnsequencedEquals(dit), Is.True); + dit.Add(3); + Assert.That(dit.UnsequencedEquals(dit), Is.True); + dit.Add(7); + Assert.That(dit.UnsequencedEquals(dit), Is.True); + } - [TearDown] - public void Dispose() - { - dit = null; - dat = null; - dut = null; + [TearDown] + public void Dispose() + { + dit.Dispose(); + dat.Dispose(); + dut.Dispose(); + } } } - } } \ No newline at end of file diff --git a/C5.Tests/Wrappers/GuardedDictionaryTests.cs b/C5.Tests/Wrappers/GuardedDictionaryTests.cs index e4d0ba42..3142256b 100644 --- a/C5.Tests/Wrappers/GuardedDictionaryTests.cs +++ b/C5.Tests/Wrappers/GuardedDictionaryTests.cs @@ -17,7 +17,7 @@ public void Keys_returns_GuardedCollectionValue() var guarded = new GuardedDictionary(source); - Assert.IsAssignableFrom>(guarded.Keys); + Assert.That(guarded.Keys, Is.AssignableFrom>()); } [Test] @@ -32,7 +32,7 @@ public void Keys_returns_Keys() var guarded = new GuardedDictionary(source); - CollectionAssert.AreEquivalent(new[] { 1, 2, 3 }, guarded.Keys); + Assert.That(guarded.Keys, Is.EquivalentTo(new[] { 1, 2, 3 })); } [Test] @@ -47,7 +47,7 @@ public void Values_returns_GuardedCollectionValue() var guarded = new GuardedDictionary(source); - Assert.IsAssignableFrom>(guarded.Values); + Assert.That(guarded.Values, Is.AssignableFrom>()); } [Test] @@ -62,7 +62,7 @@ public void Values_returns_Values() var guarded = new GuardedDictionary(source); - CollectionAssert.AreEquivalent(new[] { "one", "two", "three" }, guarded.Values); + Assert.That(guarded.Values, Is.EquivalentTo(new[] { "one", "two", "three" })); } } } diff --git a/C5.Tests/Wrappers/GuardedSortedDictionaryTests.cs b/C5.Tests/Wrappers/GuardedSortedDictionaryTests.cs index cf79cc14..0bb0a5c7 100644 --- a/C5.Tests/Wrappers/GuardedSortedDictionaryTests.cs +++ b/C5.Tests/Wrappers/GuardedSortedDictionaryTests.cs @@ -19,7 +19,7 @@ public void Keys_returns_GuardedSorted() var guarded = new GuardedSortedDictionary(source); - Assert.IsAssignableFrom>(guarded.Keys); + Assert.That(guarded.Keys, Is.AssignableFrom>()); } [Test] @@ -36,7 +36,7 @@ public void Keys_returns_Keys() var guarded = new GuardedSortedDictionary(source); - CollectionAssert.AreEquivalent(new[] { 3, 2, 1 }, guarded.Keys); + Assert.That(guarded.Keys, Is.EquivalentTo(new[] { 3, 2, 1 })); } [Test] @@ -53,7 +53,7 @@ public void Values_returns_GuardedCollectionValue() var guarded = new GuardedSortedDictionary(source); - Assert.IsAssignableFrom>(guarded.Values); + Assert.That(guarded.Values, Is.AssignableFrom>()); } [Test] @@ -70,7 +70,7 @@ public void Values_returns_Values() var guarded = new GuardedSortedDictionary(source); - CollectionAssert.AreEquivalent(new[] { "one", "two", "three" }, guarded.Values); + Assert.That(guarded.Values, Is.EquivalentTo(new[] { "one", "two", "three" })); } } } diff --git a/C5.Tests/WrappersTest.cs b/C5.Tests/WrappersTest.cs index 1f0ae84e..2f5ca709 100644 --- a/C5.Tests/WrappersTest.cs +++ b/C5.Tests/WrappersTest.cs @@ -13,7 +13,7 @@ namespace events public class IList_ { private ArrayList list; - private ICollectionValue guarded; + private GuardedList guarded; private CollectionEventList seen; [SetUp] @@ -29,10 +29,13 @@ public void Init() [Test] public void Listenable() { - Assert.AreEqual(EventType.All, guarded.ListenableEvents); - Assert.AreEqual(EventType.None, guarded.ActiveEvents); + Assert.Multiple(() => + { + Assert.That(guarded.ListenableEvents, Is.EqualTo(EventType.All)); + Assert.That(guarded.ActiveEvents, Is.EqualTo(EventType.None)); + }); listen(); - Assert.AreEqual(EventType.All, guarded.ActiveEvents); + Assert.That(guarded.ActiveEvents, Is.EqualTo(EventType.All)); } [Test] @@ -41,13 +44,13 @@ public void SetThis() list.Add(4); list.Add(56); list.Add(8); listen(); list[1] = 45; - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), guarded), new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(56,1), guarded), new CollectionEvent(EventType.Added, new ItemCountEventArgs(45, 1), guarded), new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(45,1), guarded), new CollectionEvent(EventType.Changed, new EventArgs(), guarded) - }); + ]); } [Test] @@ -56,11 +59,11 @@ public void Insert() list.Add(4); list.Add(56); list.Add(8); listen(); list.Insert(1, 45); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(45,1), guarded), new CollectionEvent(EventType.Added, new ItemCountEventArgs(45, 1), guarded), new CollectionEvent(EventType.Changed, new EventArgs(), guarded) - }); + ]); } [Test] @@ -68,9 +71,9 @@ public void InsertAll() { list.Add(4); list.Add(56); list.Add(8); listen(); - list.InsertAll(1, new int[] { 666, 777, 888 }); + list.InsertAll(1, [666, 777, 888]); //seen.Print(Console.Error); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(666,1), guarded), new CollectionEvent(EventType.Added, new ItemCountEventArgs(666, 1), guarded), new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(777,2), guarded), @@ -78,9 +81,9 @@ public void InsertAll() new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(888,3), guarded), new CollectionEvent(EventType.Added, new ItemCountEventArgs(888, 1), guarded), new CollectionEvent(EventType.Changed, new EventArgs(), guarded) - }); - list.InsertAll(1, new int[] { }); - seen.Check(new CollectionEvent[] { }); + ]); + list.InsertAll(1, []); + seen.Check([]); } [Test] @@ -89,17 +92,17 @@ public void InsertFirstLast() list.Add(4); list.Add(56); list.Add(8); listen(); list.InsertFirst(45); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(45,0), guarded), new CollectionEvent(EventType.Added, new ItemCountEventArgs(45, 1), guarded), new CollectionEvent(EventType.Changed, new EventArgs(), guarded) - }); + ]); list.InsertLast(88); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(88,4), guarded), new CollectionEvent(EventType.Added, new ItemCountEventArgs(88, 1), guarded), new CollectionEvent(EventType.Changed, new EventArgs(), guarded) - }); + ]); } [Test] @@ -108,9 +111,9 @@ public void Remove() list.Add(4); list.Add(56); list.Add(8); listen(); list.Remove(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(8, 1), guarded), - new CollectionEvent(EventType.Changed, new EventArgs(), guarded)}); + new CollectionEvent(EventType.Changed, new EventArgs(), guarded)]); } [Test] @@ -119,10 +122,10 @@ public void RemoveFirst() list.Add(4); list.Add(56); list.Add(8); listen(); list.RemoveFirst(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(4,0), guarded), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(4, 1), guarded), - new CollectionEvent(EventType.Changed, new EventArgs(), guarded)}); + new CollectionEvent(EventType.Changed, new EventArgs(), guarded)]); } [Test] @@ -131,10 +134,10 @@ public void RemoveLast() list.Add(4); list.Add(56); list.Add(8); listen(); list.RemoveLast(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(8,2), guarded), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(8, 1), guarded), - new CollectionEvent(EventType.Changed, new EventArgs(), guarded)}); + new CollectionEvent(EventType.Changed, new EventArgs(), guarded)]); } [Test] @@ -143,11 +146,11 @@ public void Reverse() list.Add(4); list.Add(56); list.Add(8); listen(); list.Reverse(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Changed, new EventArgs(), guarded) - }); + ]); list.View(1, 0).Reverse(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } @@ -157,11 +160,11 @@ public void Sort() list.Add(4); list.Add(56); list.Add(8); listen(); list.Sort(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Changed, new EventArgs(), guarded) - }); + ]); list.View(1, 0).Sort(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } [Test] @@ -170,11 +173,11 @@ public void Shuffle() list.Add(4); list.Add(56); list.Add(8); listen(); list.Shuffle(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Changed, new EventArgs(), guarded) - }); + ]); list.View(1, 0).Shuffle(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } [Test] @@ -183,10 +186,10 @@ public void RemoveAt() list.Add(4); list.Add(56); list.Add(8); listen(); list.RemoveAt(1); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(56,1), guarded), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), guarded), - new CollectionEvent(EventType.Changed, new EventArgs(), guarded)}); + new CollectionEvent(EventType.Changed, new EventArgs(), guarded)]); } [Test] @@ -195,12 +198,12 @@ public void RemoveInterval() list.Add(4); list.Add(56); list.Add(8); listen(); list.RemoveInterval(1, 2); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Cleared, new ClearedRangeEventArgs(false,2,1), guarded), new CollectionEvent(EventType.Changed, new EventArgs(), guarded) - }); + ]); list.RemoveInterval(1, 0); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } [Test] @@ -209,13 +212,13 @@ public void Update() list.Add(4); list.Add(56); list.Add(8); listen(); list.Update(53); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), guarded), new CollectionEvent(EventType.Added, new ItemCountEventArgs(53, 1), guarded), new CollectionEvent(EventType.Changed, new EventArgs(), guarded) - }); + ]); list.Update(67); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } [Test] @@ -225,13 +228,13 @@ public void FindOrAdd() listen(); int val = 53; list.FindOrAdd(ref val); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); val = 67; list.FindOrAdd(ref val); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(67, 1), guarded), new CollectionEvent(EventType.Changed, new EventArgs(), guarded) - }); + ]); } [Test] @@ -241,29 +244,29 @@ public void UpdateOrAdd() listen(); int val = 53; list.UpdateOrAdd(val); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), guarded), new CollectionEvent(EventType.Added, new ItemCountEventArgs(53, 1), guarded), new CollectionEvent(EventType.Changed, new EventArgs(), guarded) - }); + ]); val = 67; list.UpdateOrAdd(val); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(67, 1), guarded), new CollectionEvent(EventType.Changed, new EventArgs(), guarded) - }); + ]); list.UpdateOrAdd(51, out _); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(53, 1), guarded), new CollectionEvent(EventType.Added, new ItemCountEventArgs(51, 1), guarded), new CollectionEvent(EventType.Changed, new EventArgs(), guarded) - }); + ]); // val = 67; list.UpdateOrAdd(81, out _); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(81, 1), guarded), new CollectionEvent(EventType.Changed, new EventArgs(), guarded) - }); + ]); } [Test] @@ -272,13 +275,13 @@ public void RemoveItem() list.Add(4); list.Add(56); list.Add(18); listen(); list.Remove(53); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(56, 1), guarded), - new CollectionEvent(EventType.Changed, new EventArgs(), guarded)}); + new CollectionEvent(EventType.Changed, new EventArgs(), guarded)]); list.Remove(11); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(18, 1), guarded), - new CollectionEvent(EventType.Changed, new EventArgs(), guarded)}); + new CollectionEvent(EventType.Changed, new EventArgs(), guarded)]); } [Test] @@ -289,14 +292,14 @@ public void RemoveAll() list.Add(10 * i + 5); } listen(); - list.RemoveAll(new int[] { 32, 187, 45 }); + list.RemoveAll([32, 187, 45]); //TODO: the order depends on internals of the HashSet - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(35, 1), guarded), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(45, 1), guarded), - new CollectionEvent(EventType.Changed, new EventArgs(), guarded)}); - list.RemoveAll(new int[] { 200, 300 }); - seen.Check(new CollectionEvent[] { }); + new CollectionEvent(EventType.Changed, new EventArgs(), guarded)]); + list.RemoveAll([200, 300]); + seen.Check([]); } [Test] @@ -305,17 +308,17 @@ public void Clear() list.Add(4); list.Add(56); list.Add(8); listen(); list.View(1, 1).Clear(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Cleared, new ClearedRangeEventArgs(false,1,1), guarded), new CollectionEvent(EventType.Changed, new EventArgs(), guarded) - }); + ]); list.Clear(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Cleared, new ClearedRangeEventArgs(true,2,0), guarded), new CollectionEvent(EventType.Changed, new EventArgs(), guarded) - }); + ]); list.Clear(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } [Test] @@ -324,14 +327,14 @@ public void ListDispose() list.Add(4); list.Add(56); list.Add(8); listen(); list.View(1, 1).Dispose(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); list.Dispose(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Cleared, new ClearedRangeEventArgs(true,3,0), guarded), new CollectionEvent(EventType.Changed, new EventArgs(), guarded) - }); + ]); list.Dispose(); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } @@ -343,15 +346,15 @@ public void RetainAll() list.Add(10 * i + 5); } listen(); - list.RetainAll(new int[] { 32, 187, 45, 62, 82, 95, 2 }); - seen.Check(new CollectionEvent[] { + list.RetainAll([32, 187, 45, 62, 82, 95, 2]); + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(15, 1), guarded), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(25, 1), guarded), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(55, 1), guarded), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(75, 1), guarded), - new CollectionEvent(EventType.Changed, new EventArgs(), guarded)}); - list.RetainAll(new int[] { 32, 187, 45, 62, 82, 95, 2 }); - seen.Check(new CollectionEvent[] { }); + new CollectionEvent(EventType.Changed, new EventArgs(), guarded)]); + list.RetainAll([32, 187, 45, 62, 82, 95, 2]); + seen.Check([]); } [Test] @@ -363,24 +366,24 @@ public void RemoveAllCopies() } listen(); list.RemoveAllCopies(14); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Removed, new ItemCountEventArgs(11, 1), guarded), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(14, 1), guarded), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(17, 1), guarded), - new CollectionEvent(EventType.Changed, new EventArgs(), guarded)}); + new CollectionEvent(EventType.Changed, new EventArgs(), guarded)]); list.RemoveAllCopies(14); - seen.Check(new CollectionEvent[] { }); + seen.Check([]); } [Test] public void Add() { listen(); - seen.Check(new CollectionEvent[0]); + seen.Check([]); list.Add(23); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(23, 1), guarded), - new CollectionEvent(EventType.Changed, new EventArgs(), guarded)}); + new CollectionEvent(EventType.Changed, new EventArgs(), guarded)]); } [Test] @@ -391,18 +394,18 @@ public void AddAll() list.Add(10 * i + 5); } listen(); - list.AddAll(new int[] { 45, 56, 67 }); - seen.Check(new CollectionEvent[] { + list.AddAll([45, 56, 67]); + seen.Check([ new CollectionEvent(EventType.Added, new ItemCountEventArgs(45, 1), guarded), new CollectionEvent(EventType.Added, new ItemCountEventArgs(56, 1), guarded), new CollectionEvent(EventType.Added, new ItemCountEventArgs(67, 1), guarded), - new CollectionEvent(EventType.Changed, new EventArgs(), guarded)}); - list.AddAll(new int[] { }); - seen.Check(new CollectionEvent[] { }); + new CollectionEvent(EventType.Changed, new EventArgs(), guarded)]); + list.AddAll([]); + seen.Check([]); } [TearDown] - public void Dispose() { list = null; seen = null; } + public void Dispose() { list.Dispose(); guarded.Dispose(); seen = null; } [Test] public void ViewChanged() @@ -482,7 +485,7 @@ private void w_ItemRemovedAt(object sender, ItemAtEventArgs eventArgs) public class StackQueue { private ArrayList list; - private ICollectionValue guarded; + private GuardedList guarded; private CollectionEventList seen; [SetUp] @@ -501,56 +504,56 @@ public void EnqueueDequeue() { listen(); list.Enqueue(67); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(67,0), guarded), new CollectionEvent(EventType.Added, new ItemCountEventArgs(67, 1), guarded), - new CollectionEvent(EventType.Changed, new EventArgs(), guarded)}); + new CollectionEvent(EventType.Changed, new EventArgs(), guarded)]); list.Enqueue(2); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(2,1), guarded), new CollectionEvent(EventType.Added, new ItemCountEventArgs(2, 1), guarded), - new CollectionEvent(EventType.Changed, new EventArgs(), guarded)}); + new CollectionEvent(EventType.Changed, new EventArgs(), guarded)]); list.Dequeue(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(67,0), guarded), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(67, 1), guarded), - new CollectionEvent(EventType.Changed, new EventArgs(), guarded)}); + new CollectionEvent(EventType.Changed, new EventArgs(), guarded)]); list.Dequeue(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(2,0), guarded), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(2, 1), guarded), - new CollectionEvent(EventType.Changed, new EventArgs(), guarded)}); + new CollectionEvent(EventType.Changed, new EventArgs(), guarded)]); } [Test] public void PushPop() { listen(); - seen.Check(new CollectionEvent[0]); + seen.Check([]); list.Push(23); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(23,0), guarded), new CollectionEvent(EventType.Added, new ItemCountEventArgs(23, 1), guarded), - new CollectionEvent(EventType.Changed, new EventArgs(), guarded)}); + new CollectionEvent(EventType.Changed, new EventArgs(), guarded)]); list.Push(-12); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.Inserted, new ItemAtEventArgs(-12,1), guarded), new CollectionEvent(EventType.Added, new ItemCountEventArgs(-12, 1), guarded), - new CollectionEvent(EventType.Changed, new EventArgs(), guarded)}); + new CollectionEvent(EventType.Changed, new EventArgs(), guarded)]); list.Pop(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(-12,1), guarded), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(-12, 1), guarded), - new CollectionEvent(EventType.Changed, new EventArgs(), guarded)}); + new CollectionEvent(EventType.Changed, new EventArgs(), guarded)]); list.Pop(); - seen.Check(new CollectionEvent[] { + seen.Check([ new CollectionEvent(EventType.RemovedAt, new ItemAtEventArgs(23,0), guarded), new CollectionEvent(EventType.Removed, new ItemCountEventArgs(23, 1), guarded), - new CollectionEvent(EventType.Changed, new EventArgs(), guarded)}); + new CollectionEvent(EventType.Changed, new EventArgs(), guarded)]); } [TearDown] - public void Dispose() { list = null; seen = null; } + public void Dispose() { list.Dispose(); guarded.Dispose(); seen = null; } } @@ -575,76 +578,104 @@ public void Dispose() [Test] public void NoExc() { - WrappedArray wrapped = new WrappedArray(new int[] { 4, 6, 5 }); - Assert.AreEqual(6, wrapped[1]); - Assert.IsTrue(IC.Eq(wrapped[1, 2], 6, 5)); + WrappedArray wrapped = new([4, 6, 5]); + Assert.Multiple(() => + { + Assert.That(wrapped[1], Is.EqualTo(6)); + Assert.That(IC.Eq(wrapped[1, 2], 6, 5), Is.True); + }); // bool is4(int i) { return i == 4; } - Assert.AreEqual(EventType.None, wrapped.ActiveEvents); - Assert.AreEqual(false, wrapped.All(is4)); - Assert.AreEqual(true, wrapped.AllowsDuplicates); + + Assert.Multiple(() => + { + Assert.That(wrapped.ActiveEvents, Is.EqualTo(EventType.None)); + Assert.That(wrapped.All(is4), Is.EqualTo(false)); + Assert.That(wrapped.AllowsDuplicates, Is.EqualTo(true)); + }); wrapped.Apply(delegate (int i) { }); - Assert.AreEqual("{ 5, 6, 4 }", wrapped.Backwards().ToString()); - Assert.AreEqual(true, wrapped.Check()); + Assert.Multiple(() => + { + Assert.That(wrapped.Backwards().ToString(), Is.EqualTo("{ 5, 6, 4 }")); + Assert.That(wrapped.Check(), Is.EqualTo(true)); + }); wrapped.Choose(); - Assert.AreEqual(true, wrapped.Contains(4)); - Assert.AreEqual(true, wrapped.ContainsAll(new ArrayList())); - Assert.AreEqual(1, wrapped.ContainsCount(4)); - Assert.AreEqual(Speed.Linear, wrapped.ContainsSpeed); + Assert.Multiple(() => + { + Assert.That(wrapped.Contains(4), Is.EqualTo(true)); + Assert.That(wrapped.ContainsAll(new ArrayList()), Is.EqualTo(true)); + Assert.That(wrapped.ContainsCount(4), Is.EqualTo(1)); + Assert.That(wrapped.ContainsSpeed, Is.EqualTo(Speed.Linear)); + }); int[] extarray = new int[5]; wrapped.CopyTo(extarray, 1); - Assert.IsTrue(IC.Eq(extarray, 0, 4, 6, 5, 0)); - Assert.AreEqual(3, wrapped.Count); - Assert.AreEqual(Speed.Constant, wrapped.CountSpeed); - Assert.AreEqual(Direction.Forwards, wrapped.Direction); - Assert.AreEqual(false, wrapped.DuplicatesByCounting); - Assert.AreEqual(System.Collections.Generic.EqualityComparer.Default, wrapped.EqualityComparer); - Assert.AreEqual(true, wrapped.Exists(is4)); - Assert.IsTrue(IC.Eq(wrapped.Filter(is4), 4)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(extarray, 0, 4, 6, 5, 0), Is.True); + Assert.That(wrapped, Has.Count.EqualTo(3)); + }); + Assert.Multiple(() => + { + Assert.That(wrapped.CountSpeed, Is.EqualTo(Speed.Constant)); + Assert.That(wrapped.Direction, Is.EqualTo(Direction.Forwards)); + Assert.That(wrapped.DuplicatesByCounting, Is.EqualTo(false)); + Assert.That(wrapped.EqualityComparer, Is.EqualTo(System.Collections.Generic.EqualityComparer.Default)); + Assert.That(wrapped.Exists(is4), Is.EqualTo(true)); + Assert.That(IC.Eq(wrapped.Filter(is4), 4), Is.True); + }); int j = 5; - Assert.AreEqual(true, wrapped.Find(ref j)); - Assert.AreEqual(true, wrapped.Find(is4, out j)); - Assert.AreEqual("[ 0:4 ]", wrapped.FindAll(is4).ToString()); - Assert.AreEqual(0, wrapped.FindIndex(is4)); - Assert.AreEqual(true, wrapped.FindLast(is4, out j)); - Assert.AreEqual(0, wrapped.FindLastIndex(is4)); - Assert.AreEqual(4, wrapped.First); + Assert.Multiple(() => + { + Assert.That(wrapped.Find(ref j), Is.EqualTo(true)); + Assert.That(wrapped.Find(is4, out j), Is.EqualTo(true)); + Assert.That(wrapped.FindAll(is4).ToString(), Is.EqualTo("[ 0:4 ]")); + Assert.That(wrapped.FindIndex(is4), Is.EqualTo(0)); + Assert.That(wrapped.FindLast(is4, out j), Is.EqualTo(true)); + Assert.That(wrapped.FindLastIndex(is4), Is.EqualTo(0)); + Assert.That(wrapped.First, Is.EqualTo(4)); + }); wrapped.GetEnumerator(); - Assert.AreEqual(CHC.SequencedHashCode(4, 6, 5), wrapped.GetSequencedHashCode()); - Assert.AreEqual(CHC.UnsequencedHashCode(4, 6, 5), wrapped.GetUnsequencedHashCode()); - Assert.AreEqual(Speed.Constant, wrapped.IndexingSpeed); - Assert.AreEqual(2, wrapped.IndexOf(5)); - Assert.AreEqual(false, wrapped.IsEmpty); - Assert.AreEqual(true, wrapped.IsReadOnly); - Assert.AreEqual(false, wrapped.IsSorted()); - Assert.AreEqual(true, wrapped.IsValid); - Assert.AreEqual(5, wrapped.Last); - Assert.AreEqual(2, wrapped.LastIndexOf(5)); - Assert.AreEqual(EventType.None, wrapped.ListenableEvents); + Assert.Multiple(() => + { + Assert.That(wrapped.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(4, 6, 5))); + Assert.That(wrapped.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(4, 6, 5))); + Assert.That(wrapped.IndexingSpeed, Is.EqualTo(Speed.Constant)); + Assert.That(wrapped.IndexOf(5), Is.EqualTo(2)); + Assert.That(wrapped.IsEmpty, Is.EqualTo(false)); + Assert.That(wrapped.IsReadOnly, Is.EqualTo(true)); + Assert.That(wrapped.IsSorted(), Is.EqualTo(false)); + Assert.That(wrapped.IsValid, Is.EqualTo(true)); + Assert.That(wrapped.Last, Is.EqualTo(5)); + Assert.That(wrapped.LastIndexOf(5), Is.EqualTo(2)); + Assert.That(wrapped.ListenableEvents, Is.EqualTo(EventType.None)); + }); string i2s(int i) { return string.Format("T{0}", i); } - Assert.AreEqual("[ 0:T4, 1:T6, 2:T5 ]", wrapped.Map(i2s).ToString()); - Assert.AreEqual(0, wrapped.Offset); + Assert.That(wrapped.Map(i2s).ToString(), Is.EqualTo("[ 0:T4, 1:T6, 2:T5 ]")); + Assert.That(wrapped.Offset, Is.EqualTo(0)); wrapped.Reverse(); - Assert.AreEqual("[ 0:5, 1:6, 2:4 ]", wrapped.ToString()); - IList other = new ArrayList(); other.AddAll(new int[] { 4, 5, 6 }); - Assert.IsFalse(wrapped.SequencedEquals(other)); + Assert.That(wrapped.ToString(), Is.EqualTo("[ 0:5, 1:6, 2:4 ]")); + IList other = new ArrayList(); other.AddAll([4, 5, 6]); + Assert.That(wrapped.SequencedEquals(other), Is.False); j = 30; - Assert.AreEqual(true, wrapped.Show(new System.Text.StringBuilder(), ref j, null)); + Assert.That(wrapped.Show(new System.Text.StringBuilder(), ref j, null), Is.EqualTo(true)); wrapped.Sort(); - Assert.AreEqual("[ 0:4, 1:5, 2:6 ]", wrapped.ToString()); - Assert.IsTrue(IC.Eq(wrapped.ToArray(), 4, 5, 6)); - Assert.AreEqual("[ ... ]", wrapped.ToString("L4", null)); - Assert.AreEqual(null, wrapped.Underlying); - Assert.IsTrue(IC.SetEq(wrapped.UniqueItems(), 4, 5, 6)); - Assert.IsTrue(wrapped.UnsequencedEquals(other)); + Assert.Multiple(() => + { + Assert.That(wrapped.ToString(), Is.EqualTo("[ 0:4, 1:5, 2:6 ]")); + Assert.That(IC.Eq(wrapped.ToArray(), 4, 5, 6), Is.True); + Assert.That(wrapped.ToString("L4", null), Is.EqualTo("[ ... ]")); + Assert.That(wrapped.Underlying, Is.EqualTo(null)); + Assert.That(IC.SetEq(wrapped.UniqueItems(), 4, 5, 6), Is.True); + Assert.That(wrapped.UnsequencedEquals(other), Is.True); + }); wrapped.Shuffle(); - Assert.IsTrue(IC.SetEq(wrapped.UniqueItems(), 4, 5, 6)); + Assert.That(IC.SetEq(wrapped.UniqueItems(), 4, 5, 6), Is.True); } [Test] public void WithExc() { - WrappedArray wrapped = new WrappedArray(new int[] { 3, 4, 6, 5, 7 }); + WrappedArray wrapped = new([3, 4, 6, 5, 7]); // try { wrapped.Add(1); Assert.Fail("No throw"); } catch (FixedSizeCollectionException) { } @@ -694,92 +725,120 @@ public void WithExc() [Test] public void View() { - int[] inner = new int[] { 3, 4, 6, 5, 7 }; - WrappedArray outerwrapped = new WrappedArray(inner); + int[] inner = [3, 4, 6, 5, 7]; + WrappedArray outerwrapped = new(inner); WrappedArray wrapped = (WrappedArray)outerwrapped.View(1, 3); - // - Assert.AreEqual(6, wrapped[1]); - Assert.IsTrue(IC.Eq(wrapped[1, 2], 6, 5)); + Assert.Multiple(() => + { + // + Assert.That(wrapped[1], Is.EqualTo(6)); + Assert.That(IC.Eq(wrapped[1, 2], 6, 5), Is.True); + }); // bool is4(int i) { return i == 4; } - Assert.AreEqual(EventType.None, wrapped.ActiveEvents); - Assert.AreEqual(false, wrapped.All(is4)); - Assert.AreEqual(true, wrapped.AllowsDuplicates); + + Assert.Multiple(() => + { + Assert.That(wrapped.ActiveEvents, Is.EqualTo(EventType.None)); + Assert.That(wrapped.All(is4), Is.EqualTo(false)); + Assert.That(wrapped.AllowsDuplicates, Is.EqualTo(true)); + }); wrapped.Apply(delegate (int i) { }); - Assert.AreEqual("{ 5, 6, 4 }", wrapped.Backwards().ToString()); - Assert.AreEqual(true, wrapped.Check()); + Assert.Multiple(() => + { + Assert.That(wrapped.Backwards().ToString(), Is.EqualTo("{ 5, 6, 4 }")); + Assert.That(wrapped.Check(), Is.EqualTo(true)); + }); wrapped.Choose(); - Assert.AreEqual(true, wrapped.Contains(4)); - Assert.AreEqual(true, wrapped.ContainsAll(new ArrayList())); - Assert.AreEqual(1, wrapped.ContainsCount(4)); - Assert.AreEqual(Speed.Linear, wrapped.ContainsSpeed); + Assert.Multiple(() => + { + Assert.That(wrapped.Contains(4), Is.EqualTo(true)); + Assert.That(wrapped.ContainsAll(new ArrayList()), Is.EqualTo(true)); + Assert.That(wrapped.ContainsCount(4), Is.EqualTo(1)); + Assert.That(wrapped.ContainsSpeed, Is.EqualTo(Speed.Linear)); + }); int[] extarray = new int[5]; wrapped.CopyTo(extarray, 1); - Assert.IsTrue(IC.Eq(extarray, 0, 4, 6, 5, 0)); - Assert.AreEqual(3, wrapped.Count); - Assert.AreEqual(Speed.Constant, wrapped.CountSpeed); - Assert.AreEqual(Direction.Forwards, wrapped.Direction); - Assert.AreEqual(false, wrapped.DuplicatesByCounting); - Assert.AreEqual(System.Collections.Generic.EqualityComparer.Default, wrapped.EqualityComparer); - Assert.AreEqual(true, wrapped.Exists(is4)); - Assert.IsTrue(IC.Eq(wrapped.Filter(is4), 4)); + Assert.Multiple(() => + { + Assert.That(IC.Eq(extarray, 0, 4, 6, 5, 0), Is.True); + Assert.That(wrapped, Has.Count.EqualTo(3)); + }); + Assert.Multiple(() => + { + Assert.That(wrapped.CountSpeed, Is.EqualTo(Speed.Constant)); + Assert.That(wrapped.Direction, Is.EqualTo(Direction.Forwards)); + Assert.That(wrapped.DuplicatesByCounting, Is.EqualTo(false)); + Assert.That(wrapped.EqualityComparer, Is.EqualTo(System.Collections.Generic.EqualityComparer.Default)); + Assert.That(wrapped.Exists(is4), Is.EqualTo(true)); + Assert.That(IC.Eq(wrapped.Filter(is4), 4), Is.True); + }); int j = 5; - Assert.AreEqual(true, wrapped.Find(ref j)); - Assert.AreEqual(true, wrapped.Find(is4, out j)); - Assert.AreEqual("[ 0:4 ]", wrapped.FindAll(is4).ToString()); - Assert.AreEqual(0, wrapped.FindIndex(is4)); - Assert.AreEqual(true, wrapped.FindLast(is4, out j)); - Assert.AreEqual(0, wrapped.FindLastIndex(is4)); - Assert.AreEqual(4, wrapped.First); + Assert.Multiple(() => + { + Assert.That(wrapped.Find(ref j), Is.EqualTo(true)); + Assert.That(wrapped.Find(is4, out j), Is.EqualTo(true)); + Assert.That(wrapped.FindAll(is4).ToString(), Is.EqualTo("[ 0:4 ]")); + Assert.That(wrapped.FindIndex(is4), Is.EqualTo(0)); + Assert.That(wrapped.FindLast(is4, out j), Is.EqualTo(true)); + Assert.That(wrapped.FindLastIndex(is4), Is.EqualTo(0)); + Assert.That(wrapped.First, Is.EqualTo(4)); + }); wrapped.GetEnumerator(); - Assert.AreEqual(CHC.SequencedHashCode(4, 6, 5), wrapped.GetSequencedHashCode()); - Assert.AreEqual(CHC.UnsequencedHashCode(4, 6, 5), wrapped.GetUnsequencedHashCode()); - Assert.AreEqual(Speed.Constant, wrapped.IndexingSpeed); - Assert.AreEqual(2, wrapped.IndexOf(5)); - Assert.AreEqual(false, wrapped.IsEmpty); - Assert.AreEqual(true, wrapped.IsReadOnly); - Assert.AreEqual(false, wrapped.IsSorted()); - Assert.AreEqual(true, wrapped.IsValid); - Assert.AreEqual(5, wrapped.Last); - Assert.AreEqual(2, wrapped.LastIndexOf(5)); - Assert.AreEqual(EventType.None, wrapped.ListenableEvents); + Assert.Multiple(() => + { + Assert.That(wrapped.GetSequencedHashCode(), Is.EqualTo(CHC.SequencedHashCode(4, 6, 5))); + Assert.That(wrapped.GetUnsequencedHashCode(), Is.EqualTo(CHC.UnsequencedHashCode(4, 6, 5))); + Assert.That(wrapped.IndexingSpeed, Is.EqualTo(Speed.Constant)); + Assert.That(wrapped.IndexOf(5), Is.EqualTo(2)); + Assert.That(wrapped.IsEmpty, Is.EqualTo(false)); + Assert.That(wrapped.IsReadOnly, Is.EqualTo(true)); + Assert.That(wrapped.IsSorted(), Is.EqualTo(false)); + Assert.That(wrapped.IsValid, Is.EqualTo(true)); + Assert.That(wrapped.Last, Is.EqualTo(5)); + Assert.That(wrapped.LastIndexOf(5), Is.EqualTo(2)); + Assert.That(wrapped.ListenableEvents, Is.EqualTo(EventType.None)); + }); string i2s(int i) { return string.Format("T{0}", i); } - Assert.AreEqual("[ 0:T4, 1:T6, 2:T5 ]", wrapped.Map(i2s).ToString()); - Assert.AreEqual(1, wrapped.Offset); + Assert.That(wrapped.Map(i2s).ToString(), Is.EqualTo("[ 0:T4, 1:T6, 2:T5 ]")); + Assert.That(wrapped.Offset, Is.EqualTo(1)); wrapped.Reverse(); - Assert.AreEqual("[ 0:5, 1:6, 2:4 ]", wrapped.ToString()); - IList other = new ArrayList(); other.AddAll(new int[] { 4, 5, 6 }); - Assert.IsFalse(wrapped.SequencedEquals(other)); + Assert.That(wrapped.ToString(), Is.EqualTo("[ 0:5, 1:6, 2:4 ]")); + IList other = new ArrayList(); other.AddAll([4, 5, 6]); + Assert.That(wrapped.SequencedEquals(other), Is.False); j = 30; - Assert.AreEqual(true, wrapped.Show(new System.Text.StringBuilder(), ref j, null)); + Assert.That(wrapped.Show(new System.Text.StringBuilder(), ref j, null), Is.EqualTo(true)); wrapped.Sort(); - Assert.AreEqual("[ 0:4, 1:5, 2:6 ]", wrapped.ToString()); - Assert.IsTrue(IC.Eq(wrapped.ToArray(), 4, 5, 6)); - Assert.AreEqual("[ ... ]", wrapped.ToString("L4", null)); - // TODO: Below line removed as NUnit 3.0 test fails trying to enumerate... - // Assert.AreEqual(outerwrapped, wrapped.Underlying); - Assert.IsTrue(IC.SetEq(wrapped.UniqueItems(), 4, 5, 6)); - Assert.IsTrue(wrapped.UnsequencedEquals(other)); - // - Assert.IsTrue(wrapped.TrySlide(1)); - Assert.IsTrue(IC.Eq(wrapped, 5, 6, 7)); - Assert.IsTrue(wrapped.TrySlide(-1, 2)); - Assert.IsTrue(IC.Eq(wrapped, 4, 5)); - Assert.IsFalse(wrapped.TrySlide(-2)); - Assert.IsTrue(IC.Eq(wrapped.Span(outerwrapped.ViewOf(7)), 4, 5, 6, 7)); + Assert.Multiple(() => + { + Assert.That(wrapped.ToString(), Is.EqualTo("[ 0:4, 1:5, 2:6 ]")); + Assert.That(IC.Eq(wrapped.ToArray(), 4, 5, 6), Is.True); + Assert.That(wrapped.ToString("L4", null), Is.EqualTo("[ ... ]")); + // TODO: Below line removed as NUnit 3.0 test fails trying to enumerate... + // Assert.AreEqual(outerwrapped, wrapped.Underlying); + Assert.That(IC.SetEq(wrapped.UniqueItems(), 4, 5, 6), Is.True); + Assert.That(wrapped.UnsequencedEquals(other), Is.True); + // + Assert.That(wrapped.TrySlide(1), Is.True); + Assert.That(IC.Eq(wrapped, 5, 6, 7), Is.True); + Assert.That(wrapped.TrySlide(-1, 2), Is.True); + Assert.That(IC.Eq(wrapped, 4, 5), Is.True); + Assert.That(wrapped.TrySlide(-2), Is.False); + Assert.That(IC.Eq(wrapped.Span(outerwrapped.ViewOf(7)), 4, 5, 6, 7), Is.True); + }); // wrapped.Shuffle(); - Assert.IsTrue(IC.SetEq(wrapped.UniqueItems(), 4, 5)); - Assert.IsTrue(wrapped.IsValid); + Assert.That(IC.SetEq(wrapped.UniqueItems(), 4, 5), Is.True); + Assert.That(wrapped.IsValid, Is.True); wrapped.Dispose(); - Assert.IsFalse(wrapped.IsValid); + Assert.That(wrapped.IsValid, Is.False); } [Test] public void ViewWithExc() { - int[] inner = new int[] { 3, 4, 6, 5, 7 }; - WrappedArray outerwrapped = new WrappedArray(inner); + int[] inner = [3, 4, 6, 5, 7]; + WrappedArray outerwrapped = new(inner); WrappedArray wrapped = (WrappedArray)outerwrapped.View(1, 3); // try { wrapped.Add(1); Assert.Fail("No throw"); } diff --git a/C5.UserGuideExamples/AnagramHashBag.cs b/C5.UserGuideExamples/AnagramHashBag.cs index 06f352b5..0f882634 100644 --- a/C5.UserGuideExamples/AnagramHashBag.cs +++ b/C5.UserGuideExamples/AnagramHashBag.cs @@ -43,20 +43,18 @@ private static SCG.IEnumerable ReadFileWords(string filename, int n) { var delimiter = new Regex("[^a-z���A-Z���0-9-]+"); - using (var reader = File.OpenText(filename)) + using var reader = File.OpenText(filename); + for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) { - for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) + foreach (var s in delimiter.Split(line)) { - foreach (var s in delimiter.Split(line)) + if (s != "") { - if (s != "") - { - yield return s.ToLower(); - } - if (--n == 0) - { - yield break; - } + yield return s.ToLower(); + } + if (--n == 0) + { + yield break; } } } diff --git a/C5.UserGuideExamples/AnagramStrings.cs b/C5.UserGuideExamples/AnagramStrings.cs index 0c8f11c9..f05013c2 100644 --- a/C5.UserGuideExamples/AnagramStrings.cs +++ b/C5.UserGuideExamples/AnagramStrings.cs @@ -40,16 +40,14 @@ private static void Main(string[] args) private static SCG.IEnumerable ReadFileWords(string filename) { var delimiter = new Regex("[^a-z���A-Z���0-9-]+"); - using (var reader = File.OpenText(filename)) + using var reader = File.OpenText(filename); + for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) { - for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) + foreach (var s in delimiter.Split(line)) { - foreach (var s in delimiter.Split(line)) + if (s != "") { - if (s != "") - { - yield return s.ToLower(); - } + yield return s.ToLower(); } } } @@ -71,7 +69,7 @@ private static CharBag AnagramClass(string s) var anagram = AnagramClass(s); if (!classes.Find(ref anagram, out HashSet anagramClass)) { - classes[anagram] = anagramClass = new HashSet(); + classes[anagram] = anagramClass = []; } anagramClass.Add(s); } @@ -110,8 +108,10 @@ public bool Equals(CharBag that) return _contents.Equals(that._contents); } - public int CompareTo(CharBag that) + public int CompareTo(CharBag? that) { + ArgumentNullException.ThrowIfNull(that); + return _contents.CompareTo(that._contents); } } diff --git a/C5.UserGuideExamples/AnagramTreeBag.cs b/C5.UserGuideExamples/AnagramTreeBag.cs index 95e88760..88cd39c7 100644 --- a/C5.UserGuideExamples/AnagramTreeBag.cs +++ b/C5.UserGuideExamples/AnagramTreeBag.cs @@ -43,20 +43,18 @@ public static SCG.IEnumerable ReadFileWords(string filename, int n) { var delimiter = new Regex("[^a-z���A-Z���0-9-]+"); - using (var reader = File.OpenText(filename)) + using var reader = File.OpenText(filename); + for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) { - for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) + foreach (string s in delimiter.Split(line)) { - foreach (string s in delimiter.Split(line)) + if (s != "") { - if (s != "") - { - yield return s.ToLower(); - } - if (--n == 0) - { - yield break; - } + yield return s.ToLower(); + } + if (--n == 0) + { + yield break; } } } diff --git a/C5.UserGuideExamples/Anagrams.cs b/C5.UserGuideExamples/Anagrams.cs index c676cef7..c8316173 100644 --- a/C5.UserGuideExamples/Anagrams.cs +++ b/C5.UserGuideExamples/Anagrams.cs @@ -43,20 +43,18 @@ private static SCG.IEnumerable ReadFileWords(string filename, int n) { var delimiter = new Regex("[^a-z���A-Z���0-9-]+"); - using (var reader = File.OpenText(filename)) + using var reader = File.OpenText(filename); + for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) { - for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) + foreach (var s in delimiter.Split(line)) { - foreach (var s in delimiter.Split(line)) + if (s != "") { - if (s != "") - { - yield return s.ToLower(); - } - if (--n == 0) - { - yield break; - } + yield return s.ToLower(); + } + if (--n == 0) + { + yield break; } } } diff --git a/C5.UserGuideExamples/AntiPatterns.cs b/C5.UserGuideExamples/AntiPatterns.cs index ad23b69b..8f7d389e 100644 --- a/C5.UserGuideExamples/AntiPatterns.cs +++ b/C5.UserGuideExamples/AntiPatterns.cs @@ -35,7 +35,7 @@ private static void ModifyInner() inner2 = new TreeSet(), inner3 = new TreeSet(); - inner1.AddAll(new[] { 2, 3, 5, 7, 11 }); + inner1.AddAll([2, 3, 5, 7, 11]); inner2.AddAll(inner1); inner2.Add(13); inner3.AddAll(inner1); @@ -72,7 +72,7 @@ private static void DontModifyInner() inner1 = new TreeSet(), inner2 = new TreeSet(), inner3 = new TreeSet(); - inner1.AddAll(new[] { 2, 3, 5, 7, 11 }); + inner1.AddAll([2, 3, 5, 7, 11]); inner2.AddAll(inner1); inner2.Add(13); inner3.AddAll(inner1); diff --git a/C5.UserGuideExamples/C5.UserGuideExamples.csproj b/C5.UserGuideExamples/C5.UserGuideExamples.csproj index 5508034c..d0331691 100644 --- a/C5.UserGuideExamples/C5.UserGuideExamples.csproj +++ b/C5.UserGuideExamples/C5.UserGuideExamples.csproj @@ -5,16 +5,6 @@ enable latest - - - - - - - - - - diff --git a/C5.UserGuideExamples/C5SerializationTest.cs b/C5.UserGuideExamples/C5SerializationTest.cs deleted file mode 100644 index 23cc789f..00000000 --- a/C5.UserGuideExamples/C5SerializationTest.cs +++ /dev/null @@ -1,77 +0,0 @@ -// This file is part of the C5 Generic Collection Library for C# and CLI -// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. - -namespace C5.UserGuideExamples; - -internal static class C5SerializationTest -{ - private static void Main() - { - // The following appear to serialize/deserialize just fine - var arrayList = new ArrayList { 1, 2, 3, 4 }; - arrayList.ToFileDCS("C5ArrayList.xml"); - var testC5ArrayList = FromFileDCS>("C5ArrayList.xml"); - // TODO: Assert content - - var arrayListOfArrayList = new ArrayList> { testC5ArrayList, testC5ArrayList }; - arrayListOfArrayList.ToFileDCS("C5ArrayListList.xml"); - - var testC5ArrayListOrArrayList = FromFileDCS>("C5ArrayList.xml"); - Console.WriteLine($"Identity preserved: {ReferenceEquals(arrayListOfArrayList[0], testC5ArrayListOrArrayList[1])}"); - - var linkedList = new LinkedList { 1, 2, 3, 4 }; - linkedList.ToFileXML("C5LinkedList.xml"); - _ = FromFileXML>("C5LinkedList.xml"); - // TODO: Assert content - - // The following only work using the DataContractSerializer SerializationExceptions: - new SortedArray { 1, 2, 3, 4 }.ToFileDCS("C5SortedArray.xml"); - _ = FromFileDCS>("C5SortedArray.xml"); - new HashBag { 1, 2, 3, 4 }.ToFileDCS("C5HashBag.xml"); - _ = FromFileDCS>("C5HashBag.xml"); - new HashSet { 1, 2, 3, 4 }.ToFileDCS("C5HashSet.xml"); - _ = FromFileDCS>("C5HashSet.xml"); - - // The following System.Collections.Generic.Dictionary serializes... - new SCG.Dictionary { { 1, 1f }, { 2, 2f }, { 3, 3f }, { 4, 4f } }.ToFileDCS("Dictionary.xml"); - _ = FromFileDCS>("Dictionary.xml"); - - // ...but the C5.HashDictionary or C5.TreeDictionary do not. - new HashDictionary { { 1, 1f }, { 2, 2f }, { 3, 3f }, { 4, 4f } }.ToFileDCS("C5HashDictionary.xml"); - _ = FromFileDCS>("C5HashDictionary.xml"); - new TreeDictionary { { 1, 1f }, { 2, 2f }, { 3, 3f }, { 4, 4f } }.ToFileDCS("C5TreeDictionary.xml"); - _ = FromFileDCS>("C5TreeDictionary.xml"); - } - - public static T FromFileXML(string filename) - { - using (Stream stream = File.OpenRead(Path.GetFullPath(filename))) - { - return (T)new XmlSerializer(typeof(T)).Deserialize(stream); - } - } - - public static void ToFileXML(this T myObject, string filename) - { - using (Stream stream = File.Create(Path.GetFullPath(filename))) - { - new XmlSerializer(typeof(T)).Serialize(stream, myObject); - } - } - - public static T FromFileDCS(string filename) - { - using (Stream stream = File.OpenRead(Path.GetFullPath(filename))) - { - return (T)new DataContractSerializer(typeof(T)).ReadObject(stream); - } - } - - public static void ToFileDCS(this T myObject, string filename) - { - using (Stream stream = File.Create(Path.GetFullPath(filename))) - { - new DataContractSerializer(typeof(T)).WriteObject(stream, myObject); - } - } -} diff --git a/C5.UserGuideExamples/CharBags.cs b/C5.UserGuideExamples/CharBags.cs deleted file mode 100644 index 8cfbab1a..00000000 --- a/C5.UserGuideExamples/CharBags.cs +++ /dev/null @@ -1,50 +0,0 @@ -// This file is part of the C5 Generic Collection Library for C# and CLI -// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. - -// C5 example 2004-09-01 - -namespace C5.UserGuideExamples; - -class CharBags -{ - private static readonly IHasher> sequencedTreeBagHasher = new C5.HasherBuilder.SequencedHasher, char>(); - private static readonly IHasher> unsequencedTreeBagHasher = new C5.HasherBuilder.UnsequencedHasher, char>(); - private static readonly IHasher> unsequencedHashBagHasher = new C5.HasherBuilder.UnsequencedHasher, char>(); - - public static void Main(string[] args) - { - } - - public static void FindCollisions(SCG.IEnumerable ss) - { - var occurrences = new HashBag(); - foreach (string s in ss) - { - var tb = TreeBag(s); - // HashBag hb = HashBag(s); - occurrences.Add(sequencedTreeBagHasher.GetHashCode(tb)); - // unsequencedTreeBagHasher.GetHashCode(tb); - // unsequencedHashBagHasher.GetHashCode(hb); - } - } - - public static TreeBag TreeBag(string s) - { - var anagram = new TreeBag(); - foreach (char c in s) - { - anagram.Add(c); - } - return anagram; - } - - public static HashBag HashBag(string s) - { - var anagram = new HashBag(); - foreach (char c in s) - { - anagram.Add(c); - } - return anagram; - } -} diff --git a/C5.UserGuideExamples/CollectionCollection.cs b/C5.UserGuideExamples/CollectionCollection.cs index 478ad6fb..e319c581 100644 --- a/C5.UserGuideExamples/CollectionCollection.cs +++ b/C5.UserGuideExamples/CollectionCollection.cs @@ -20,9 +20,9 @@ public static void Main() public static void ListEqualityComparers() { - _col1.AddAll(new[] { 7, 9, 13 }); - _col2.AddAll(new[] { 7, 9, 13 }); - _col3.AddAll(new[] { 9, 7, 13 }); + _col1.AddAll([7, 9, 13]); + _col2.AddAll([7, 9, 13]); + _col3.AddAll([9, 7, 13]); // Default equality and hasher == sequenced equality and hasher var hs1 = new HashSet>(); @@ -56,7 +56,7 @@ public static void Equalities(string msg, SCG.IEqualityComparer> equa public static void IntSetSet() { var outer = new HashSet>(); - int[] ss = { 2, 3, 5, 7 }; + int[] ss = [2, 3, 5, 7]; var inner = new TreeSet(); outer.Add(inner.Snapshot()); diff --git a/C5.UserGuideExamples/CollectionSanity.cs b/C5.UserGuideExamples/CollectionSanity.cs index 03a743d8..8de70d16 100644 --- a/C5.UserGuideExamples/CollectionSanity.cs +++ b/C5.UserGuideExamples/CollectionSanity.cs @@ -12,12 +12,12 @@ public static void Main() var col1 = new LinkedList(); var col2 = new LinkedList(); var col3 = new LinkedList(); - col1.AddAll(new[] { 7, 9, 13 }); - col2.AddAll(new[] { 7, 9, 13 }); - col3.AddAll(new[] { 9, 7, 13 }); + col1.AddAll([7, 9, 13]); + col2.AddAll([7, 9, 13]); + col3.AddAll([9, 7, 13]); - HashSet> hs1 = new HashSet> - { + HashSet> hs1 = new() + { col1, col2, col3 diff --git a/C5.UserGuideExamples/DistinctBag.cs b/C5.UserGuideExamples/DistinctBag.cs index 2a4c1c43..6e0100b7 100644 --- a/C5.UserGuideExamples/DistinctBag.cs +++ b/C5.UserGuideExamples/DistinctBag.cs @@ -27,7 +27,8 @@ internal class DistinctBagProgram { private static void Main() { - var nameColl = new DistinctHashBag(new PersonDistinctBag.NameEqualityComparer()); + var nameEqualityComparer = ComparerFactory.CreateEqualityComparer((a, b) => StringComparer.InvariantCultureIgnoreCase.Equals(a.Name, b.Name), a => a.Name.GetHashCode()); + var nameColl = new DistinctHashBag(nameEqualityComparer); var p1 = new PersonDistinctBag("Peter", 19620625); var p2 = new PersonDistinctBag("Carsten", 19640627); var p3 = new PersonDistinctBag("Carsten", 19640628); @@ -97,39 +98,10 @@ public override string ToString() } } -public class PersonDistinctBag +public class PersonDistinctBag(string name, int date) { - private string Name { get; } - private int Date { get; } + public string Name { get; } = name; + public int Date { get; } = date; - public PersonDistinctBag(string name, int date) - { - Name = name; - Date = date; - } - - public class NameEqualityComparer : SCG.IEqualityComparer - { - public bool Equals(PersonDistinctBag p1, PersonDistinctBag p2) - { - return p1.Name == p2.Name; - } - public int GetHashCode(PersonDistinctBag p) - { - return p.Name.GetHashCode(); - } - } - - public class DateComparer : SCG.IComparer - { - public int Compare(PersonDistinctBag p1, PersonDistinctBag p2) - { - return p1.Date.CompareTo(p2.Date); - } - } - - public override string ToString() - { - return $"{Name} ({Date})"; - } + public override string ToString() => $"{Name} ({Date})"; } diff --git a/C5.UserGuideExamples/EventPatterns.cs b/C5.UserGuideExamples/EventPatterns.cs index 45c6d01e..5f0ae534 100644 --- a/C5.UserGuideExamples/EventPatterns.cs +++ b/C5.UserGuideExamples/EventPatterns.cs @@ -20,7 +20,7 @@ public static void UnindexedCollectionEvents() { ICollection coll = new ArrayList(); ICollection bag1 = new HashBag(); - bag1.AddAll(new[] { 3, 2, 5, 5, 7, 7, 5, 3, 7, 7 }); + bag1.AddAll([3, 2, 5, 5, 7, 7, 5, 3, 7, 7]); // Add change handler coll.CollectionChanged += o => Console.WriteLine("Collection changed"); @@ -35,7 +35,7 @@ public static void UnindexedCollectionEvents() AddItemsRemovedCounter(coll); coll.AddAll(bag1); - coll.RemoveAll(new[] { 2, 5, 6, 3, 7, 2 }); + coll.RemoveAll([2, 5, 6, 3, 7, 2]); coll.Clear(); ICollection bag2 = new HashBag(); @@ -87,7 +87,7 @@ public static void IndexedCollectionEvents() { var coll = new ArrayList(); var bag = new HashBag(); - bag.AddAll(new[] { 3, 2, 5, 5, 7, 7, 5, 3, 7, 7 }); + bag.AddAll([3, 2, 5, 5, 7, 7, 5, 3, 7, 7]); // Add item inserted handler coll.ItemInserted += (o, args) => Console.WriteLine($"Item {args.Item} inserted at {args.Index}"); @@ -159,7 +159,7 @@ public static void UpdateEvent() coll.Add(new Teacher("Jens", "physics")); // The update handler is activated also by indexed updates var list = new ArrayList(); - list.AddAll(new[] { 7, 11, 13 }); + list.AddAll([7, 11, 13]); AddItemUpdatedHandler(list); list[1] = 9; } diff --git a/C5.UserGuideExamples/Extensions.cs b/C5.UserGuideExamples/Extensions.cs index d822f2ff..ee14c188 100644 --- a/C5.UserGuideExamples/Extensions.cs +++ b/C5.UserGuideExamples/Extensions.cs @@ -31,8 +31,8 @@ private static void Main() { var hs = new HashSet { - new NamedPerson("Ole"), - new NamedPerson("Hans") + new("Ole"), + new("Hans") }; foreach (NamedPerson q in (from p in hs where p.Name.Length == 4 select p)) diff --git a/C5.UserGuideExamples/GCHForm.cs b/C5.UserGuideExamples/GCHForm.cs deleted file mode 100644 index b3243747..00000000 --- a/C5.UserGuideExamples/GCHForm.cs +++ /dev/null @@ -1,252 +0,0 @@ -// This file is part of the C5 Generic Collection Library for C# and CLI -// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. - -using System; -using System.Drawing; -using System.Collections; -using System.ComponentModel; -using System.Windows.Forms; -using System.Diagnostics; -using C5; - -namespace GConvexHull; - -/// -/// Summary description for Form1. -/// -public class TesterForm : System.Windows.Forms.Form -{ - //My data - - //My GUI stuff - private System.Windows.Forms.Panel drawarea; - - private Graphics drawg; - - //Std stuff - private System.Windows.Forms.Button runButton; - private TextBox pointCount; - - /// - /// Required designer variable. - /// - private System.ComponentModel.Container components = null; - - - public TesterForm() - { - // - // Required for Windows Form Designer support - // - InitializeComponent(); - - // - // TODO: Add any constructor code after InitializeComponent call - // - drawg = drawarea.CreateGraphics(); - reset(); - } - - - /// - /// Clean up any resources being used. - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - if (components != null) - { - components.Dispose(); - } - } - - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.drawarea = new System.Windows.Forms.Panel(); - this.runButton = new System.Windows.Forms.Button(); - this.pointCount = new System.Windows.Forms.TextBox(); - this.SuspendLayout(); - // - // drawarea - // - this.drawarea.BackColor = System.Drawing.Color.White; - this.drawarea.Location = new System.Drawing.Point(8, 9); - this.drawarea.Name = "drawarea"; - this.drawarea.Size = new System.Drawing.Size(500, 500); - this.drawarea.TabIndex = 0; - this.drawarea.Paint += new System.Windows.Forms.PaintEventHandler(this.drawarea_Paint); - this.drawarea.Invalidated += new System.Windows.Forms.InvalidateEventHandler(this.drawarea_Invalidated); - this.drawarea.MouseMove += new System.Windows.Forms.MouseEventHandler(this.drawarea_MouseMove); - this.drawarea.MouseClick += new System.Windows.Forms.MouseEventHandler(this.drawarea_MouseClick); - // - // runButton - // - this.runButton.Location = new System.Drawing.Point(8, 516); - this.runButton.Name = "runButton"; - this.runButton.Size = new System.Drawing.Size(42, 20); - this.runButton.TabIndex = 1; - this.runButton.Text = "Run"; - this.runButton.Click += new System.EventHandler(this.runButton_Click); - // - // pointCount - // - this.pointCount.Location = new System.Drawing.Point(97, 517); - this.pointCount.Name = "pointCount"; - this.pointCount.Size = new System.Drawing.Size(55, 20); - this.pointCount.TabIndex = 5; - // - // TesterForm - // - this.ClientSize = new System.Drawing.Size(524, 550); - this.Controls.Add(this.pointCount); - this.Controls.Add(this.runButton); - this.Controls.Add(this.drawarea); - this.Name = "TesterForm"; - this.Text = "C5 Tester"; - this.Load += new System.EventHandler(this.TesterForm_Load); - this.ResumeLayout(false); - this.PerformLayout(); - - } - #endregion - - /// - /// The main entry point for the application. - /// - [STAThread] - static void Main() - { - Application.EnableVisualStyles(); - Application.Run(new TesterForm()); - } - - Point[] pts; - Point[] chpts; - - private void runButton_Click(object sender, System.EventArgs e) - { - int N = int.Parse(pointCount.Text); - pts = new Point[N]; - for (int i = 0; i < N; i++) - pts[i] = Point.Random(500, 500); - chpts = Convexhull.ConvexHull(pts); - - drawarea.Invalidate(); - } - - - private void drawarea_Paint(object sender, System.Windows.Forms.PaintEventArgs e) - { - mydraw(); - } - - - private void resetButton_Click(object sender, System.EventArgs e) - { - reset(); - } - - - private void reset() - { - drawarea.Invalidate();//(new Rectangle(0, 0, 40, 40)); - } - - - - public void mydraw() - { - if (pts == null) - { - return; - } - for (int i = 0; i < pts.Length; i++) - { - Point p = pts[i]; - drawg.DrawEllipse(new Pen(Color.Red), transx(p.x) - 2, transy(p.y) - 2, 4, 4); - } - for (int i = 0; i < chpts.Length; i++) - { - int j = i + 1 < chpts.Length ? i + 1 : 0; - drawg.DrawEllipse(new Pen(Color.Blue), transx(chpts[i].x) - 2, transy(chpts[i].y) - 2, 4, 4); - drawg.DrawLine(new Pen(Color.LawnGreen), transx(chpts[i].x), transx(chpts[i].y), transx(chpts[j].x), transx(chpts[j].y)); - } - } - - - - private int transx(double x) - { - return (int)x; - } - - - private int transy(double y) - { - return (int)y; - } - - - private void dumpButton_Click(object sender, System.EventArgs e) - { - Debug.WriteLine("###############"); - Debug.WriteLine("###############"); - } - - - private void graphTypeControlArray_Click(object sender, System.EventArgs e) - { - Debug.WriteLine(e.GetType()); - Debug.WriteLine(sender.GetType()); - drawarea.Invalidate(); - } - - - private void drawarea_MouseMove(object sender, MouseEventArgs e) - { - } - - - private void drawarea_MouseClick(object sender, MouseEventArgs e) - { - //double x = untransx(e.X), y = untransy(e.Y); - - } - - - private void drawarea_Invalidated(object sender, InvalidateEventArgs e) - { - //msg.Text = e.InvalidRect + ""; - //mydraw(); - } - - - private void preparedFigureSelection_SelectedIndexChanged(object sender, System.EventArgs e) - { - } - - private void voronoiButton_CheckedChanged(object sender, EventArgs e) - { - graphTypeControlArray_Click(sender, e); - } - - private void delaunayButton_CheckedChanged(object sender, EventArgs e) - { - graphTypeControlArray_Click(sender, e); - } - - private void TesterForm_Load(object sender, EventArgs e) - { - - } - -} diff --git a/C5.UserGuideExamples/GCHForm.resources b/C5.UserGuideExamples/GCHForm.resources deleted file mode 100644 index 6c05a977..00000000 Binary files a/C5.UserGuideExamples/GCHForm.resources and /dev/null differ diff --git a/C5.UserGuideExamples/GCHForm.resx b/C5.UserGuideExamples/GCHForm.resx deleted file mode 100644 index 040cde7e..00000000 --- a/C5.UserGuideExamples/GCHForm.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 25 - - \ No newline at end of file diff --git a/C5.UserGuideExamples/GConvexHull.cs b/C5.UserGuideExamples/GConvexHull.cs index c9830a6f..3efc9cf6 100644 --- a/C5.UserGuideExamples/GConvexHull.cs +++ b/C5.UserGuideExamples/GConvexHull.cs @@ -86,7 +86,7 @@ public static void Eliminate(IList lst) // Points in the plane public class Point : IComparable { - private static readonly C5Random rnd = new C5Random(42); + private static readonly C5Random rnd = new(42); public double X { get; } public double Y { get; } diff --git a/C5.UserGuideExamples/GNfaToDfa.cs b/C5.UserGuideExamples/GNfaToDfa.cs index 45125a6a..1bc1028a 100644 --- a/C5.UserGuideExamples/GNfaToDfa.cs +++ b/C5.UserGuideExamples/GNfaToDfa.cs @@ -299,34 +299,32 @@ public int Next() // http://www.research.att.com/sw/tools/graphviz/ public void WriteDot(string filename) { - using (var writer = new StreamWriter(new FileStream(filename, FileMode.Create, FileAccess.Write))) + using var writer = new StreamWriter(new FileStream(filename, FileMode.Create, FileAccess.Write)); + writer.WriteLine("// Format this file as a Postscript file with "); + writer.WriteLine("// dot " + filename + " -Tps -o out.ps\n"); + writer.WriteLine("digraph nfa {"); + writer.WriteLine("size=\"11,8.25\";"); + writer.WriteLine("rotate=90;"); + writer.WriteLine("rankdir=LR;"); + writer.WriteLine("start [style=invis];"); // Invisible start node + writer.WriteLine("start -> d" + Start); // Edge into start state + + // The accept state has a double circle + writer.WriteLine("d" + Exit + " [peripheries=2];"); + + // The transitions + foreach (var entry in Trans) { - writer.WriteLine("// Format this file as a Postscript file with "); - writer.WriteLine("// dot " + filename + " -Tps -o out.ps\n"); - writer.WriteLine("digraph nfa {"); - writer.WriteLine("size=\"11,8.25\";"); - writer.WriteLine("rotate=90;"); - writer.WriteLine("rankdir=LR;"); - writer.WriteLine("start [style=invis];"); // Invisible start node - writer.WriteLine("start -> d" + Start); // Edge into start state - - // The accept state has a double circle - writer.WriteLine("d" + Exit + " [peripheries=2];"); - - // The transitions - foreach (var entry in Trans) + var s1 = entry.Key; + for (var i = 0; i < entry.Value.Count; i++) { - var s1 = entry.Key; - for (var i = 0; i < entry.Value.Count; i++) - { - var s1Trans = entry.Value[i]; - var lab = s1Trans.Lab ?? "eps"; - var s2 = s1Trans.Target; - writer.WriteLine("d" + s1 + " -> d" + s2 + " [label=\"" + lab + "\"];"); - } + var s1Trans = entry.Value[i]; + var lab = s1Trans.Lab ?? "eps"; + var s2 = s1Trans.Target; + writer.WriteLine("d" + s1 + " -> d" + s2 + " [label=\"" + lab + "\"];"); } - writer.WriteLine("}"); } + writer.WriteLine("}"); } } @@ -378,39 +376,37 @@ public override string ToString() // http://www.research.att.com/sw/tools/graphviz/ public void WriteDot(string filename) { - using (var writer = new StreamWriter(new FileStream(filename, FileMode.Create, FileAccess.Write))) + using var writer = new StreamWriter(new FileStream(filename, FileMode.Create, FileAccess.Write)); + writer.WriteLine("// Format this file as a Postscript file with "); + writer.WriteLine("// dot " + filename + " -Tps -o out.ps\n"); + writer.WriteLine("digraph dfa {"); + writer.WriteLine("size=\"11,8.25\";"); + writer.WriteLine("rotate=90;"); + writer.WriteLine("rankdir=LR;"); + writer.WriteLine("start [style=invis];"); // Invisible start node + writer.WriteLine("start -> d" + Start); // Edge into start state + + // Accept states are double circles + foreach (var state in Trans.Keys) { - writer.WriteLine("// Format this file as a Postscript file with "); - writer.WriteLine("// dot " + filename + " -Tps -o out.ps\n"); - writer.WriteLine("digraph dfa {"); - writer.WriteLine("size=\"11,8.25\";"); - writer.WriteLine("rotate=90;"); - writer.WriteLine("rankdir=LR;"); - writer.WriteLine("start [style=invis];"); // Invisible start node - writer.WriteLine("start -> d" + Start); // Edge into start state - - // Accept states are double circles - foreach (var state in Trans.Keys) + if (Accept.Contains(state)) { - if (Accept.Contains(state)) - { - writer.WriteLine("d" + state + " [peripheries=2];"); - } + writer.WriteLine("d" + state + " [peripheries=2];"); } + } - // The transitions - foreach (var entry in Trans) + // The transitions + foreach (var entry in Trans) + { + var s1 = entry.Key; + foreach (var s1Trans in entry.Value) { - var s1 = entry.Key; - foreach (var s1Trans in entry.Value) - { - var lab = s1Trans.Key; - var s2 = s1Trans.Value; - writer.WriteLine($"d{s1} -> d{s2} [label=\"{lab}\"];"); - } + var lab = s1Trans.Key; + var s2 = s1Trans.Value; + writer.WriteLine($"d{s1} -> d{s2} [label=\"{lab}\"];"); } - writer.WriteLine("}"); } + writer.WriteLine("}"); } } diff --git a/C5.UserGuideExamples/Graph.cs b/C5.UserGuideExamples/Graph.cs index 89979416..41af878e 100644 --- a/C5.UserGuideExamples/Graph.cs +++ b/C5.UserGuideExamples/Graph.cs @@ -726,7 +726,7 @@ public int ComponentCount public ICollectionValue>> Components() { - ArrayList>> retval = new ArrayList>>(); + ArrayList>> retval = new(); HashGraph component; ArrayList vertices = null; void edgeaction(Edge e) @@ -842,7 +842,7 @@ void visit(V v, V parent, bool atRoot) foreach (System.Collections.Generic.KeyValuePair p in adjacent) { V end = p.Key; - Edge e = new Edge(v, end, p.Value); + Edge e = new(v, end, p.Value); if (!seen.FindOrAdd(ref end)) { onfollow(e); @@ -1233,7 +1233,7 @@ public IDirectedCollectionValue ApproximateTSP2() var fakeid = 1; foreach (Edge e in matching) { - Vplus fakevertex = new Vplus(fakeid++); + Vplus fakevertex = new(fakeid++); fused.AddEdge(new Vplus(e.Start), fakevertex, e.EdgeData); fused.AddEdge(fakevertex, new Vplus(e.End), e.EdgeData); } @@ -1363,7 +1363,7 @@ internal class UsedByAttribute : Attribute public override string ToString() { - System.Text.StringBuilder sb = new System.Text.StringBuilder(); + System.Text.StringBuilder sb = new(); for (int i = 0; i < tests.Length; i++) { if (i > 0) @@ -1394,7 +1394,7 @@ internal class Graph { private static SCG.IEnumerable> Grid(int n) { - Random ran = new Random(1717); + Random ran = new(1717); for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) @@ -1531,7 +1531,7 @@ public static void TestCOMP() //TODO: remove? public static void Test3() { - HashGraph g = new HashGraph(new CountWeight(), Grid(5)); + HashGraph g = new(new CountWeight(), Grid(5)); g.Print(Console.Out); //EdgeWeight weight = delegate(int i) { return i; }; Console.WriteLine("========= PFS accum ========="); @@ -1629,7 +1629,7 @@ public static void TestTSP() [ExampleDescription("Approximate TSP2")] public static void TestTSP2() { - HashGraph g = new HashGraph(new DoubleWeight(), Wheel(true, 20)); + HashGraph g = new(new DoubleWeight(), Wheel(true, 20)); foreach (string s in g.ApproximateTSP2()) { @@ -1695,7 +1695,7 @@ public static void TestTSP2() /// public static void TestEuler() { - HashGraph g = new HashGraph(new DoubleWeight(), Wheel(true, 6)); + HashGraph g = new(new DoubleWeight(), Wheel(true, 6)); foreach (string s in g.EulerTour()) { Console.Write(s + " "); @@ -1729,7 +1729,7 @@ public static void TestEuler() [ExampleDescription("Using the advanced DFS to compute articulation points")] public static void TestDFS() { - HashGraph g = new HashGraph(new IntWeight()); + HashGraph g = new(new IntWeight()); g.AddEdge("A", "B", 0); g.AddEdge("A", "E", 0); g.AddEdge("B", "E", 0); @@ -1742,7 +1742,7 @@ public static void TestDFS() g.AddEdge("C", "G", 0); g.AddEdge("F", "G", 0); - HashDictionary index = new HashDictionary(); + HashDictionary index = new(); int[] leastIndexReachableFrom = new int[g.VertexCount]; int nextindex = 0; int outgoingFromRoot = 0; diff --git a/C5.UserGuideExamples/HashCodes.cs b/C5.UserGuideExamples/HashCodes.cs index 428c87d1..62c5e7ba 100644 --- a/C5.UserGuideExamples/HashCodes.cs +++ b/C5.UserGuideExamples/HashCodes.cs @@ -36,7 +36,7 @@ public static void Main(string[] args) } } - private static readonly C5Random rnd = new C5Random(); + private static readonly C5Random rnd = new(); public static HashSet MakeRandom(int count, SCG.IEqualityComparer eqc) { diff --git a/C5.UserGuideExamples/IndexedObjects.cs b/C5.UserGuideExamples/IndexedObjects.cs index 99afe8b7..935970d4 100644 --- a/C5.UserGuideExamples/IndexedObjects.cs +++ b/C5.UserGuideExamples/IndexedObjects.cs @@ -58,7 +58,7 @@ private static void Main() } private static readonly string[] _months = - { + [ "Jan", "Feb", "Mar", @@ -71,7 +71,7 @@ private static void Main() "Oct", "Nov", "Dec" - }; + ]; } public interface IIndexer diff --git a/C5.UserGuideExamples/IndexedObjects2.cs b/C5.UserGuideExamples/IndexedObjects2.cs index 193ab19b..dc8b6c81 100644 --- a/C5.UserGuideExamples/IndexedObjects2.cs +++ b/C5.UserGuideExamples/IndexedObjects2.cs @@ -194,7 +194,7 @@ public class PersonIndexedObjects2 public static readonly IIndex NameIndex = new HashIndex(p => p.Name); public static readonly IIndex YearIndex = new HashIndex(p => p.Date / 10000); public static readonly IIndex DayIndex = new HashIndex(p => p.Date % 100); - public static readonly TreeIndex MonthIndex = new TreeIndex(p => (Month)(p.Date / 100 % 100)); + public static readonly TreeIndex MonthIndex = new(p => (Month)(p.Date / 100 % 100)); // Defining and initializing the indexing delegate private static event Action Index; diff --git a/C5.UserGuideExamples/KeywordRecognition.cs b/C5.UserGuideExamples/KeywordRecognition.cs index 1d53447a..fcf50f27 100644 --- a/C5.UserGuideExamples/KeywordRecognition.cs +++ b/C5.UserGuideExamples/KeywordRecognition.cs @@ -9,7 +9,7 @@ internal class KeywordRecognition { // Array of 77 keywords: private static readonly string[] _keywordArray = - { + [ "abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", @@ -21,7 +21,7 @@ internal class KeywordRecognition "stackalloc", "static", "string", "struct", "switch", "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void", "volatile", "while" - }; + ]; private static readonly ICollection _keywords1; diff --git a/C5.UserGuideExamples/ListenableEvents.cs b/C5.UserGuideExamples/ListenableEvents.cs index 157dde81..04016ef8 100644 --- a/C5.UserGuideExamples/ListenableEvents.cs +++ b/C5.UserGuideExamples/ListenableEvents.cs @@ -15,7 +15,7 @@ public static void Main() PrintEvents("HashedArrayList", new HashedArrayList()); PrintEvents("HashedLinkedList", new HashedLinkedList()); PrintEvents("SortedArray", new SortedArray()); - PrintEvents("WrappedArray", new WrappedArray(new int[0])); + PrintEvents("WrappedArray", new WrappedArray([])); PrintEvents("TreeSet", new TreeSet()); PrintEvents("TreeBag", new TreeBag()); PrintEvents("HashSet", new HashSet()); diff --git a/C5.UserGuideExamples/Locking.cs b/C5.UserGuideExamples/Locking.cs index 3a2916f4..009b1fd3 100644 --- a/C5.UserGuideExamples/Locking.cs +++ b/C5.UserGuideExamples/Locking.cs @@ -7,7 +7,7 @@ namespace C5.UserGuideExamples { internal class Locking { - private static ArrayList _collection = new ArrayList(); + private static ArrayList _collection = new(); private static readonly int _count = 1000; public static void Main() @@ -81,7 +81,7 @@ public static void AddAndRemove(int count) } } - private static readonly object _lock = new object(); + private static readonly object _lock = new(); public static void SafeAddAndRemove(int count) { diff --git a/C5.UserGuideExamples/MultiCollection.cs b/C5.UserGuideExamples/MultiCollection.cs index 68930494..57486f36 100644 --- a/C5.UserGuideExamples/MultiCollection.cs +++ b/C5.UserGuideExamples/MultiCollection.cs @@ -49,7 +49,7 @@ internal class BasicMultiCollection : IMultiCollection//: IDic where W : ICollection, new() where U : IDictionary, new() { - private readonly U _dictionary = new U(); + private readonly U _dictionary = new(); public SCG.IEqualityComparer KeyEqualityComparer => EqualityComparer.Default; diff --git a/C5.UserGuideExamples/MultiDictionary.cs b/C5.UserGuideExamples/MultiDictionary.cs index e0b28cea..c64b5d15 100644 --- a/C5.UserGuideExamples/MultiDictionary.cs +++ b/C5.UserGuideExamples/MultiDictionary.cs @@ -231,7 +231,7 @@ public static void Run() } { MultiHashDictionary> mdict - = new MultiHashDictionary> + = new() { { 2, "to" }, { 2, "deux" }, @@ -248,8 +248,8 @@ MultiHashDictionary> mdict mdict.Remove(20, "twenty"); Console.WriteLine(mdict); Console.WriteLine("mdict.Count is {0}", mdict.Count); - HashSet zwei = new HashSet - { + HashSet zwei = new() + { "zwei" }; mdict[2] = zwei; @@ -259,7 +259,7 @@ MultiHashDictionary> mdict zwei.Add("kaksi"); Console.WriteLine(mdict); Console.WriteLine("mdict.Count is {0}", mdict.Count); - HashSet empty = new HashSet(); + HashSet empty = new(); mdict[0] = empty; Console.WriteLine(mdict); Console.WriteLine("mdict.Count is {0}", mdict.Count); diff --git a/C5.UserGuideExamples/MultiDictionary2.cs b/C5.UserGuideExamples/MultiDictionary2.cs index ec39f0fc..06fc1342 100644 --- a/C5.UserGuideExamples/MultiDictionary2.cs +++ b/C5.UserGuideExamples/MultiDictionary2.cs @@ -13,7 +13,7 @@ public class MultiDictionary2 { public static void Main() { - MultiHashDictionary mdict = new MultiHashDictionary + MultiHashDictionary mdict = new() { { 2, "to" }, { 2, "deux" }, @@ -31,7 +31,7 @@ public static void Main() mdict.Remove(20, "twenty"); Console.WriteLine(mdict); Console.WriteLine("mdict.Count is {0}", mdict.Count); - Inner zwei = new Inner + Inner zwei = new() { "zwei" }; @@ -42,7 +42,7 @@ public static void Main() zwei.Add("kaksi"); Console.WriteLine(mdict); Console.WriteLine("mdict.Count is {0}", mdict.Count); - Inner empty = new Inner(); + Inner empty = new(); mdict[0] = empty; Console.WriteLine(mdict); Console.WriteLine("mdict.Count is {0}", mdict.Count); diff --git a/C5.UserGuideExamples/PointLocation.cs b/C5.UserGuideExamples/PointLocation.cs index 6c498ba1..00d46946 100644 --- a/C5.UserGuideExamples/PointLocation.cs +++ b/C5.UserGuideExamples/PointLocation.cs @@ -210,9 +210,9 @@ public void Build() //htree.Clear(); htree = new TreeDictionary>>(); - TreeSet> vtree = new TreeSet>(); + TreeSet> vtree = new(); - htree[Double.NegativeInfinity] = (ISorted>)(vtree.Snapshot()); + htree[double.NegativeInfinity] = (ISorted>)(vtree.Snapshot()); foreach (System.Collections.Generic.KeyValuePair>, LinkedList>>> p in endpoints) { @@ -265,7 +265,7 @@ public bool Place(double x, double y, out T cell) //if (DoubleComparer.StaticCompare(cell.key,x)==0) //Just note it, we have thrown away the vertical edges! - PointComparer c = new PointComparer(x, y); + PointComparer c = new(x, y); //Return value true here means we are at an edge. //But note that if x is in htree.Keys, we may be at a @@ -297,7 +297,7 @@ public void Place(double x, double y, out T upper, out bool hval, out T lower, o //if (DoubleComparer.StaticCompare(cell.key,x)==0) //Just note it, we have thrown away the vertical edges! - PointComparer c = new PointComparer(x, y); + PointComparer c = new(x, y); //Return value true here means we are at an edge. //But note that if x is in htree.Keys, we may be at a @@ -482,7 +482,7 @@ public double Traverse() public bool LookUp(int count, int seed) { - Random random = new Random(seed); + Random random = new(seed); bool res = false; for (int i = 0; i < count; i++) @@ -684,7 +684,7 @@ public double Traverse() public bool LookUp(int count, int seed) { - Random random = new Random(seed); + Random random = new(seed); bool res = false; for (int i = 0; i < count; i++) @@ -702,7 +702,7 @@ public static void Run() int repeats = 2; int lookups = 50000; Console.WriteLine("TestLattice Run({0}), means over {1} repeats:", d, repeats); - TestLattice tl = new TestLattice(d, 0.000001); + TestLattice tl = new(d, 0.000001); tl.Traverse(); @@ -746,7 +746,7 @@ internal class T1 { private static void t1() { - PointLocator pl = new PointLocator(); + PointLocator pl = new(); pl.Add(new Edge(1, 1, 3, 4, 1, -1)); pl.Add(new Edge(3, 4, 4, 2, 1, -1)); pl.Add(new Edge(1, 1, 4, 2, -1, 1)); @@ -798,7 +798,7 @@ private static void t1() private static void t2() { - PointLocator pl = new PointLocator(); + PointLocator pl = new(); //outer triangle pl.Add(new Edge(1, 1, 2, 8, 1, -1)); pl.Add(new Edge(2, 8, 7, 5, 1, -1)); @@ -912,7 +912,7 @@ private static void t2() private static void t3() { - PointLocator pl = new PointLocator(); + PointLocator pl = new(); pl.Add(new Edge(1, 1, 5, 2, -1, 1)); pl.Add(new Edge(5, 2, 6, 6, -1, 1)); pl.Add(new Edge(4, 3, 6, 6, 1, -1)); @@ -994,7 +994,7 @@ private static void t3() private static void t4() { - PointLocator pl = new PointLocator(); + PointLocator pl = new(); pl.Add(new Edge(2, 4, 5, 1, -1, 1)); pl.Add(new Edge(5, 1, 11, 2, -1, 2)); pl.Add(new Edge(5, 1, 9, 4, 2, 1)); @@ -1399,7 +1399,7 @@ public class PointLocationProgram public static void Main() { Test.T1.run(); - Test.TestUgly.Run(new string[0]); + Test.TestUgly.Run([]); } } } diff --git a/C5.UserGuideExamples/QuickViewSort.cs b/C5.UserGuideExamples/QuickViewSort.cs index d62884ad..024d2b40 100644 --- a/C5.UserGuideExamples/QuickViewSort.cs +++ b/C5.UserGuideExamples/QuickViewSort.cs @@ -78,7 +78,7 @@ public static void QwSort(T[] arr) where T : IComparable QwSort(arr, 0, arr.Length - 1); } - private static readonly Random _random = new Random(); + private static readonly Random _random = new(); private static int[] RandomInts(int n) { diff --git a/C5.UserGuideExamples/RandomSelection.cs b/C5.UserGuideExamples/RandomSelection.cs index c6a757b8..0ead4f86 100644 --- a/C5.UserGuideExamples/RandomSelection.cs +++ b/C5.UserGuideExamples/RandomSelection.cs @@ -9,8 +9,8 @@ internal class RandomSelection { public static void Main() { - ArrayList list = new ArrayList(); - list.AddAll(new[] { 2, 3, 5, 7, 11, 13, 17, 19 }); + ArrayList list = new(); + list.AddAll([2, 3, 5, 7, 11, 13, 17, 19]); var copy1 = new ArrayList(); copy1.AddAll(list); var copy2 = new ArrayList(); @@ -40,7 +40,7 @@ public static void Main() Console.WriteLine(); } - private static readonly C5Random _random = new C5Random(); + private static readonly C5Random _random = new(); // Select N random items from coll, with replacement. // Does not modify the given list. diff --git a/C5.UserGuideExamples/Sets.cs b/C5.UserGuideExamples/Sets.cs index 893cdcf2..7dc41014 100644 --- a/C5.UserGuideExamples/Sets.cs +++ b/C5.UserGuideExamples/Sets.cs @@ -75,9 +75,13 @@ public Set(params T[] elems) : this((SCG.IEnumerable)elems) { } return !(s1 == s2); } - public override bool Equals(object that) + public override bool Equals(object? that) { - return this == (that as Set); + var t = that as Set; + + ArgumentNullException.ThrowIfNull(t); + + return this == (t); } public override int GetHashCode() diff --git a/C5.UserGuideExamples/SortedArrayTest.cs b/C5.UserGuideExamples/SortedArrayTest.cs index bad1fa7d..e784df7b 100644 --- a/C5.UserGuideExamples/SortedArrayTest.cs +++ b/C5.UserGuideExamples/SortedArrayTest.cs @@ -20,7 +20,7 @@ public static void Main() } ); - SortedArray<(string, int)> sarr = new SortedArray<(string, int)>(lexico) + SortedArray<(string, int)> sarr = new(lexico) { ("ole", 32), ("hans", 77), diff --git a/C5.UserGuideExamples/SortingPermutation.cs b/C5.UserGuideExamples/SortingPermutation.cs index ae3b7f66..241ab7df 100644 --- a/C5.UserGuideExamples/SortingPermutation.cs +++ b/C5.UserGuideExamples/SortingPermutation.cs @@ -10,7 +10,7 @@ internal class SortingPermutation { public static void Main() { - string[] cities = { "Tokyo", "Beijing", "Hangzhou", "Kyoto", "Beijing", "Copenhagen", "Seattle" }; + string[] cities = ["Tokyo", "Beijing", "Hangzhou", "Kyoto", "Beijing", "Copenhagen", "Seattle"]; IList alst = new ArrayList(); alst.AddAll(cities); diff --git a/C5.UserGuideExamples/ThisFun.cs b/C5.UserGuideExamples/ThisFun.cs index 5b45f7d6..03dc94c8 100644 --- a/C5.UserGuideExamples/ThisFun.cs +++ b/C5.UserGuideExamples/ThisFun.cs @@ -12,7 +12,7 @@ public static void Main() { var fb = new FooBar(); IList list = new LinkedList(); - list.AddAll(new[] { 2, 3, 5, 7, 11 }); + list.AddAll([2, 3, 5, 7, 11]); list.Map(fb).Apply(Console.WriteLine); list.Apply(fb); } diff --git a/C5.UserGuideExamples/Toposort.cs b/C5.UserGuideExamples/Toposort.cs index f339c41b..cabd43b4 100644 --- a/C5.UserGuideExamples/Toposort.cs +++ b/C5.UserGuideExamples/Toposort.cs @@ -10,11 +10,11 @@ internal class Toposort public static void Main() { MyNode - d = new MyNode("d"), - e = new MyNode("e"), - c = new MyNode("c", d, e), - b = new MyNode("b", d), - a = new MyNode("a", d, b, c); + d = new("d"), + e = new("e"), + c = new("c", d, e), + b = new("b", d), + a = new("a", d, b, c); foreach (var n in Toposort0(a)) { @@ -109,19 +109,17 @@ public static IList> Toposort2(params MyNode[] starts) if (!sorted.Contains(start)) { sorted.InsertLast(start); - using (IList> cursor = sorted.View(sorted.Count - 1, 1)) + using IList> cursor = sorted.View(sorted.Count - 1, 1); + do { - do + MyNode child; + while ((child = PendingChild(sorted, cursor.First)) != null) { - MyNode child; - while ((child = PendingChild(sorted, cursor.First)) != null) - { - cursor.InsertFirst(child); - cursor.Slide(0, 1); - } + cursor.InsertFirst(child); + cursor.Slide(0, 1); } - while (cursor.TrySlide(+1)); } + while (cursor.TrySlide(+1)); } } diff --git a/C5.UserGuideExamples/UnionFind.cs b/C5.UserGuideExamples/UnionFind.cs index 9a72db47..dcb29cad 100644 --- a/C5.UserGuideExamples/UnionFind.cs +++ b/C5.UserGuideExamples/UnionFind.cs @@ -59,7 +59,7 @@ public static void Main() public class Eqclass { - private static readonly HashDictionary> dict = new HashDictionary>(); + private static readonly HashDictionary> dict = new(); private Eqclass _link; private int _rank; diff --git a/C5.UserGuideExamples/ViewPatterns.cs b/C5.UserGuideExamples/ViewPatterns.cs index 3a30e0fd..73c0052a 100644 --- a/C5.UserGuideExamples/ViewPatterns.cs +++ b/C5.UserGuideExamples/ViewPatterns.cs @@ -10,7 +10,7 @@ internal class ViewPatterns public static void Main() { IList lst = new ArrayList(); - lst.AddAll(new char[] { 'a', 'b', 'c', 'd' }); + lst.AddAll(['a', 'b', 'c', 'd']); IList v1 = lst.View(1, 1); Console.WriteLine("v1 = {0}", v1); InsertBeforeFirst(v1, '<', 'b'); @@ -38,7 +38,7 @@ public static void Main() } IList lst2 = new ArrayList(); - lst2.AddAll(new char[] { 'a', 'b', 'c', 'A', 'a', 'd', 'a' }); + lst2.AddAll(['a', 'b', 'c', 'A', 'a', 'd', 'a']); foreach (var i in IndexesOf(lst2, 'a')) { @@ -223,13 +223,11 @@ public static void ReplaceXsByY(HashedLinkedList list, T[] xs, T y) { foreach (var x in xs) { - using (var view = list.ViewOf(x)) + using var view = list.ViewOf(x); + if (view != null) { - if (view != null) - { - view.Remove(); - view.Add(y); - } + view.Remove(); + view.Add(y); } } } @@ -299,17 +297,15 @@ public static bool SameUnderlying(IList u, IList w) // Find the index of the first item that satisfies p public static int FindFirstIndex(IList list, Func p) { - using (var view = list.View(0, 0)) + using var view = list.View(0, 0); + while (view.TrySlide(0, 1)) { - while (view.TrySlide(0, 1)) + if (p(view.First)) { - if (p(view.First)) - { - return view.Offset; - } - - view.Slide(+1, 0); + return view.Offset; } + + view.Slide(+1, 0); } return -1; } @@ -317,14 +313,12 @@ public static int FindFirstIndex(IList list, Func p) // Find the index of the last item that satisfies p public static int FindLastIndex(IList list, Func p) { - using (var view = list.View(list.Count, 0)) + using var view = list.View(list.Count, 0); + while (view.TrySlide(-1, 1)) { - while (view.TrySlide(-1, 1)) + if (p(view.First)) { - if (p(view.First)) - { - return view.Offset; - } + return view.Offset; } } return -1; diff --git a/C5.UserGuideExamples/Views.cs b/C5.UserGuideExamples/Views.cs index 3b925892..817004a1 100644 --- a/C5.UserGuideExamples/Views.cs +++ b/C5.UserGuideExamples/Views.cs @@ -10,7 +10,7 @@ internal class Views public static void Main() { IList lst = new LinkedList(); - lst.AddAll(new char[] { 'a', 'b', 'c', 'd' }); + lst.AddAll(['a', 'b', 'c', 'd']); IList A = lst.View(0, 2), B = lst.View(2, 0), @@ -19,7 +19,7 @@ public static void Main() E = lst.View(4, 0), F = lst.View(1, 2), G = lst.View(0, 4); - IList[] views = { A, B, C, D, E, F, G }; + IList[] views = [A, B, C, D, E, F, G]; Console.WriteLine("ABCDEFG overlaps with:"); foreach (IList u in views) { @@ -113,13 +113,11 @@ public static void ReplaceXsByY(HashedLinkedList list, T[] xs, T y) { foreach (T x in xs) { - using (IList view = list.ViewOf(x)) + using IList view = list.ViewOf(x); + if (view != null) { - if (view != null) - { - view.Remove(); - view.Add(y); - } + view.Remove(); + view.Add(y); } } } diff --git a/C5/Arrays/ArrayList.cs b/C5/Arrays/ArrayList.cs index 1bd02502..54479a87 100644 --- a/C5/Arrays/ArrayList.cs +++ b/C5/Arrays/ArrayList.cs @@ -3,1810 +3,1637 @@ using System; using SCG = System.Collections.Generic; -namespace C5 + +namespace C5; + +/// +/// A list collection based on a plain dynamic array data structure. +/// Expansion of the internal array is performed by doubling on demand. +/// The internal array is only shrinked by the Clear method. +/// +/// When the FIFO property is set to false this class works fine as a stack of T. +/// When the FIFO property is set to true the class will function as a (FIFO) queue +/// but very inefficiently, use a LinkedList () instead. +/// +/// +/// Create an array list with external item equalityComparer and prescribed initial capacity. +/// +/// The prescribed capacity +/// The external item equalitySCG.Comparer +public class ArrayList(int capacity, SCG.IEqualityComparer itemequalityComparer) : ArrayBase(capacity, itemequalityComparer), IList, IStack, IQueue { + #region Fields + /// - /// A list collection based on a plain dynamic array data structure. - /// Expansion of the internal array is performed by doubling on demand. - /// The internal array is only shrinked by the Clear method. - /// - /// When the FIFO property is set to false this class works fine as a stack of T. - /// When the FIFO property is set to true the class will function as a (FIFO) queue - /// but very inefficiently, use a LinkedList () instead. + /// Has this list or view not been invalidated by some operation (by someone calling Dispose()) /// - public class ArrayList : ArrayBase, IList, IStack, IQueue - { - #region Fields - - /// - /// Has this list or view not been invalidated by some operation (by someone calling Dispose()) - /// - private bool isValid = true; - - //TODO: wonder if we should save some memory on none-view situations by - // putting these three fields into a single ref field? - /// - /// The underlying list if we are a view, null else. - /// - private ArrayList? underlying; - private WeakViewList>? views; - private WeakViewList>.Node? myWeakReference; - - /// - /// The size of the underlying list. - /// - private int Underlyingsize => (underlying ?? this).size; - - /// - /// The underlying field of the FIFO property - /// - private bool fIFO = false; + private bool isValid = true; - #endregion - #region Events - - /// - /// - /// - /// - public override EventType ListenableEvents => underlying == null ? EventType.All : EventType.None; - - /* - /// - /// - /// - /// - public override event CollectionChangedHandler CollectionChanged - { - add - { - if (underlying == null) - base.CollectionChanged += value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - remove - { - if (underlying == null) - base.CollectionChanged -= value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - } - - /// - /// - /// - /// - public override event CollectionClearedHandler CollectionCleared - { - add - { - if (underlying == null) - base.CollectionCleared += value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - remove - { - if (underlying == null) - base.CollectionCleared -= value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - } - - /// - /// - /// - /// - public override event ItemsAddedHandler ItemsAdded - { - add - { - if (underlying == null) - base.ItemsAdded += value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - remove - { - if (underlying == null) - base.ItemsAdded -= value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - } + //TODO: wonder if we should save some memory on none-view situations by + // putting these three fields into a single ref field? + /// + /// The underlying list if we are a view, null else. + /// + private ArrayList? underlying; + private WeakViewList>? views; + private WeakViewList>.Node? myWeakReference; - /// - /// - /// - /// - public override event ItemInsertedHandler ItemInserted - { - add - { - if (underlying == null) - base.ItemInserted += value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - remove - { - if (underlying == null) - base.ItemInserted -= value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - } + /// + /// The size of the underlying list. + /// + private int UnderlyingSize => (underlying ?? this).size; - /// - /// - /// - /// - public override event ItemsRemovedHandler ItemsRemoved - { - add - { - if (underlying == null) - base.ItemsRemoved += value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - remove - { - if (underlying == null) - base.ItemsRemoved -= value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - } + /// + /// The underlying field of the FIFO property + /// + private bool fIFO = false; - /// - /// - /// - /// - public override event ItemRemovedAtHandler ItemRemovedAt - { - add - { - if (underlying == null) - base.ItemRemovedAt += value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - remove - { - if (underlying == null) - base.ItemRemovedAt -= value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - } + #endregion + #region Events - */ + /// + /// + /// + /// + public override EventType ListenableEvents => underlying == null ? EventType.All : EventType.None; - #endregion - #region Util + #endregion + #region Util - private bool Equals(T i1, T i2) { return itemequalityComparer.Equals(i1, i2); } + private bool Equals(T i1, T i2) => itemEqualityComparer.Equals(i1, i2); - /// - /// Increment or decrement the private size fields - /// - /// Increment (with sign) - private void AddToSize(int delta) + /// + /// Increment or decrement the private size fields + /// + /// Increment (with sign) + private void AddToSize(int delta) + { + size += delta; + if (underlying != null) { - size += delta; - if (underlying != null) - { - underlying.size += delta; - } + underlying.size += delta; } + } - #region Array handling - /// - /// Double the size of the internal array. - /// - protected override void Expand() - { Expand(2 * array.Length, Underlyingsize); } - + #region Array handling + /// + /// Double the size of the internal array. + /// + protected override void Expand() + { + Expand(2 * array.Length, UnderlyingSize); + } - /// - /// Expand the internal array, resetting the index of the first unused element. - /// - /// The new capacity (will be rounded upwards to a power of 2). - /// The new count of - protected override void Expand(int newcapacity, int newsize) + /// + /// Expand the internal array, resetting the index of the first unused element. + /// + /// The new capacity (will be rounded upwards to a power of 2). + /// The new count of + protected override void Expand(int newCapacity, int newSize) + { + if (underlying != null) { - if (underlying != null) - { - underlying.Expand(newcapacity, newsize); - } - else + underlying.Expand(newCapacity, newSize); + } + else + { + base.Expand(newCapacity, newSize); + if (views != null) { - base.Expand(newcapacity, newsize); - if (views != null) + foreach (ArrayList v in views) { - foreach (ArrayList v in views) - { - v.array = array; - } + v.array = array; } } } + } - #endregion + #endregion - #region Checks - /// - /// Check if it is valid to perform updates and increment stamp if so. - /// - /// If check fails by this list being a disposed view. - /// If check fails by this being a read only list. - protected override void UpdateCheck() + #region Checks + /// + /// Check if it is valid to perform updates and increment stamp if so. + /// + /// If check fails by this list being a disposed view. + /// If check fails by this being a read only list. + protected override void UpdateCheck() + { + ValidityCheck(); + base.UpdateCheck(); + if (underlying != null) { - ValidityCheck(); - base.UpdateCheck(); - if (underlying != null) - { - underlying.stamp++; - } + underlying.stamp++; } + } - - /// - /// Check if we are a view that the underlying list has only been updated through us. - /// This method should be called from enumerators etc to guard against - /// modification of the base collection. - /// - /// if check fails. - private void ValidityCheck() + /// + /// Check if we are a view that the underlying list has only been updated through us. + /// This method should be called from enumerators etc to guard against + /// modification of the base collection. + /// + /// if check fails. + private void ValidityCheck() + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException(); - } + throw new ViewDisposedException(); } + } - - /// - /// Check that the list has not been updated since a particular time. - /// To be used by enumerators and range - /// - /// If check fails by this list being a disposed view. - /// If the list *has* been updated since that time.. - /// The stamp indicating the time. - protected override void ModifyCheck(int stamp) + /// + /// Check that the list has not been updated since a particular time. + /// To be used by enumerators and range + /// + /// If check fails by this list being a disposed view. + /// If the list *has* been updated since that time.. + /// The stamp indicating the time. + protected override void ModifyCheck(int stamp) + { + ValidityCheck(); + if (this.stamp != stamp) { - ValidityCheck(); - if (this.stamp != stamp) - { - throw new CollectionModifiedException(); - } + throw new CollectionModifiedException(); } + } - #endregion + #endregion - #region Searching + #region Searching - /// - /// Internal version of IndexOf without modification checks. - /// - /// Item to look for - /// The index of first occurrence - private int IndexOfInner(T item) + /// + /// Internal version of IndexOf without modification checks. + /// + /// Item to look for + /// The index of first occurrence + private int IndexOfInner(T item) + { + for (int i = 0; i < size; i++) { - for (int i = 0; i < size; i++) + if (Equals(item, array[offsetField + i])) { - if (Equals(item, array[offsetField + i])) - { - return i; - } + return i; } - - return ~size; } - /// - /// Internal version of LastIndexOf without modification checks. - /// - /// Item to look for - /// The index of last occurrence - private int LastIndexOfInner(T item) + return ~size; + } + + /// + /// Internal version of LastIndexOf without modification checks. + /// + /// Item to look for + /// The index of last occurrence + private int LastIndexOfInner(T item) + { + for (int i = size - 1; i >= 0; i--) { - for (int i = size - 1; i >= 0; i--) + if (Equals(item, array[offsetField + i])) { - if (Equals(item, array[offsetField + i])) - { - return i; - } + return i; } - - return ~size; } - #endregion - #region Inserting + return ~size; + } + #endregion - /// - /// Internal version of Insert with no modification checks. - /// - /// Index to insert at - /// Item to insert - protected override void InsertProtected(int i, T item) + #region Inserting + + /// + /// Internal version of Insert with no modification checks. + /// + /// Index to insert at + /// Item to insert + protected override void InsertProtected(int i, T item) + { + BaseInsertInner(i, item); + } + + private void BaseInsertInner(int i, T item) + { + if (UnderlyingSize == array.Length) { - BaseInsertInner(i, item); + Expand(); } - private void BaseInsertInner(int i, T item) + i += offsetField; + if (i < UnderlyingSize) { - if (Underlyingsize == array.Length) - { - Expand(); - } - - i += offsetField; - if (i < Underlyingsize) - { - Array.Copy(array, i, array, i + 1, Underlyingsize - i); - } - - array[i] = item; - AddToSize(1); - FixViewsAfterInsert(1, i); + Array.Copy(array, i, array, i + 1, UnderlyingSize - i); } - #endregion - #region Removing - - /// - /// Internal version of RemoveAt with no modification checks. - /// - /// Index to remove at - /// The removed item - private T RemoveAtInner(int i) - { - i += offsetField; - FixViewsBeforeSingleRemove(i); - T retval = array[i]; - AddToSize(-1); - if (Underlyingsize > i) - { - Array.Copy(array, i + 1, array, i, Underlyingsize - i); - } + array[i] = item; + AddToSize(1); + FixViewsAfterInsert(1, i); + } + #endregion - array[Underlyingsize] = default; + #region Removing - return retval; + /// + /// Internal version of RemoveAt with no modification checks. + /// + /// Index to remove at + /// The removed item + private T RemoveAtInner(int i) + { + i += offsetField; + FixViewsBeforeSingleRemove(i); + var retval = array[i]; + AddToSize(-1); + if (UnderlyingSize > i) + { + Array.Copy(array, i + 1, array, i, UnderlyingSize - i); } - #endregion - #region Indexing + array[UnderlyingSize] = default; - #endregion + return retval; + } + #endregion - #region fixView utilities + #region Indexing - /// - /// - /// - /// The actual number of inserted nodes - /// - private void FixViewsAfterInsert(int added, int realInsertionIndex) + #endregion + + #region fixView utilities + + /// + /// + /// + /// The actual number of inserted nodes + /// + private void FixViewsAfterInsert(int added, int realInsertionIndex) + { + if (views != null) { - if (views != null) + foreach (ArrayList view in views) { - foreach (ArrayList view in views) + if (view != this) { - if (view != this) + if (view.offsetField < realInsertionIndex && view.offsetField + view.size > realInsertionIndex) { - if (view.offsetField < realInsertionIndex && view.offsetField + view.size > realInsertionIndex) - { - view.size += added; - } + view.size += added; + } - if (view.offsetField > realInsertionIndex || (view.offsetField == realInsertionIndex && view.size > 0)) - { - view.offsetField += added; - } + if (view.offsetField > realInsertionIndex || (view.offsetField == realInsertionIndex && view.size > 0)) + { + view.offsetField += added; } } } } + } - private void FixViewsBeforeSingleRemove(int realRemovalIndex) + private void FixViewsBeforeSingleRemove(int realRemovalIndex) + { + if (views != null) { - if (views != null) + foreach (ArrayList view in views) { - foreach (ArrayList view in views) + if (view != this) { - if (view != this) + if (view.offsetField <= realRemovalIndex && view.offsetField + view.size > realRemovalIndex) { - if (view.offsetField <= realRemovalIndex && view.offsetField + view.size > realRemovalIndex) - { - view.size--; - } + view.size--; + } - if (view.offsetField > realRemovalIndex) - { - view.offsetField--; - } + if (view.offsetField > realRemovalIndex) + { + view.offsetField--; } } } } + } - /// - /// Fix offsets and sizes of other views before removing an interval from this - /// - /// the start of the interval relative to the array/underlying - /// - private void FixViewsBeforeRemove(int start, int count) + /// + /// Fix offsets and sizes of other views before removing an interval from this + /// + /// the start of the interval relative to the array/underlying + /// + private void FixViewsBeforeRemove(int start, int count) + { + int clearend = start + count - 1; + if (views != null) { - int clearend = start + count - 1; - if (views != null) + foreach (ArrayList view in views) { - foreach (ArrayList view in views) + if (view == this) { - if (view == this) - { - continue; - } + continue; + } - int viewoffset = view.offsetField, viewend = viewoffset + view.size - 1; - if (start < viewoffset) + int viewoffset = view.offsetField, viewend = viewoffset + view.size - 1; + if (start < viewoffset) + { + if (clearend < viewoffset) { - if (clearend < viewoffset) - { - view.offsetField = viewoffset - count; - } - else - { - view.offsetField = start; - view.size = clearend < viewend ? viewend - clearend : 0; - } + view.offsetField = viewoffset - count; } - else if (start <= viewend) + else { - view.size = clearend <= viewend ? view.size - count : start - viewoffset; + view.offsetField = start; + view.size = clearend < viewend ? viewend - clearend : 0; } } + else if (start <= viewend) + { + view.size = clearend <= viewend ? view.size - count : start - viewoffset; + } } } + } - /// - /// - /// - /// - /// - /// The position of View(otherOffset, otherSize) wrt. this view - private MutualViewPosition ViewPosition(int otherOffset, int otherSize) + /// + /// + /// + /// + /// + /// The position of View(otherOffset, otherSize) wrt. this view + private MutualViewPosition ViewPosition(int otherOffset, int otherSize) + { + int end = offsetField + size, otherEnd = otherOffset + otherSize; + if (otherOffset >= end || otherEnd <= offsetField) { - int end = offsetField + size, otherEnd = otherOffset + otherSize; - if (otherOffset >= end || otherEnd <= offsetField) - { - return MutualViewPosition.NonOverlapping; - } - - if (size == 0 || (otherOffset <= offsetField && end <= otherEnd)) - { - return MutualViewPosition.Contains; - } + return MutualViewPosition.NonOverlapping; + } - if (otherSize == 0 || (offsetField <= otherOffset && otherEnd <= end)) - { - return MutualViewPosition.ContainedIn; - } + if (size == 0 || (otherOffset <= offsetField && end <= otherEnd)) + { + return MutualViewPosition.Contains; + } - return MutualViewPosition.Overlapping; + if (otherSize == 0 || (offsetField <= otherOffset && otherEnd <= end)) + { + return MutualViewPosition.ContainedIn; } - //TODO: make version that fits the new, more forgiving rules for disposing - private void DisposeOverlappingViews(bool reverse) + return MutualViewPosition.Overlapping; + } + + //TODO: make version that fits the new, more forgiving rules for disposing + private void DisposeOverlappingViews(bool reverse) + { + if (views != null) { - if (views != null) + foreach (ArrayList view in views) { - foreach (ArrayList view in views) + if (view != this) { - if (view != this) + switch (ViewPosition(view.offsetField, view.size)) { - switch (ViewPosition(view.offsetField, view.size)) - { - case MutualViewPosition.ContainedIn: - if (reverse) - { - view.offsetField = 2 * offsetField + size - view.size - view.offsetField; - } - else - { - view.Dispose(); - } - - break; - case MutualViewPosition.Overlapping: + case MutualViewPosition.ContainedIn: + if (reverse) + { + view.offsetField = 2 * offsetField + size - view.size - view.offsetField; + } + else + { view.Dispose(); - break; - case MutualViewPosition.Contains: - case MutualViewPosition.NonOverlapping: - break; - } + } + + break; + case MutualViewPosition.Overlapping: + view.Dispose(); + break; + case MutualViewPosition.Contains: + case MutualViewPosition.NonOverlapping: + break; } } } } - #endregion + } + #endregion - #endregion + #endregion - #region Position, PositionComparer and ViewHandler nested types - private class PositionComparer : SCG.IComparer + #region Position, PositionComparer and ViewHandler nested types + private class PositionComparer : SCG.IComparer + { + public int Compare(Position a, Position b) { - public int Compare(Position a, Position b) - { - return a.Index.CompareTo(b.Index); - } + return a.Index.CompareTo(b.Index); } + } - /// - /// During RemoveAll, we need to cache the original endpoint indices of views (??? also for ArrayList?) - /// - private struct Position + /// + /// During RemoveAll, we need to cache the original endpoint indices of views (??? also for ArrayList?) + /// + private readonly struct Position + { + public ArrayList? View { get; } + + public int Index { get; } + + public Position(ArrayList view, bool left) { - public ArrayList? View { get; } + View = view; + Index = left ? view.offsetField : view.offsetField + view.size - 1; + } - public int Index { get; } + public Position(int index) + { + Index = index; + View = null; + } + } - public Position(ArrayList view, bool left) - { - View = view; - Index = left ? view.offsetField : view.offsetField + view.size - 1; + /// + /// Handle the update of (other) views during a multi-remove operation. + /// + private struct ViewHandler + { + private readonly ArrayList? leftEnds; + private readonly ArrayList? rightEnds; + private int leftEndIndex, rightEndIndex; + internal readonly int viewCount; + internal ViewHandler(ArrayList list) + { + leftEndIndex = rightEndIndex = viewCount = 0; + leftEnds = null; + rightEnds = null; + if (list.views != null) + { + foreach (ArrayList v in list.views) + { + if (v != list) + { + if (leftEnds == null || rightEnds == null) + { + leftEnds = []; + rightEnds = []; + } + leftEnds.Add(new Position(v, true)); + rightEnds.Add(new Position(v, false)); + } + } } - public Position(int index) + if (leftEnds == null || rightEnds == null) { - Index = index; - View = null; + return; } - } + viewCount = leftEnds.Count; + leftEnds.Sort(new PositionComparer()); + rightEnds.Sort(new PositionComparer()); + } /// - /// Handle the update of (other) views during a multi-remove operation. + /// This is to be called with realindex pointing to the first node to be removed after a (stretch of) node that was not removed /// - private struct ViewHandler + /// + /// + internal void SkipEndpoints(int removed, int realindex) { - private readonly ArrayList? leftEnds; - private readonly ArrayList? rightEnds; - private int leftEndIndex, rightEndIndex; - internal readonly int viewCount; - internal ViewHandler(ArrayList list) + if (viewCount > 0) { - leftEndIndex = rightEndIndex = viewCount = 0; - leftEnds = null; - rightEnds = null; - if (list.views != null) + Position endpoint; + while (leftEndIndex < viewCount && (endpoint = leftEnds![leftEndIndex]).Index <= realindex) { - foreach (ArrayList v in list.views) - { - if (v != list) - { - if (leftEnds == null || rightEnds == null) - { - leftEnds = new ArrayList(); - rightEnds = new ArrayList(); - } - leftEnds.Add(new Position(v, true)); - rightEnds.Add(new Position(v, false)); - } - } + ArrayList view = endpoint.View!; + view.offsetField -= removed; + view.size += removed; + leftEndIndex++; } - - if (leftEnds == null || rightEnds == null) + while (rightEndIndex < viewCount && (endpoint = rightEnds![rightEndIndex]).Index < realindex) { - return; + endpoint.View!.size -= removed; + rightEndIndex++; } - - viewCount = leftEnds.Count; - leftEnds.Sort(new PositionComparer()); - rightEnds.Sort(new PositionComparer()); } - /// - /// This is to be called with realindex pointing to the first node to be removed after a (stretch of) node that was not removed - /// - /// - /// - internal void SkipEndpoints(int removed, int realindex) + } + internal void UpdateViewSizesAndCounts(int removed, int realindex) + { + if (viewCount > 0) { - if (viewCount > 0) + Position endpoint; + while (leftEndIndex < viewCount && (endpoint = leftEnds![leftEndIndex]).Index <= realindex) { - Position endpoint; - while (leftEndIndex < viewCount && (endpoint = leftEnds![leftEndIndex]).Index <= realindex) - { - ArrayList view = endpoint.View!; - view.offsetField -= removed; - view.size += removed; - leftEndIndex++; - } - while (rightEndIndex < viewCount && (endpoint = rightEnds![rightEndIndex]).Index < realindex) - { - endpoint.View!.size -= removed; - rightEndIndex++; - } + ArrayList view = endpoint.View!; + view.offsetField = view.Offset - removed; + view.size += removed; + leftEndIndex++; } - } - internal void UpdateViewSizesAndCounts(int removed, int realindex) - { - if (viewCount > 0) + while (rightEndIndex < viewCount && (endpoint = rightEnds![rightEndIndex]).Index < realindex) { - Position endpoint; - while (leftEndIndex < viewCount && (endpoint = leftEnds![leftEndIndex]).Index <= realindex) - { - ArrayList view = endpoint.View!; - view.offsetField = view.Offset - removed; - view.size += removed; - leftEndIndex++; - } - while (rightEndIndex < viewCount && (endpoint = rightEnds![rightEndIndex]).Index < realindex) - { - endpoint.View!.size -= removed; - rightEndIndex++; - } + endpoint.View!.size -= removed; + rightEndIndex++; } } } - #endregion - - #region Constructors - /// - /// Create an array list with default item equalityComparer and initial capacity 8 items. - /// - public ArrayList() : this(8) { } - - - /// - /// Create an array list with external item equalityComparer and initial capacity 8 items. - /// - /// The external item equalitySCG.Comparer - public ArrayList(SCG.IEqualityComparer itemequalityComparer) : this(8, itemequalityComparer) { } - - - /// - /// Create an array list with default item equalityComparer and prescribed initial capacity. - /// - /// The prescribed capacity - public ArrayList(int capacity) : this(capacity, EqualityComparer.Default) { } - + } + #endregion - /// - /// Create an array list with external item equalityComparer and prescribed initial capacity. - /// - /// The prescribed capacity - /// The external item equalitySCG.Comparer - public ArrayList(int capacity, SCG.IEqualityComparer itemequalityComparer) - : base(capacity, itemequalityComparer) - { + #region Constructors + /// + /// Create an array list with default item equalityComparer and initial capacity 8 items. + /// + public ArrayList() : this(8) { } - } - #endregion + /// + /// Create an array list with external item equalityComparer and initial capacity 8 items. + /// + /// The external item equalitySCG.Comparer + public ArrayList(SCG.IEqualityComparer itemequalityComparer) : this(8, itemequalityComparer) { } - #region IList Members - /// - /// - /// if this list is empty. - /// The first item in this list. - public virtual T First - { - get - { - ValidityCheck(); - if (size == 0) - { - throw new NoSuchItemException(); - } + /// + /// Create an array list with default item equalityComparer and prescribed initial capacity. + /// + /// The prescribed capacity + public ArrayList(int capacity) : this(capacity, EqualityComparer.Default) { } - return array[offsetField]; - } - } + #endregion + #region IList Members - /// - /// - /// if this list is empty. - /// The last item in this list. - public virtual T Last + /// + /// + /// if this list is empty. + /// The first item in this list. + public virtual T First + { + get { - get + ValidityCheck(); + if (size == 0) { - ValidityCheck(); - if (size == 0) - { - throw new NoSuchItemException(); - } - - return array[offsetField + size - 1]; + throw new NoSuchItemException(); } - } - - /// - /// Since Add(T item) always add at the end of the list, - /// this describes if list has FIFO or LIFO semantics. - /// - /// True if the Remove() operation removes from the - /// start of the list, false if it removes from the end. The default for a new array list is false. - public virtual bool FIFO - { - get { ValidityCheck(); return fIFO; } - set { UpdateCheck(); fIFO = value; } + return array[offsetField]; } + } - /// - /// - /// - public virtual bool IsFixedSize - { - get { ValidityCheck(); return false; } - } - /// - /// On this list, this indexer is read/write. - /// - /// if index is negative or - /// >= the size of the collection. - /// The index'th item of this list. - /// The index of the item to fetch or store. - public virtual T this[int index] + /// + /// + /// if this list is empty. + /// The last item in this list. + public virtual T Last + { + get { - get + ValidityCheck(); + if (size == 0) { - ValidityCheck(); - if (index < 0 || index >= size) - { - throw new IndexOutOfRangeException(); - } - - return array[offsetField + index]; + throw new NoSuchItemException(); } - set - { - UpdateCheck(); - if (index < 0 || index >= size) - { - throw new IndexOutOfRangeException(); - } - index += offsetField; - T item = array[index]; + return array[offsetField + size - 1]; + } + } - array[index] = value; - (underlying ?? this).RaiseForSetThis(index, value, item); - } - } + /// + /// Since Add(T item) always add at the end of the list, + /// this describes if list has FIFO or LIFO semantics. + /// + /// True if the Remove() operation removes from the + /// start of the list, false if it removes from the end. The default for a new array list is false. + public virtual bool FIFO + { + get { ValidityCheck(); return fIFO; } + set { UpdateCheck(); fIFO = value; } + } - /// - /// - /// - /// - public virtual Speed IndexingSpeed => Speed.Constant; + /// + /// + /// + public virtual bool IsFixedSize + { + get { ValidityCheck(); return false; } + } - /// - /// Insert an item at a specific index location in this list. - /// - /// if i is negative or - /// > the size of the collection. - /// The index at which to insert. - /// The item to insert. - public virtual void Insert(int index, T item) + /// + /// On this list, this indexer is read/write. + /// + /// if index is negative or + /// >= the size of the collection. + /// The index'th item of this list. + /// The index of the item to fetch or store. + public virtual T this[int index] + { + get { - UpdateCheck(); - if (index < 0 || index > size) + ValidityCheck(); + if (index < 0 || index >= size) { throw new IndexOutOfRangeException(); } - InsertProtected(index, item); - (underlying ?? this).RaiseForInsert(index + offsetField, item); - } - - /// - /// Insert an item at the end of a compatible view, used as a pointer. - /// The pointer must be a view on the same list as - /// this and the endpoint of pointer must be - /// a valid insertion point of this - /// - /// If pointer - /// is not a view on or the same list as this - /// ?????? if the endpoint of - /// pointer is not inside this - /// if the list has - /// AllowsDuplicates==false and the item is - /// already in the list. - /// - /// - public void Insert(IList pointer, T item) - { - if ((pointer == null) || ((pointer.Underlying ?? pointer) != (underlying ?? this))) - { - throw new IncompatibleViewException(); - } - - Insert(pointer.Offset + pointer.Count - Offset, item); + return array[offsetField + index]; } - - /// - /// Insert into this list all items from an enumerable collection starting - /// at a particular index. - /// - /// if index is negative or - /// > the size of the collection. - /// Index to start inserting at - /// Items to insert - public virtual void InsertAll(int index, SCG.IEnumerable items) + set { UpdateCheck(); - if (index < 0 || index > size) + if (index < 0 || index >= size) { throw new IndexOutOfRangeException(); } index += offsetField; - int toadd = CountItems(items); - if (toadd == 0) - { - return; - } + T item = array[index]; - if (toadd + Underlyingsize > array.Length) - { - Expand(toadd + Underlyingsize, Underlyingsize); - } - - if (Underlyingsize > index) - { - Array.Copy(array, index, array, index + toadd, Underlyingsize - index); - } - - int i = index; - try - { - - foreach (T item in items) - { - array[i++] = item; - } - } - finally - { - int added = i - index; - if (added < toadd) - { - Array.Copy(array, index + toadd, array, i, Underlyingsize - index); - Array.Clear(array, Underlyingsize + added, toadd - added); - } - if (added > 0) - { - AddToSize(added); + array[index] = value; - FixViewsAfterInsert(added, index); - (underlying ?? this).RaiseForInsertAll(index, added); - } - } + (underlying ?? this).RaiseForSetThis(index, value, item); } - private void RaiseForInsertAll(int index, int added) - { - if (ActiveEvents != 0) - { - if ((ActiveEvents & (EventType.Added | EventType.Inserted)) != 0) - { - for (int j = index; j < index + added; j++) - { - RaiseItemInserted(array[j], j); - RaiseItemsAdded(array[j], 1); - } - } + } - RaiseCollectionChanged(); - } - } + /// + /// + /// + /// + public virtual Speed IndexingSpeed => Speed.Constant; - /// - /// Insert an item at the front of this list; - /// - /// The item to insert. - public virtual void InsertFirst(T item) + /// + /// Insert an item at a specific index location in this list. + /// + /// if i is negative or + /// > the size of the collection. + /// The index at which to insert. + /// The item to insert. + public virtual void Insert(int index, T item) + { + UpdateCheck(); + if (index < 0 || index > size) { - UpdateCheck(); - InsertProtected(0, item); - (underlying ?? this).RaiseForInsert(offsetField, item); + throw new IndexOutOfRangeException(); } - /// - /// Insert an item at the back of this list. - /// - /// The item to insert. - public virtual void InsertLast(T item) + InsertProtected(index, item); + (underlying ?? this).RaiseForInsert(index + offsetField, item); + } + + /// + /// Insert an item at the end of a compatible view, used as a pointer. + /// The pointer must be a view on the same list as + /// this and the endpoint of pointer must be + /// a valid insertion point of this + /// + /// If pointer + /// is not a view on or the same list as this + /// ?????? if the endpoint of + /// pointer is not inside this + /// if the list has + /// AllowsDuplicates==false and the item is + /// already in the list. + /// + /// + public void Insert(IList pointer, T item) + { + if ((pointer == null) || ((pointer.Underlying ?? pointer) != (underlying ?? this))) { - UpdateCheck(); - InsertProtected(size, item); - (underlying ?? this).RaiseForInsert(size - 1 + offsetField, item); + throw new IncompatibleViewException(); } + Insert(pointer.Offset + pointer.Count - Offset, item); + } - //NOTE: if the filter throws an exception, no result will be returned. - /// - /// Create a new list consisting of the items of this list satisfying a - /// certain predicate. - /// The new list will be of type ArrayList - /// - /// The filter delegate defining the predicate. - /// The new list. - public virtual IList FindAll(Func filter) + /// + /// Insert into this list all items from an enumerable collection starting + /// at a particular index. + /// + /// if index is negative or + /// > the size of the collection. + /// Index to start inserting at + /// Items to insert + public virtual void InsertAll(int index, SCG.IEnumerable items) + { + UpdateCheck(); + if (index < 0 || index > size) { - ValidityCheck(); - int stamp = this.stamp; - ArrayList res = new ArrayList(itemequalityComparer); - int j = 0, rescap = res.array.Length; - for (int i = 0; i < size; i++) - { - T a = array[offsetField + i]; - bool found = filter(a); - ModifyCheck(stamp); - if (found) - { - if (j == rescap) - { - res.Expand(rescap = 2 * rescap, j); - } - - res.array[j++] = a; - } - } - res.size = j; - - return res; + throw new IndexOutOfRangeException(); } - /// - /// Create a new list consisting of the results of mapping all items of this - /// list. The new list will use the default item equalityComparer for the item type V. - /// The new list will be of type ArrayList - /// - /// The type of items of the new list - /// The delegate defining the map. - /// The new list. - public virtual IList Map(Func mapper) + index += offsetField; + int toadd = CountItems(items); + if (toadd == 0) { - ValidityCheck(); - - ArrayList res = new ArrayList(size); - - return Map(mapper, res); + return; } - /// - /// Create a new list consisting of the results of mapping all items of this - /// list. The new list will use a specified item equalityComparer for the item type. - /// The new list will be of type ArrayList - /// - /// The type of items of the new list - /// The delegate defining the map. - /// The item equalityComparer to use for the new list - /// The new list. - public virtual IList Map(Func mapper, SCG.IEqualityComparer itemequalityComparer) + if (toadd + UnderlyingSize > array.Length) { - ValidityCheck(); - - ArrayList res = new ArrayList(size, itemequalityComparer); - - return Map(mapper, res); + Expand(toadd + UnderlyingSize, UnderlyingSize); } - private IList Map(Func mapper, ArrayList res) + if (UnderlyingSize > index) { - int stamp = this.stamp; - if (size > 0) - { - for (int i = 0; i < size; i++) - { - V mappeditem = mapper(array[offsetField + i]); - ModifyCheck(stamp); - - res.array[i] = mappeditem; - } - } - - res.size = size; - return res; + Array.Copy(array, index, array, index + toadd, UnderlyingSize - index); } - /// - /// Remove one item from the list: from the front if FIFO - /// is true, else from the back. - /// - /// if this list is empty. - /// The removed item. - public virtual T Remove() + int i = index; + try { - UpdateCheck(); - if (size == 0) + + foreach (T item in items) { - throw new NoSuchItemException("List is empty"); + array[i++] = item; } - - T item = RemoveAtInner(fIFO ? 0 : size - 1); - (underlying ?? this).RaiseForRemove(item); - return item; } - - /// - /// Remove one item from the front of the list. - /// - /// if this list is empty. - /// The removed item. - public virtual T RemoveFirst() + finally { - UpdateCheck(); - if (size == 0) + int added = i - index; + if (added < toadd) { - throw new NoSuchItemException("List is empty"); + Array.Copy(array, index + toadd, array, i, UnderlyingSize - index); + Array.Clear(array, UnderlyingSize + added, toadd - added); } + if (added > 0) + { + AddToSize(added); - T item = RemoveAtInner(0); - (underlying ?? this).RaiseForRemoveAt(offsetField, item); - return item; + FixViewsAfterInsert(added, index); + (underlying ?? this).RaiseForInsertAll(index, added); + } } - - - /// - /// Remove one item from the back of the list. - /// - /// if this list is empty. - /// The removed item. - public virtual T RemoveLast() + } + private void RaiseForInsertAll(int index, int added) + { + if (ActiveEvents != 0) { - UpdateCheck(); - if (size == 0) + if ((ActiveEvents & (EventType.Added | EventType.Inserted)) != 0) { - throw new NoSuchItemException("List is empty"); + for (int j = index; j < index + added; j++) + { + RaiseItemInserted(array[j], j); + RaiseItemsAdded(array[j], 1); + } } - T item = RemoveAtInner(size - 1); - (underlying ?? this).RaiseForRemoveAt(size + offsetField, item); - return item; + RaiseCollectionChanged(); } + } - /// - /// Create a list view on this list. - /// - /// if the start or count is negative - /// or the range does not fit within list. - /// The index in this list of the start of the view. - /// The size of the view. - /// The new list view. - public virtual IList? View(int start, int count) - { - ValidityCheck(); - CheckRange(start, count); - views ??= new WeakViewList>(); + /// + /// Insert an item at the front of this list; + /// + /// The item to insert. + public virtual void InsertFirst(T item) + { + UpdateCheck(); + InsertProtected(0, item); + (underlying ?? this).RaiseForInsert(offsetField, item); + } - ArrayList retval = (ArrayList)MemberwiseClone(); + /// + /// Insert an item at the back of this list. + /// + /// The item to insert. + public virtual void InsertLast(T item) + { + UpdateCheck(); + InsertProtected(size, item); + (underlying ?? this).RaiseForInsert(size - 1 + offsetField, item); + } - retval.underlying = underlying ?? (this); - retval.offsetField = start + offsetField; - retval.size = count; - retval.myWeakReference = views.Add(retval); - return retval; - } + //NOTE: if the filter throws an exception, no result will be returned. + /// + /// Create a new list consisting of the items of this list satisfying a + /// certain predicate. + /// The new list will be of type ArrayList + /// + /// The filter delegate defining the predicate. + /// The new list. + public virtual IList FindAll(Func filter) + { + ValidityCheck(); + int stamp = this.stamp; + ArrayList res = new(itemEqualityComparer); + int j = 0, rescap = res.array.Length; + for (int i = 0; i < size; i++) + { + T a = array[offsetField + i]; + bool found = filter(a); + ModifyCheck(stamp); + if (found) + { + if (j == rescap) + { + res.Expand(rescap = 2 * rescap, j); + } - /// - /// Create a list view on this list containing the (first) occurrence of a particular item. - /// Returns null if the item is not in this list. - /// - /// The item to find. - /// The new list view. - public virtual IList? ViewOf(T item) - { - int index = IndexOfInner(item); - if (index < 0) - { - return null; + res.array[j++] = a; } - - return View(index, 1); } + res.size = j; + return res; + } - /// - /// Create a list view on this list containing the last occurrence of a particular item. - /// Returns null if the item is not in this list. - /// - /// The item to find. - /// The new list view. - public virtual IList? LastViewOf(T item) - { - int index = LastIndexOfInner(item); - if (index < 0) - { - return null; - } + /// + /// Create a new list consisting of the results of mapping all items of this + /// list. The new list will use the default item equalityComparer for the item type V. + /// The new list will be of type ArrayList + /// + /// The type of items of the new list + /// The delegate defining the map. + /// The new list. + public virtual IList Map(Func mapper) + { + ValidityCheck(); - return View(index, 1); - } + ArrayList res = new(size); - /// - /// Null if this list is not a view. - /// - /// Underlying list for view. - public virtual IList? Underlying => underlying; + return Map(mapper, res); + } + /// + /// Create a new list consisting of the results of mapping all items of this + /// list. The new list will use a specified item equalityComparer for the item type. + /// The new list will be of type ArrayList + /// + /// The type of items of the new list + /// The delegate defining the map. + /// The item equalityComparer to use for the new list + /// The new list. + public virtual IList Map(Func mapper, SCG.IEqualityComparer itemequalityComparer) + { + ValidityCheck(); - /// - /// - /// Offset for this list view or 0 for an underlying list. - public virtual int Offset => offsetField; + ArrayList res = new(size, itemequalityComparer); - /// - /// - /// - /// - public virtual bool IsValid => isValid; + return Map(mapper, res); + } - /// - /// Slide this list view along the underlying list. - /// - /// if this list is not a view. - /// if the operation - /// would bring either end of the view outside the underlying list. - /// The signed amount to slide: positive to slide - /// towards the end. - public virtual IList Slide(int offset) - { - if (!TrySlide(offset, size)) + private ArrayList Map(Func mapper, ArrayList res) + { + int stamp = this.stamp; + if (size > 0) + { + for (int i = 0; i < size; i++) { - throw new ArgumentOutOfRangeException(nameof(offset)); + V mappeditem = mapper(array[offsetField + i]); + ModifyCheck(stamp); + + res.array[i] = mappeditem; } + } - return this; + res.size = size; + return res; + } + + /// + /// Remove one item from the list: from the front if FIFO + /// is true, else from the back. + /// + /// if this list is empty. + /// The removed item. + public virtual T Remove() + { + UpdateCheck(); + if (size == 0) + { + throw new NoSuchItemException("List is empty"); } + T item = RemoveAtInner(fIFO ? 0 : size - 1); + (underlying ?? this).RaiseForRemove(item); + return item; + } + + /// + /// Remove one item from the front of the list. + /// + /// if this list is empty. + /// The removed item. + public virtual T RemoveFirst() + { + UpdateCheck(); + if (size == 0) + { + throw new NoSuchItemException("List is empty"); + } + + T item = RemoveAtInner(0); + (underlying ?? this).RaiseForRemoveAt(offsetField, item); + return item; + } - /// - /// Slide this list view along the underlying list, changing its size. - /// - /// if this list is not a view. - /// if the operation - /// would bring either end of the view outside the underlying list. - /// The signed amount to slide: positive to slide - /// towards the end. - /// The new size of the view. - public virtual IList Slide(int offset, int size) - { - if (!TrySlide(offset, size)) - { - throw new ArgumentOutOfRangeException(); - } - return this; + /// + /// Remove one item from the back of the list. + /// + /// if this list is empty. + /// The removed item. + public virtual T RemoveLast() + { + UpdateCheck(); + if (size == 0) + { + throw new NoSuchItemException("List is empty"); } - /// - /// - /// - /// if this list is not a view. - /// - /// - public virtual bool TrySlide(int offset) + T item = RemoveAtInner(size - 1); + (underlying ?? this).RaiseForRemoveAt(size + offsetField, item); + return item; + } + + /// + /// Create a list view on this list. + /// + /// if the start or count is negative + /// or the range does not fit within list. + /// The index in this list of the start of the view. + /// The size of the view. + /// The new list view. + public virtual IList? View(int start, int count) + { + ValidityCheck(); + CheckRange(start, count); + views ??= new WeakViewList>(); + + ArrayList retval = (ArrayList)MemberwiseClone(); + + + retval.underlying = underlying ?? (this); + retval.offsetField = start + offsetField; + retval.size = count; + retval.myWeakReference = views.Add(retval); + return retval; + } + + /// + /// Create a list view on this list containing the (first) occurrence of a particular item. + /// Returns null if the item is not in this list. + /// + /// The item to find. + /// The new list view. + public virtual IList? ViewOf(T item) + { + int index = IndexOfInner(item); + if (index < 0) { - return TrySlide(offset, size); + return null; } - /// - /// - /// - /// if this list is not a view. - /// - /// - /// - public virtual bool TrySlide(int offset, int size) + return View(index, 1); + } + + + /// + /// Create a list view on this list containing the last occurrence of a particular item. + /// Returns null if the item is not in this list. + /// + /// The item to find. + /// The new list view. + public virtual IList? LastViewOf(T item) + { + int index = LastIndexOfInner(item); + if (index < 0) { - UpdateCheck(); - if (underlying == null) - { - throw new NotAViewException("Not a view"); - } + return null; + } - int newoffset = offsetField + offset; - int newsize = size; + return View(index, 1); + } - if (newoffset < 0 || newsize < 0 || newoffset + newsize > Underlyingsize) - { - return false; - } + /// + /// Null if this list is not a view. + /// + /// Underlying list for view. + public virtual IList? Underlying => underlying; - offsetField = newoffset; - this.size = newsize; - return true; + + /// + /// + /// Offset for this list view or 0 for an underlying list. + public virtual int Offset => offsetField; + + /// + /// + /// + /// + public virtual bool IsValid => isValid; + + /// + /// Slide this list view along the underlying list. + /// + /// if this list is not a view. + /// if the operation + /// would bring either end of the view outside the underlying list. + /// The signed amount to slide: positive to slide + /// towards the end. + public virtual IList Slide(int offset) + { + if (!TrySlide(offset, size)) + { + throw new ArgumentOutOfRangeException(nameof(offset)); } - /// - /// - /// Returns null if otherView is strictly to the left of this view - /// - /// - /// If otherView does not have the same underlying list as this - /// - public virtual IList? Span(IList otherView) + return this; + } + + + /// + /// Slide this list view along the underlying list, changing its size. + /// + /// if this list is not a view. + /// if the operation + /// would bring either end of the view outside the underlying list. + /// The signed amount to slide: positive to slide + /// towards the end. + /// The new size of the view. + public virtual IList Slide(int offset, int size) + { + if (!TrySlide(offset, size)) { - if ((otherView == null) || ((otherView.Underlying ?? otherView) != (underlying ?? this))) - { - throw new IncompatibleViewException(); - } + throw new ArgumentOutOfRangeException(nameof(offset)); + } - if (otherView.Offset + otherView.Count - Offset < 0) - { - return null; - } + return this; + } - return (underlying ?? this).View(Offset, otherView.Offset + otherView.Count - Offset); + /// + /// + /// + /// if this list is not a view. + /// + /// + public virtual bool TrySlide(int offset) + { + return TrySlide(offset, size); + } + + /// + /// + /// + /// if this list is not a view. + /// + /// + /// + public virtual bool TrySlide(int offset, int size) + { + UpdateCheck(); + if (underlying == null) + { + throw new NotAViewException("Not a view"); } - /// - /// Reverse the list so the items are in the opposite sequence order. - /// - public virtual void Reverse() + int newoffset = offsetField + offset; + int newsize = size; + + if (newoffset < 0 || newsize < 0 || newoffset + newsize > UnderlyingSize) { - UpdateCheck(); - if (size == 0) - { - return; - } + return false; + } - for (int i = 0, length = size / 2, end = offsetField + size - 1; i < length; i++) - { - T swap = array[offsetField + i]; + offsetField = newoffset; + this.size = newsize; + return true; + } - array[offsetField + i] = array[end - i]; - array[end - i] = swap; - } + /// + /// + /// Returns null if otherView is strictly to the left of this view + /// + /// + /// If otherView does not have the same underlying list as this + /// + public virtual IList? Span(IList otherView) + { + if ((otherView == null) || ((otherView.Underlying ?? otherView) != (underlying ?? this))) + { + throw new IncompatibleViewException(); + } - //TODO: be more forgiving wrt. disposing - DisposeOverlappingViews(true); - (underlying ?? this).RaiseCollectionChanged(); + if (otherView.Offset + otherView.Count - Offset < 0) + { + return null; } - /// - /// Check if this list is sorted according to the default sorting order - /// for the item type T, as defined by the class - /// - /// if T is not comparable - /// True if the list is sorted, else false. - public bool IsSorted() { return IsSorted(SCG.Comparer.Default); } + return (underlying ?? this).View(Offset, otherView.Offset + otherView.Count - Offset); + } - /// - /// Check if this list is sorted according to a specific sorting order. - /// - /// The comparer defining the sorting order. - /// True if the list is sorted, else false. - public virtual bool IsSorted(SCG.IComparer c) + /// + /// Reverse the list so the items are in the opposite sequence order. + /// + public virtual void Reverse() + { + UpdateCheck(); + if (size == 0) { - ValidityCheck(); - for (int i = offsetField + 1, end = offsetField + size; i < end; i++) - { - if (c.Compare(array[i - 1], array[i]) > 0) - { - return false; - } - } - - return true; + return; } - /// - /// Sort the items of the list according to the default sorting order - /// for the item type T, as defined by the Comparer[T] class - /// (). - /// - /// if T is not comparable - public virtual void Sort() + for (int i = 0, length = size / 2, end = offsetField + size - 1; i < length; i++) { - Sort(SCG.Comparer.Default); + (array[end - i], array[offsetField + i]) = (array[offsetField + i], array[end - i]); } + //TODO: be more forgiving wrt. disposing + DisposeOverlappingViews(true); + (underlying ?? this).RaiseCollectionChanged(); + } - /// - /// Sort the items of the list according to a specific sorting order. - /// - /// The comparer defining the sorting order. - public virtual void Sort(SCG.IComparer comparer) + /// + /// Check if this list is sorted according to the default sorting order + /// for the item type T, as defined by the class + /// + /// if T is not comparable + /// True if the list is sorted, else false. + public bool IsSorted() { return IsSorted(SCG.Comparer.Default); } + + /// + /// Check if this list is sorted according to a specific sorting order. + /// + /// The comparer defining the sorting order. + /// True if the list is sorted, else false. + public virtual bool IsSorted(SCG.IComparer c) + { + ValidityCheck(); + for (int i = offsetField + 1, end = offsetField + size; i < end; i++) { - UpdateCheck(); - if (size == 0) + if (c.Compare(array[i - 1], array[i]) > 0) { - return; + return false; } + } + + return true; + } + + /// + /// Sort the items of the list according to the default sorting order + /// for the item type T, as defined by the Comparer[T] class + /// (). + /// + /// if T is not comparable + public virtual void Sort() + { + Sort(SCG.Comparer.Default); + } - Sorting.IntroSort(array, offsetField, size, comparer); - DisposeOverlappingViews(false); - (underlying ?? this).RaiseCollectionChanged(); + /// + /// Sort the items of the list according to a specific sorting order. + /// + /// The comparer defining the sorting order. + public virtual void Sort(SCG.IComparer comparer) + { + UpdateCheck(); + if (size == 0) + { + return; } + Sorting.IntroSort(array, offsetField, size, comparer); + DisposeOverlappingViews(false); - /// - /// Randomly shuffle the items of this list. - /// - public virtual void Shuffle() { Shuffle(new C5Random()); } + (underlying ?? this).RaiseCollectionChanged(); + } - /// - /// Shuffle the items of this list according to a specific random source. - /// - /// The random source. - public virtual void Shuffle(Random rnd) + /// + /// Randomly shuffle the items of this list. + /// + public virtual void Shuffle() { Shuffle(new C5Random()); } + + + /// + /// Shuffle the items of this list according to a specific random source. + /// + /// The random source. + public virtual void Shuffle(Random rnd) + { + UpdateCheck(); + if (size == 0) { - UpdateCheck(); - if (size == 0) - { - return; - } + return; + } - for (int i = offsetField, top = offsetField + size, end = top - 1; i < end; i++) + for (int i = offsetField, top = offsetField + size, end = top - 1; i < end; i++) + { + int j = rnd.Next(i, top); + if (j != i) { - int j = rnd.Next(i, top); - if (j != i) - { - T tmp = array[i]; - array[i] = array[j]; - array[j] = tmp; - } + (array[j], array[i]) = (array[i], array[j]); } - DisposeOverlappingViews(false); - - (underlying ?? this).RaiseCollectionChanged(); } - #endregion + DisposeOverlappingViews(false); - #region IIndexed Members + (underlying ?? this).RaiseCollectionChanged(); + } + #endregion - /// - /// Search for an item in the list going forwards from the start. - /// - /// Item to search for. - /// Index of item from start. - public virtual int IndexOf(T item) { ValidityCheck(); return IndexOfInner(item); } + #region IIndexed Members + /// + /// Search for an item in the list going forwards from the start. + /// + /// Item to search for. + /// Index of item from start. + public virtual int IndexOf(T item) { ValidityCheck(); return IndexOfInner(item); } - /// - /// Search for an item in the list going backwards from the end. - /// - /// Item to search for. - /// Index of item from the end. - public virtual int LastIndexOf(T item) { ValidityCheck(); return LastIndexOfInner(item); } + /// + /// Search for an item in the list going backwards from the end. + /// + /// Item to search for. + /// Index of item from the end. + public virtual int LastIndexOf(T item) { ValidityCheck(); return LastIndexOfInner(item); } - /// - /// Remove the item at a specific position of the list. - /// - /// if index is negative or - /// >= the size of the collection. - /// The index of the item to remove. - /// The removed item. - public virtual T RemoveAt(int index) - { - UpdateCheck(); - if (index < 0 || index >= size) - { - throw new IndexOutOfRangeException("Index out of range for sequenced collection"); - } - T item = RemoveAtInner(index); - (underlying ?? this).RaiseForRemoveAt(offsetField + index, item); - return item; + /// + /// Remove the item at a specific position of the list. + /// + /// if index is negative or + /// >= the size of the collection. + /// The index of the item to remove. + /// The removed item. + public virtual T RemoveAt(int index) + { + UpdateCheck(); + if (index < 0 || index >= size) + { + throw new IndexOutOfRangeException("Index out of range for sequenced collection"); } + T item = RemoveAtInner(index); + (underlying ?? this).RaiseForRemoveAt(offsetField + index, item); + return item; + } - /// - /// Remove all items in an index interval. - /// - /// If start - /// and count does not describe a valid interval in the list - /// The index of the first item to remove. - /// The number of items to remove. - public virtual void RemoveInterval(int start, int count) + + /// + /// Remove all items in an index interval. + /// + /// If start + /// and count does not describe a valid interval in the list + /// The index of the first item to remove. + /// The number of items to remove. + public virtual void RemoveInterval(int start, int count) + { + UpdateCheck(); + if (count == 0) { - UpdateCheck(); - if (count == 0) - { - return; - } + return; + } - CheckRange(start, count); - start += offsetField; - FixViewsBeforeRemove(start, count); + CheckRange(start, count); + start += offsetField; + FixViewsBeforeRemove(start, count); - Array.Copy(array, start + count, array, start, Underlyingsize - start - count); - AddToSize(-count); - Array.Clear(array, Underlyingsize, count); + Array.Copy(array, start + count, array, start, UnderlyingSize - start - count); + AddToSize(-count); + Array.Clear(array, UnderlyingSize, count); - (underlying ?? this).RaiseForRemoveInterval(start, count); - } + (underlying ?? this).RaiseForRemoveInterval(start, count); + } - private void RaiseForRemoveInterval(int start, int count) + private void RaiseForRemoveInterval(int start, int count) + { + if (ActiveEvents != 0) { - if (ActiveEvents != 0) - { - RaiseCollectionCleared(size == 0, count, start); - RaiseCollectionChanged(); - } + RaiseCollectionCleared(size == 0, count, start); + RaiseCollectionChanged(); } - #endregion + } + #endregion - #region ICollection Members + #region ICollection Members - /// - /// The value is symbolic indicating the type of asymptotic complexity - /// in terms of the size of this collection (worst-case or amortized as - /// relevant). - /// - /// Speed.Linear - public virtual Speed ContainsSpeed => Speed.Linear; + /// + /// The value is symbolic indicating the type of asymptotic complexity + /// in terms of the size of this collection (worst-case or amortized as + /// relevant). + /// + /// Speed.Linear + public virtual Speed ContainsSpeed => Speed.Linear; - /// - /// - /// - /// - public override int GetUnsequencedHashCode() - { ValidityCheck(); return base.GetUnsequencedHashCode(); } + /// + /// + /// + /// + public override int GetUnsequencedHashCode() + { ValidityCheck(); return base.GetUnsequencedHashCode(); } - /// - /// - /// - /// - /// - public override bool UnsequencedEquals(ICollection that) - { ValidityCheck(); return base.UnsequencedEquals(that); } + /// + /// + /// + /// + /// + public override bool UnsequencedEquals(ICollection that) + { ValidityCheck(); return base.UnsequencedEquals(that); } - /// - /// Check if this collection contains (an item equivalent to according to the - /// itemequalityComparer) a particular value. - /// - /// The value to check for. - /// True if the items is in this collection. - public virtual bool Contains(T item) - { ValidityCheck(); return IndexOfInner(item) >= 0; } + /// + /// Check if this collection contains (an item equivalent to according to the + /// itemequalityComparer) a particular value. + /// + /// The value to check for. + /// True if the items is in this collection. + public virtual bool Contains(T item) + { ValidityCheck(); return IndexOfInner(item) >= 0; } - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, return in the ref argument (a - /// binary copy of) the actual value found. - /// - /// The value to look for. - /// True if the items is in this collection. - public virtual bool Find(ref T item) + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, return in the ref argument (a + /// binary copy of) the actual value found. + /// + /// The value to look for. + /// True if the items is in this collection. + public virtual bool Find(ref T item) + { + ValidityCheck(); + + int i; + + if ((i = IndexOfInner(item)) >= 0) { - ValidityCheck(); + item = array[offsetField + i]; + return true; + } + + return false; + } + - int i; + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// to with a binary copy of the supplied value. This will only update the first + /// mathching item. + /// + /// Value to update. + /// True if the item was found and hence updated. + public virtual bool Update(T item) + { + return Update(item, out _); + } + + /// + /// + /// + /// + /// + /// + public virtual bool Update(T item, out T olditem) + { + UpdateCheck(); + int i; - if ((i = IndexOfInner(item)) >= 0) - { - item = array[offsetField + i]; - return true; - } + if ((i = IndexOfInner(item)) >= 0) + { + olditem = array[offsetField + i]; + array[offsetField + i] = item; - return false; + (underlying ?? this).RaiseForUpdate(item, olditem); + return true; } + olditem = default; + return false; + } - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// to with a binary copy of the supplied value. This will only update the first - /// mathching item. - /// - /// Value to update. - /// True if the item was found and hence updated. - public virtual bool Update(T item) + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, return in the ref argument (a + /// binary copy of) the actual value found. Else, add the item to the collection. + /// + /// The value to look for. + /// True if the item was found (hence not added). + public virtual bool FindOrAdd(ref T item) + { + UpdateCheck(); + if (Find(ref item)) { - return Update(item, out _); + return true; } - /// - /// - /// - /// - /// - /// - public virtual bool Update(T item, out T olditem) - { - UpdateCheck(); - int i; - - if ((i = IndexOfInner(item)) >= 0) - { - olditem = array[offsetField + i]; - array[offsetField + i] = item; + Add(item); + return false; + } - (underlying ?? this).RaiseForUpdate(item, olditem); - return true; - } - olditem = default; - return false; + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// to with a binary copy of the supplied value. This will only update the first + /// matching item. + /// + /// Value to update. + /// True if the item was found and hence updated. + public virtual bool UpdateOrAdd(T item) + { + UpdateCheck(); + if (Update(item)) + { + return true; } - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, return in the ref argument (a - /// binary copy of) the actual value found. Else, add the item to the collection. - /// - /// The value to look for. - /// True if the item was found (hence not added). - public virtual bool FindOrAdd(ref T item) - { - UpdateCheck(); - if (Find(ref item)) - { - return true; - } + Add(item); + return false; + } - Add(item); - return false; + /// + /// + /// + /// + /// + /// + public virtual bool UpdateOrAdd(T item, out T olditem) + { + UpdateCheck(); + if (Update(item, out olditem)) + { + return true; } + Add(item); + olditem = default; + return false; + } - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// to with a binary copy of the supplied value. This will only update the first - /// matching item. - /// - /// Value to update. - /// True if the item was found and hence updated. - public virtual bool UpdateOrAdd(T item) - { - UpdateCheck(); - if (Update(item)) - { - return true; - } + /// + /// Remove a particular item from this list. The item will be searched + /// for from the end of the list if FIFO == false (the default), + /// else from the start. + /// + /// The value to remove. + /// True if the item was found (and removed). + public virtual bool Remove(T item) + { + UpdateCheck(); - Add(item); - return false; - } + int i = fIFO ? IndexOfInner(item) : LastIndexOfInner(item); - /// - /// - /// - /// - /// - /// - public virtual bool UpdateOrAdd(T item, out T olditem) + if (i < 0) { - UpdateCheck(); - if (Update(item, out olditem)) - { - return true; - } - - Add(item); - olditem = default; return false; } - /// - /// Remove a particular item from this list. The item will be searched - /// for from the end of the list if FIFO == false (the default), - /// else from the start. - /// - /// The value to remove. - /// True if the item was found (and removed). - public virtual bool Remove(T item) - { - UpdateCheck(); - - int i = fIFO ? IndexOfInner(item) : LastIndexOfInner(item); + T removeditem = RemoveAtInner(i); + (underlying ?? this).RaiseForRemove(removeditem); + return true; + } - if (i < 0) - { - return false; - } - T removeditem = RemoveAtInner(i); - (underlying ?? this).RaiseForRemove(removeditem); - return true; - } + /// + /// Remove the first copy of a particular item from this collection if found. + /// If an item was removed, report a binary copy of the actual item removed in + /// the argument. The item will be searched + /// for from the end of the list if FIFO == false (the default), + /// else from the start. + /// + /// The value to remove. + /// The removed value. + /// True if the item was found (and removed). + public virtual bool Remove(T item, out T removeditem) + { + UpdateCheck(); + int i = fIFO ? IndexOfInner(item) : LastIndexOfInner(item); - /// - /// Remove the first copy of a particular item from this collection if found. - /// If an item was removed, report a binary copy of the actual item removed in - /// the argument. The item will be searched - /// for from the end of the list if FIFO == false (the default), - /// else from the start. - /// - /// The value to remove. - /// The removed value. - /// True if the item was found (and removed). - public virtual bool Remove(T item, out T removeditem) + if (i < 0) { - UpdateCheck(); + removeditem = default; + return false; + } - int i = fIFO ? IndexOfInner(item) : LastIndexOfInner(item); + removeditem = RemoveAtInner(i); + (underlying ?? this).RaiseForRemove(removeditem); + return true; + } - if (i < 0) - { - removeditem = default; - return false; - } - removeditem = RemoveAtInner(i); - (underlying ?? this).RaiseForRemove(removeditem); - return true; + //TODO: remove from end or according to FIFO? + /// + /// Remove all items in another collection from this one, taking multiplicities into account. + /// Matching items will be removed from the front. Current implementation is not optimal. + /// + /// The items to remove. + public virtual void RemoveAll(SCG.IEnumerable items) + { + UpdateCheck(); + if (size == 0) + { + return; + } + //TODO: reactivate the old code for small sizes + HashBag toremove = new(itemEqualityComparer); + toremove.AddAll(items); + if (toremove.Count == 0) + { + return; } + RaiseForRemoveAllHandler raiseHandler = new(underlying ?? this); + bool mustFire = raiseHandler.MustFire; + ViewHandler viewHandler = new(this); + int j = offsetField; + int removed = 0; + int i = offsetField, end = offsetField + size; - //TODO: remove from end or according to FIFO? - /// - /// Remove all items in another collection from this one, taking multiplicities into account. - /// Matching items will be removed from the front. Current implementation is not optimal. - /// - /// The items to remove. - public virtual void RemoveAll(SCG.IEnumerable items) + while (i < end) { - UpdateCheck(); - if (size == 0) - { - return; - } - //TODO: reactivate the old code for small sizes - HashBag toremove = new HashBag(itemequalityComparer); - toremove.AddAll(items); - if (toremove.Count == 0) + T item; + //pass by a stretch of nodes + while (i < end && !toremove.Contains(item = array[i])) { - return; + //if (j - /// - /// - /// - void RemoveAll(Func predicate) + if (removed == 0) { - updatecheck(); - if (size == 0) - return; - RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); - bool mustFire = raiseHandler.MustFire; - ViewHandler viewHandler = new ViewHandler(this); - int j = offsetField; - int removed = 0; - int i = offsetField, end = offsetField + size; - - while (i < end) - { - T item; - //pass by a stretch of nodes - while (i < end && !predicate(item = array[i])) - { - updatecheck(); - - //if (j - /// Remove all items from this collection, resetting internal array size. - /// - public override void Clear() - { - if (underlying == null) + /* + /// + /// + /// + /// + void RemoveAll(Func predicate) + { + updatecheck(); + if (size == 0) + return; + RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); + bool mustFire = raiseHandler.MustFire; + ViewHandler viewHandler = new ViewHandler(this); + int j = offsetField; + int removed = 0; + int i = offsetField, end = offsetField + size; + + while (i < end) + { + T item; + //pass by a stretch of nodes + while (i < end && !predicate(item = array[i])) { - UpdateCheck(); - if (size == 0) - { - return; - } - - int oldsize = size; - FixViewsBeforeRemove(0, size); + updatecheck(); - array = new T[8]; - size = 0; - (underlying ?? this).RaiseForRemoveInterval(offsetField, oldsize); + //if (j - /// Remove all items not in some other collection from this one, taking multiplicities into account. - /// Items are retained front first. - /// - /// The items to retain. - public virtual void RetainAll(SCG.IEnumerable items) + if (mustFire) + raiseHandler.Raise(); + } + */ + + /// + /// Remove all items from this collection, resetting internal array size. + /// + public override void Clear() + { + if (underlying == null) { UpdateCheck(); if (size == 0) @@ -1814,636 +1641,684 @@ public virtual void RetainAll(SCG.IEnumerable items) return; } - HashBag toretain = new HashBag(itemequalityComparer); - toretain.AddAll(items); - if (toretain.Count == 0) + int oldsize = size; + FixViewsBeforeRemove(0, size); + + array = new T[8]; + size = 0; + (underlying ?? this).RaiseForRemoveInterval(offsetField, oldsize); + } + else + { + RemoveInterval(0, size); + } + } + + /// + /// Remove all items not in some other collection from this one, taking multiplicities into account. + /// Items are retained front first. + /// + /// The items to retain. + public virtual void RetainAll(SCG.IEnumerable items) + { + UpdateCheck(); + if (size == 0) + { + return; + } + + HashBag toretain = new(itemEqualityComparer); + toretain.AddAll(items); + if (toretain.Count == 0) + { + Clear(); + return; + } + RaiseForRemoveAllHandler raiseHandler = new(underlying ?? this); + bool mustFire = raiseHandler.MustFire; + ViewHandler viewHandler = new(this); + int j = offsetField; + int removed = 0; + int i = offsetField, end = offsetField + size; + + while (i < end) + { + T item; + //pass by a stretch of nodes + while (i < end && toretain.Remove(item = array[i])) { - Clear(); - return; + //if (j - /// - /// - /// - void RetainAll(Func predicate) - { - updatecheck(); - if (size == 0) - return; - RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); - bool mustFire = raiseHandler.MustFire; - ViewHandler viewHandler = new ViewHandler(this); - int j = offsetField; - int removed = 0; - int i = offsetField, end = offsetField + size; - - while (i < end) + /* + /// + /// + /// + /// + void RetainAll(Func predicate) + { + updatecheck(); + if (size == 0) + return; + RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); + bool mustFire = raiseHandler.MustFire; + ViewHandler viewHandler = new ViewHandler(this); + int j = offsetField; + int removed = 0; + int i = offsetField, end = offsetField + size; + + while (i < end) + { + T item; + //pass by a stretch of nodes + while (i < end && predicate(item = array[i])) { - T item; - //pass by a stretch of nodes - while (i < end && predicate(item = array[i])) - { - updatecheck(); - - //if (j - /// Check if this collection contains all the values in another collection, - /// taking multiplicities into account. - /// Current implementation is not optimal. - /// - /// The - /// True if all values in itemsis in this collection. - public virtual bool ContainsAll(SCG.IEnumerable items) + /// + /// Check if this collection contains all the values in another collection, + /// taking multiplicities into account. + /// Current implementation is not optimal. + /// + /// The + /// True if all values in itemsis in this collection. + public virtual bool ContainsAll(SCG.IEnumerable items) + { + ValidityCheck(); + + //TODO: use aux hash bag to obtain linear time procedure + HashBag tomatch = new(itemEqualityComparer); + tomatch.AddAll(items); + if (tomatch.Count == 0) { - ValidityCheck(); + return true; + } - //TODO: use aux hash bag to obtain linear time procedure - HashBag tomatch = new HashBag(itemequalityComparer); - tomatch.AddAll(items); + for (int i = offsetField, end = offsetField + size; i < end; i++) + { + tomatch.Remove(array[i]); if (tomatch.Count == 0) { return true; } - - for (int i = offsetField, end = offsetField + size; i < end; i++) - { - tomatch.Remove(array[i]); - if (tomatch.Count == 0) - { - return true; - } - } - return false; } + return false; + } - /// - /// Count the number of items of the collection equal to a particular value. - /// Returns 0 if and only if the value is not in the collection. - /// - /// The value to count. - /// The number of copies found. - public virtual int ContainsCount(T item) - { - ValidityCheck(); + /// + /// Count the number of items of the collection equal to a particular value. + /// Returns 0 if and only if the value is not in the collection. + /// + /// The value to count. + /// The number of copies found. + public virtual int ContainsCount(T item) + { + ValidityCheck(); - int count = 0; - for (int i = 0; i < size; i++) + int count = 0; + for (int i = 0; i < size; i++) + { + if (Equals(item, array[offsetField + i])) { - if (Equals(item, array[offsetField + i])) - { - count++; - } + count++; } - - return count; } - /// - /// - /// - /// - public virtual ICollectionValue UniqueItems() - { - HashBag hashbag = new HashBag(itemequalityComparer); - hashbag.AddAll(this); - return hashbag.UniqueItems(); - } + return count; + } + + /// + /// + /// + /// + public virtual ICollectionValue UniqueItems() + { + HashBag hashbag = new(itemEqualityComparer); + hashbag.AddAll(this); + return hashbag.UniqueItems(); + } + + /// + /// + /// + /// + public virtual ICollectionValue> ItemMultiplicities() + { + HashBag hashbag = new(itemEqualityComparer); + hashbag.AddAll(this); + return hashbag.ItemMultiplicities(); + } - /// - /// - /// - /// - public virtual ICollectionValue> ItemMultiplicities() - { - HashBag hashbag = new HashBag(itemequalityComparer); - hashbag.AddAll(this); - return hashbag.ItemMultiplicities(); - } + /// + /// Remove all items equal to a given one. + /// + /// The value to remove. + public virtual void RemoveAllCopies(T item) + { + UpdateCheck(); + if (size == 0) + { + return; + } - /// - /// Remove all items equal to a given one. - /// - /// The value to remove. - public virtual void RemoveAllCopies(T item) + RaiseForRemoveAllHandler raiseHandler = new(underlying ?? this); + bool mustFire = raiseHandler.MustFire; + ViewHandler viewHandler = new(this); + int j = offsetField; + int removed = 0; + int i = offsetField, end = offsetField + size; + while (i < end) { - UpdateCheck(); - if (size == 0) + //pass by a stretch of nodes + while (i < end && !Equals(item, array[i])) { - return; + array[j++] = array[i++]; } - RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); - bool mustFire = raiseHandler.MustFire; - ViewHandler viewHandler = new ViewHandler(this); - int j = offsetField; - int removed = 0; - int i = offsetField, end = offsetField + size; - while (i < end) + viewHandler.SkipEndpoints(removed, i); + //Remove a stretch of nodes + while (i < end && Equals(item, array[i])) { - //pass by a stretch of nodes - while (i < end && !Equals(item, array[i])) + if (mustFire) { - array[j++] = array[i++]; + raiseHandler.Remove(array[i]); } - viewHandler.SkipEndpoints(removed, i); - //Remove a stretch of nodes - while (i < end && Equals(item, array[i])) - { - if (mustFire) - { - raiseHandler.Remove(array[i]); - } - - removed++; - i++; - viewHandler.UpdateViewSizesAndCounts(removed, i); - } - } - if (removed == 0) - { - return; + removed++; + i++; + viewHandler.UpdateViewSizesAndCounts(removed, i); } - - viewHandler.UpdateViewSizesAndCounts(removed, Underlyingsize); - Array.Copy(array, offsetField + size, array, j, Underlyingsize - offsetField - size); - AddToSize(-removed); - Array.Clear(array, Underlyingsize, removed); - raiseHandler.Raise(); + } + if (removed == 0) + { + return; } + viewHandler.UpdateViewSizesAndCounts(removed, UnderlyingSize); + Array.Copy(array, offsetField + size, array, j, UnderlyingSize - offsetField - size); + AddToSize(-removed); + Array.Clear(array, UnderlyingSize, removed); + raiseHandler.Raise(); + } - //TODO: check views - /// - /// Check the integrity of the internal data structures of this array list. - /// - /// True if check does not fail. - public override bool Check() - { - bool retval = true; - if (Underlyingsize > array.Length) - { - Logger.Log(string.Format("underlyingsize ({0}) > array.Length ({1})", size, array.Length)); - return false; - } + //TODO: check views + /// + /// Check the integrity of the internal data structures of this array list. + /// + /// True if check does not fail. + public override bool Check() + { + bool retval = true; - if (offsetField + size > Underlyingsize) - { - Logger.Log(string.Format("offset({0})+size({1}) > underlyingsize ({2})", offsetField, size, Underlyingsize)); - return false; - } + if (UnderlyingSize > array.Length) + { + Logger.Log(string.Format("underlyingsize ({0}) > array.Length ({1})", size, array.Length)); + return false; + } - if (offsetField < 0) - { - Logger.Log(string.Format("offset({0}) < 0", offsetField)); - return false; - } + if (offsetField + size > UnderlyingSize) + { + Logger.Log(string.Format("offset({0})+size({1}) > underlyingsize ({2})", offsetField, size, UnderlyingSize)); + return false; + } + + if (offsetField < 0) + { + Logger.Log(string.Format("offset({0}) < 0", offsetField)); + return false; + } - for (int i = 0; i < Underlyingsize; i++) + for (int i = 0; i < UnderlyingSize; i++) + { + if (array[i] == null) { - if (array[i] == null) - { - Logger.Log(string.Format("Bad element: null at (base)index {0}", i)); - retval = false; - } + Logger.Log(string.Format("Bad element: null at (base)index {0}", i)); + retval = false; } + } - for (int i = Underlyingsize, length = array.Length; i < length; i++) + for (int i = UnderlyingSize, length = array.Length; i < length; i++) + { + if (!Equals(array[i], default)) { - if (!Equals(array[i], default)) - { - Logger.Log(string.Format("Bad element: != default(T) at (base)index {0}", i)); - retval = false; - } + Logger.Log(string.Format("Bad element: != default(T) at (base)index {0}", i)); + retval = false; } + } + { + ArrayList u = underlying ?? this; + if (u.views != null) { - ArrayList u = underlying ?? this; - if (u.views != null) + foreach (ArrayList v in u.views) { - foreach (ArrayList v in u.views) + if (u.array != v.array) { - if (u.array != v.array) - { - Logger.Log(string.Format("View from {0} of length {1} has different base array than the underlying list", v.offsetField, v.size)); - retval = false; - } + Logger.Log(string.Format("View from {0} of length {1} has different base array than the underlying list", v.offsetField, v.size)); + retval = false; } } } - - return retval; } - #endregion + return retval; + } - #region IExtensible Members + #endregion - /// - /// - /// - /// True, indicating array list has bag semantics. - public virtual bool AllowsDuplicates => true; + #region IExtensible Members - /// - /// By convention this is true for any collection with set semantics. - /// - /// True if only one representative of a group of equal items - /// is kept in the collection together with the total count. - public virtual bool DuplicatesByCounting => false; + /// + /// + /// + /// True, indicating array list has bag semantics. + public virtual bool AllowsDuplicates => true; - /// - /// Add an item to end of this list. - /// - /// The item to add. - /// True - public virtual bool Add(T item) - { - UpdateCheck(); + /// + /// By convention this is true for any collection with set semantics. + /// + /// True if only one representative of a group of equal items + /// is kept in the collection together with the total count. + public virtual bool DuplicatesByCounting => false; - BaseInsertInner(size, item); + /// + /// Add an item to end of this list. + /// + /// The item to add. + /// True + public virtual bool Add(T item) + { + UpdateCheck(); - (underlying ?? this).RaiseForAdd(item); - return true; - } + BaseInsertInner(size, item); + (underlying ?? this).RaiseForAdd(item); + return true; + } - /// - /// Add the elements from another collection to this collection. - /// - /// - public virtual void AddAll(SCG.IEnumerable items) + + /// + /// Add the elements from another collection to this collection. + /// + /// + public virtual void AddAll(SCG.IEnumerable items) + { + UpdateCheck(); + int toadd = CountItems(items); + if (toadd == 0) { - UpdateCheck(); - int toadd = CountItems(items); - if (toadd == 0) - { - return; - } + return; + } - if (toadd + Underlyingsize > array.Length) - { - Expand(toadd + Underlyingsize, Underlyingsize); - } + if (toadd + UnderlyingSize > array.Length) + { + Expand(toadd + UnderlyingSize, UnderlyingSize); + } + + int i = size + offsetField; + if (UnderlyingSize > i) + { + Array.Copy(array, i, array, i + toadd, UnderlyingSize - i); + } - int i = size + offsetField; - if (Underlyingsize > i) + try + { + foreach (T item in items) { - Array.Copy(array, i, array, i + toadd, Underlyingsize - i); + array[i++] = item; } - - try + } + finally + { + int added = i - size - offsetField; + if (added < toadd) { - foreach (T item in items) - { - array[i++] = item; - } + Array.Copy(array, size + offsetField + toadd, array, i, UnderlyingSize - size - offsetField); + Array.Clear(array, UnderlyingSize + added, toadd - added); } - finally + if (added > 0) { - int added = i - size - offsetField; - if (added < toadd) - { - Array.Copy(array, size + offsetField + toadd, array, i, Underlyingsize - size - offsetField); - Array.Clear(array, Underlyingsize + added, toadd - added); - } - if (added > 0) - { - AddToSize(added); - FixViewsAfterInsert(added, i - added); - (underlying ?? this).RaiseForAddAll(i - added, added); - } + AddToSize(added); + FixViewsAfterInsert(added, i - added); + (underlying ?? this).RaiseForAddAll(i - added, added); } } - private void RaiseForAddAll(int start, int added) + } + private void RaiseForAddAll(int start, int added) + { + if ((ActiveEvents & EventType.Added) != 0) { - if ((ActiveEvents & EventType.Added) != 0) + for (int i = start, end = start + added; i < end; i++) { - for (int i = start, end = start + added; i < end; i++) - { - RaiseItemsAdded(array[i], 1); - } + RaiseItemsAdded(array[i], 1); } - - RaiseCollectionChanged(); } - #endregion + RaiseCollectionChanged(); + } - #region IDirectedEnumerable Members + #endregion - /// - /// Create a collection containing the same items as this collection, but - /// whose enumerator will enumerate the items backwards. The new collection - /// will become invalid if the original is modified. Method typically used as in - /// foreach (T x in coll.Backwards()) {...} - /// - /// The backwards collection. - IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } + #region IDirectedEnumerable Members - #endregion + /// + /// Create a collection containing the same items as this collection, but + /// whose enumerator will enumerate the items backwards. The new collection + /// will become invalid if the original is modified. Method typically used as in + /// foreach (T x in coll.Backwards()) {...} + /// + /// The backwards collection. + IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } - #region ICollectionValue Members - /// - /// - /// - /// The number of items in this collection - public override int Count { get { ValidityCheck(); return size; } } - #endregion + #endregion - #region IEnumerable Members - //TODO: make tests of all calls on a disposed view throws the right exception! (Which should be C5.InvalidListViewException) - /// - /// Create an enumerator for the collection - /// - /// The enumerator - public override SCG.IEnumerator GetEnumerator() - { - ValidityCheck(); - return base.GetEnumerator(); - } - #endregion + #region ICollectionValue Members + /// + /// + /// + /// The number of items in this collection + public override int Count { get { ValidityCheck(); return size; } } + #endregion + #region IEnumerable Members + //TODO: make tests of all calls on a disposed view throws the right exception! (Which should be C5.InvalidListViewException) + /// + /// Create an enumerator for the collection + /// + /// The enumerator + public override SCG.IEnumerator GetEnumerator() + { + ValidityCheck(); + return base.GetEnumerator(); + } + #endregion - #region IStack Members - /// - /// Push an item to the top of the stack. - /// - /// The item - public virtual void Push(T item) - { - InsertLast(item); - } + #region IStack Members - /// - /// Pop the item at the top of the stack from the stack. - /// - /// The popped item. - public virtual T Pop() - { - return RemoveLast(); - } + /// + /// Push an item to the top of the stack. + /// + /// The item + public virtual void Push(T item) + { + InsertLast(item); + } - #endregion + /// + /// Pop the item at the top of the stack from the stack. + /// + /// The popped item. + public virtual T Pop() + { + return RemoveLast(); + } - #region IQueue Members + #endregion - /// - /// Enqueue an item at the back of the queue. - /// - /// The item - public virtual void Enqueue(T item) - { - InsertLast(item); - } + #region IQueue Members - /// - /// Dequeue an item from the front of the queue. - /// - /// The item - public virtual T Dequeue() - { - return RemoveFirst(); - } + /// + /// Enqueue an item at the back of the queue. + /// + /// The item + public virtual void Enqueue(T item) + { + InsertLast(item); + } - #endregion - #region IDisposable Members + /// + /// Dequeue an item from the front of the queue. + /// + /// The item + public virtual T Dequeue() + { + return RemoveFirst(); + } - /// - /// Invalidate this list. If a view, just invalidate the view. - /// If not a view, invalidate the list and all views on it. - /// - public virtual void Dispose() - { - Dispose(false); - } + #endregion + #region IDisposable Members - private void Dispose(bool disposingUnderlying) + /// + /// Invalidate this list. If a view, just invalidate the view. + /// If not a view, invalidate the list and all views on it. + /// + public virtual void Dispose() + { + GC.SuppressFinalize(this); + + Dispose(false); + } + + private void Dispose(bool disposingUnderlying) + { + if (isValid) { - if (isValid) + if (underlying != null) { - if (underlying != null) + isValid = false; + if (!disposingUnderlying && views != null) { - isValid = false; - if (!disposingUnderlying && views != null) - { - views.Remove(myWeakReference!); - } - - underlying = null; - views = null; - myWeakReference = null; + views.Remove(myWeakReference!); } - else + + underlying = null; + views = null; + myWeakReference = null; + } + else + { + //isValid = false; + if (views != null) { - //isValid = false; - if (views != null) + foreach (ArrayList view in views) { - foreach (ArrayList view in views) - { - view.Dispose(true); - } + view.Dispose(true); } - - Clear(); } + + Clear(); } } + } - #endregion + #endregion + + #region ISerializable Members + /* +/// +/// +/// +/// +/// +public ArrayList(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : + this(info.GetInt32("sz"),(SCG.IEqualityComparer)(info.GetValue("eq",typeof(SCG.IEqualityComparer)))) +{ + size = info.GetInt32("sz"); + for (int i = 0; i < size; i++) + { + array[i] = (T)(info.GetValue("elem" + i,typeof(T))); + } - #region ISerializable Members - /* - /// - /// - /// - /// - /// - public ArrayList(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : - this(info.GetInt32("sz"),(SCG.IEqualityComparer)(info.GetValue("eq",typeof(SCG.IEqualityComparer)))) - { - size = info.GetInt32("sz"); - for (int i = 0; i < size; i++) - { - array[i] = (T)(info.GetValue("elem" + i,typeof(T))); - } +} + +/// +/// +/// +/// +/// +public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) +{ + info.AddValue("sz", size); + info.AddValue("eq", EqualityComparer); + for (int i = 0; i < size; i++) + { + info.AddValue("elem" + i, array[i + offset]); + } +} +*/ + #endregion + + #region System.Collections.Generic.IList Members + void System.Collections.Generic.IList.RemoveAt(int index) + { + RemoveAt(index); } - /// - /// - /// - /// - /// - public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) + void System.Collections.Generic.ICollection.Add(T item) { - info.AddValue("sz", size); - info.AddValue("eq", EqualityComparer); - for (int i = 0; i < size; i++) - { - info.AddValue("elem" + i, array[i + offset]); - } + Add(item); } -*/ - #endregion - #region System.Collections.Generic.IList Members + #endregion - void System.Collections.Generic.IList.RemoveAt(int index) + #region System.Collections.ICollection Members + + bool System.Collections.ICollection.IsSynchronized => false; + + [Obsolete] + object System.Collections.ICollection.SyncRoot => underlying != null ? ((System.Collections.ICollection)underlying).SyncRoot : array; + + void System.Collections.ICollection.CopyTo(Array arr, int index) + { + if (index < 0 || index + Count > arr.Length) { - RemoveAt(index); + throw new ArgumentOutOfRangeException(nameof(index)); } - void System.Collections.Generic.ICollection.Add(T item) + foreach (T item in this) { - Add(item); + arr.SetValue(item, index++); } + } - #endregion - - #region System.Collections.ICollection Members - - bool System.Collections.ICollection.IsSynchronized => false; + #endregion - [Obsolete] - Object System.Collections.ICollection.SyncRoot => underlying != null ? ((System.Collections.ICollection)underlying).SyncRoot : array; + #region System.Collections.IList Members - void System.Collections.ICollection.CopyTo(Array arr, int index) + object? System.Collections.IList.this[int index] + { + get => this[index]!; + set { - if (index < 0 || index + Count > arr.Length) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } + if (value is null && default(T) is not null) throw new ArgumentNullException(nameof(value)); + if (value is not T) throw new ArgumentException("Wrong type", nameof(value)); - foreach (T item in this) - { - arr.SetValue(item, index++); - } + this[index] = (T)value; } + } - #endregion + int System.Collections.IList.Add(object? value) + { + if (value is null && default(T) is not null) throw new ArgumentNullException(nameof(value)); + if (value is not T) throw new ArgumentException("Wrong type", nameof(value)); - #region System.Collections.IList Members + bool added = Add((T)value!); + // What position to report if item not added? SC.IList.Add doesn't say + return added ? Count - 1 : -1; + } - Object System.Collections.IList.this[int index] - { - get => this[index]!; - set => this[index] = (T)value; - } + bool System.Collections.IList.Contains(object? value) + { + if (value is null && default(T) is not null) return false; + if (value is not T) return false; - int System.Collections.IList.Add(Object o) - { - bool added = Add((T)o); - // What position to report if item not added? SC.IList.Add doesn't say - return added ? Count - 1 : -1; - } + return Contains((T)value); + } - bool System.Collections.IList.Contains(Object o) - { - return Contains((T)o); - } + int System.Collections.IList.IndexOf(object? value) + { + if (value is null && default(T) is not null) return -1; + if (value is not T) return -1; - int System.Collections.IList.IndexOf(Object o) - { - return Math.Max(-1, IndexOf((T)o)); - } + return Math.Max(-1, IndexOf((T)value)); + } - void System.Collections.IList.Insert(int index, Object o) - { - Insert(index, (T)o); - } + void System.Collections.IList.Insert(int index, object? value) + { + if (value is null && default(T) is not null) throw new ArgumentNullException(nameof(value)); + if (value is not T) throw new ArgumentException("Wrong type", nameof(value)); - void System.Collections.IList.Remove(Object o) - { - Remove((T)o); - } + Insert(index, (T)value); + } - void System.Collections.IList.RemoveAt(int index) - { - RemoveAt(index); - } + void System.Collections.IList.Remove(object? value) + { + if (value is null && default(T) is not null) return; + if (value is not T) return; - #endregion + Remove((T)value); } + + void System.Collections.IList.RemoveAt(int index) + { + RemoveAt(index); + } + + #endregion } diff --git a/C5/Arrays/CircularQueue.cs b/C5/Arrays/CircularQueue.cs index 415dfebd..1a463ecb 100644 --- a/C5/Arrays/CircularQueue.cs +++ b/C5/Arrays/CircularQueue.cs @@ -3,295 +3,308 @@ using System; using SCG = System.Collections.Generic; -namespace C5 + +namespace C5; + +/// +/// +/// +/// +public class CircularQueue : SequencedBase, IQueue, IStack { + #region Fields + /* + Invariant: the items in the queue ar the elements from front upwards, + possibly wrapping around at the end of array, to back. + + if front<=back then size = back - front + 1; + else size = array.Length + back - front + 1; + + */ + private int front, back; + /// - /// + /// The internal container array is doubled when necessary, but never shrinked. /// - /// - public class CircularQueue : SequencedBase, IQueue, IStack - { - #region Fields - /* - Invariant: the itemes in the queue ar the elements from front upwards, - possibly wrapping around at the end of array, to back. + private T[] array; + private bool forwards = true; + private bool original = true; + #endregion - if front<=back then size = back - front + 1; - else size = array.Length + back - front + 1; + #region Events - */ - private int front, back; + /// + /// + /// + /// + public override EventType ListenableEvents => EventType.Basic; - /// - /// The internal container array is doubled when necessary, but never shrinked. - /// - private T[] array; - private bool forwards = true; - private bool original = true; - #endregion + #endregion - #region Events + #region Util + private void Expand() + { + int newlength = 2 * array.Length; + T[] newarray = new T[newlength]; - /// - /// - /// - /// - public override EventType ListenableEvents => EventType.Basic; + if (front <= back) + { + Array.Copy(array, front, newarray, 0, size); + } + else + { + int half = array.Length - front; + Array.Copy(array, front, newarray, 0, half); + Array.Copy(array, 0, newarray, half, size - half); + } - #endregion + front = 0; + back = size; + array = newarray; + } - #region Util - private void Expand() - { - int newlength = 2 * array.Length; - T[] newarray = new T[newlength]; + #endregion - if (front <= back) - { - Array.Copy(array, front, newarray, 0, size); - } - else - { - int half = array.Length - front; - Array.Copy(array, front, newarray, 0, half); - Array.Copy(array, 0, newarray, half, size - half); - } + #region Constructors - front = 0; - back = size; - array = newarray; + /// + /// + /// + public CircularQueue() : this(8) { } + + /// + /// + /// + /// + public CircularQueue(int capacity) + : base(EqualityComparer.Default) + { + int newlength = 8; + while (newlength < capacity) + { + newlength *= 2; } - #endregion + array = new T[newlength]; + } - #region Constructors + #endregion - /// - /// - /// - public CircularQueue() : this(8) { } + #region IQueue Members + /// + /// + /// + /// + public virtual bool AllowsDuplicates => true; - /// - /// - /// - /// - public CircularQueue(int capacity) - : base(EqualityComparer.Default) + /// + /// Get the i'th item in the queue. The front of the queue is at index 0. + /// + /// + /// + public virtual T this[int i] + { + get { - int newlength = 8; - while (newlength < capacity) + if (i < 0 || i >= size) { - newlength *= 2; + throw new IndexOutOfRangeException(); } - array = new T[newlength]; + i += front; + //Bug fix by Steve Wallace 2006/02/10 + return array[i >= array.Length ? i - array.Length : i]; } + } - #endregion - - #region IQueue Members - /// - /// - /// - /// - public virtual bool AllowsDuplicates => true; - - /// - /// Get the i'th item in the queue. The front of the queue is at index 0. - /// - /// - /// - public virtual T this[int i] - { - get - { - if (i < 0 || i >= size) - { - throw new IndexOutOfRangeException(); - } - i += front; - //Bug fix by Steve Wallace 2006/02/10 - return array[i >= array.Length ? i - array.Length : i]; - } + /// + /// + /// + /// + public virtual void Enqueue(T item) + { + if (!original) + { + throw new ReadOnlyCollectionException(); } - - /// - /// - /// - /// - public virtual void Enqueue(T item) + stamp++; + if (size == array.Length - 1) { - if (!original) - { - throw new ReadOnlyCollectionException(); - } + Expand(); + } - stamp++; - if (size == array.Length - 1) - { - Expand(); - } + size++; + int oldback = back++; + if (back == array.Length) + { + back = 0; + } - size++; - int oldback = back++; - if (back == array.Length) - { - back = 0; - } + array[oldback] = item; + if (ActiveEvents != 0) + { + RaiseForAdd(item); + } + } - array[oldback] = item; - if (ActiveEvents != 0) - { - RaiseForAdd(item); - } + /// + /// + /// + /// + public virtual T Dequeue() + { + if (!original) + { + throw new ReadOnlyCollectionException("Object is a non-updatable clone"); } - /// - /// - /// - /// - public virtual T Dequeue() + stamp++; + if (size == 0) { - if (!original) - { - throw new ReadOnlyCollectionException("Object is a non-updatable clone"); - } + throw new NoSuchItemException(); + } - stamp++; - if (size == 0) - { - throw new NoSuchItemException(); - } + size--; + int oldfront = front++; + if (front == array.Length) + { + front = 0; + } - size--; - int oldfront = front++; - if (front == array.Length) - { - front = 0; - } + T retval = array[oldfront]; + // array[oldfront] = default; + // We can't use default as it would be null -> we just store garbage + if (ActiveEvents != 0) + { + RaiseForRemove(retval); + } - T retval = array[oldfront]; - // array[oldfront] = default; - // We can't use default as it would be null -> we just store garbage - if (ActiveEvents != 0) - { - RaiseForRemove(retval); - } + return retval; + } - return retval; + /// + /// + /// + /// + public void Push(T item) //== Enqueue + { + if (!original) + { + throw new ReadOnlyCollectionException(); } - /// - /// - /// - /// - public void Push(T item) //== Enqueue + stamp++; + if (size == array.Length - 1) { - if (!original) - { - throw new ReadOnlyCollectionException(); - } - - stamp++; - if (size == array.Length - 1) - { - Expand(); - } - - size++; - int oldback = back++; - if (back == array.Length) - { - back = 0; - } + Expand(); + } - array[oldback] = item; - if (ActiveEvents != 0) - { - RaiseForAdd(item); - } + size++; + int oldback = back++; + if (back == array.Length) + { + back = 0; } - /// - /// - /// - /// - public T Pop() + array[oldback] = item; + if (ActiveEvents != 0) { - if (!original) - { - throw new ReadOnlyCollectionException("Object is a non-updatable clone"); - } + RaiseForAdd(item); + } + } - stamp++; - if (size == 0) - { - throw new NoSuchItemException(); - } + /// + /// + /// + /// + public T Pop() + { + if (!original) + { + throw new ReadOnlyCollectionException("Object is a non-updatable clone"); + } - size--; - back--; - if (back == -1) - { - back = array.Length - 1; - } + stamp++; + if (size == 0) + { + throw new NoSuchItemException(); + } - T retval = array[back]; - //array[back] = default; - //We can't use default -> just store garbage - if (ActiveEvents != 0) - { - RaiseForRemove(retval); - } + size--; + back--; + if (back == -1) + { + back = array.Length - 1; + } - return retval; + T retval = array[back]; + //array[back] = default; + //We can't use default -> just store garbage + if (ActiveEvents != 0) + { + RaiseForRemove(retval); } - #endregion - #region ICollectionValue Members + return retval; + } + #endregion - //TODO: implement these with Array.Copy instead of relying on XxxBase: - /* - public void CopyTo(T[] a, int i) - { - } + #region ICollectionValue Members - public T[] ToArray() - { - }*/ + //TODO: implement these with Array.Copy instead of relying on XxxBase: + /* + public void CopyTo(T[] a, int i) + { + } - /// - /// - /// - /// - public override T Choose() + public T[] ToArray() { - if (size == 0) - { - throw new NoSuchItemException(); - } + }*/ - return array[front]; + /// + /// + /// + /// + public override T Choose() + { + if (size == 0) + { + throw new NoSuchItemException(); } - #endregion + return array[front]; + } + + #endregion - #region IEnumerable Members + #region IEnumerable Members - /// - /// - /// - /// - public override SCG.IEnumerator GetEnumerator() + /// + /// + /// + /// + public override SCG.IEnumerator GetEnumerator() + { + int stamp = this.stamp; + if (forwards) { - int stamp = this.stamp; - if (forwards) + int position = front; + int end = front <= back ? back : array.Length; + while (position < end) { - int position = front; - int end = front <= back ? back : array.Length; - while (position < end) + if (stamp != this.stamp) + { + throw new CollectionModifiedException(); + } + + yield return array[position++]; + } + if (front > back) + { + position = 0; + while (position < back) { if (stamp != this.stamp) { @@ -300,25 +313,25 @@ public override SCG.IEnumerator GetEnumerator() yield return array[position++]; } - if (front > back) + } + } + else + { + int position = back - 1; + int end = front <= back ? front : 0; + while (position >= end) + { + if (stamp != this.stamp) { - position = 0; - while (position < back) - { - if (stamp != this.stamp) - { - throw new CollectionModifiedException(); - } - - yield return array[position++]; - } + throw new CollectionModifiedException(); } + + yield return array[position--]; } - else + if (front > back) { - int position = back - 1; - int end = front <= back ? front : 0; - while (position >= end) + position = array.Length - 1; + while (position >= front) { if (stamp != this.stamp) { @@ -327,67 +340,54 @@ public override SCG.IEnumerator GetEnumerator() yield return array[position--]; } - if (front > back) - { - position = array.Length - 1; - while (position >= front) - { - if (stamp != this.stamp) - { - throw new CollectionModifiedException(); - } - - yield return array[position--]; - } - } } } + } - #endregion + #endregion - #region IDirectedCollectionValue Members + #region IDirectedCollectionValue Members - /// - /// - /// - /// - public override IDirectedCollectionValue Backwards() - { - CircularQueue retval = (CircularQueue)MemberwiseClone(); - retval.original = false; - retval.forwards = !forwards; - return retval; - } + /// + /// + /// + /// + public override IDirectedCollectionValue Backwards() + { + CircularQueue retval = (CircularQueue)MemberwiseClone(); + retval.original = false; + retval.forwards = !forwards; + return retval; + } - #endregion + #endregion - #region IDirectedEnumerable Members + #region IDirectedEnumerable Members - /// - /// - /// - /// - IDirectedEnumerable IDirectedEnumerable.Backwards() - { - return Backwards(); - } + /// + /// + /// + /// + IDirectedEnumerable IDirectedEnumerable.Backwards() + { + return Backwards(); + } - #endregion + #endregion - /// - /// - /// - /// - public virtual bool Check() + /// + /// + /// + /// + public virtual bool Check() + { + if (front < 0 || front >= array.Length || back < 0 || back >= array.Length || + (front <= back && size != back - front) || (front > back && size != array.Length + back - front)) { - if (front < 0 || front >= array.Length || back < 0 || back >= array.Length || - (front <= back && size != back - front) || (front > back && size != array.Length + back - front)) - { - Logger.Log(string.Format("Bad combination of (front,back,size,array.Length): ({0},{1},{2},{3})", - front, back, size, array.Length)); - return false; - } - return true; + Logger.Log(string.Format("Bad combination of (front,back,size,array.Length): ({0},{1},{2},{3})", + front, back, size, array.Length)); + return false; } + return true; } } \ No newline at end of file diff --git a/C5/Arrays/HashedArrayList.cs b/C5/Arrays/HashedArrayList.cs index 13fe0ea9..2fed561d 100644 --- a/C5/Arrays/HashedArrayList.cs +++ b/C5/Arrays/HashedArrayList.cs @@ -4,1873 +4,1836 @@ using System; using SCG = System.Collections.Generic; -namespace C5 + +namespace C5; + +/// +/// A list collection based on a plain dynamic array data structure. +/// Expansion of the internal array is performed by doubling on demand. +/// The internal array is only shrinked by the Clear method. +/// +/// When the FIFO property is set to false this class works fine as a stack of T. +/// When the FIFO property is set to true the class will function as a (FIFO) queue +/// but very inefficiently, use a LinkedList () instead. +/// +/// +/// Create an array list with external item equalityComparer and prescribed initial capacity. +/// +/// The prescribed capacity +/// The external item equalitySCG.Comparer +public class HashedArrayList(int capacity, SCG.IEqualityComparer itemequalityComparer) : ArrayBase(capacity, itemequalityComparer), IList, SCG.IList { + #region Fields + + /// + /// Has this list or view not been invalidated by some operation (by someone calling Dispose()) + /// + private bool isValid = true; + + //TODO: wonder if we should save some memory on none-view situations by + // putting these three fields into a single ref field? + /// + /// The underlying list if we are a view, null else. + /// + private HashedArrayList? underlying; + private WeakViewList>? views; + private WeakViewList>.Node? myWeakReference; + + /// + /// The size of the underlying list. + /// + private int UnderlyingSize => (underlying ?? this).size; + + /// + /// The underlying field of the FIFO property + /// + private bool fIFO = false; + private readonly HashSet> itemIndex = new(new KeyValuePairEqualityComparer(itemequalityComparer)); + #endregion + #region Events + /// - /// A list collection based on a plain dynamic array data structure. - /// Expansion of the internal array is performed by doubling on demand. - /// The internal array is only shrinked by the Clear method. /// - /// When the FIFO property is set to false this class works fine as a stack of T. - /// When the FIFO property is set to true the class will function as a (FIFO) queue - /// but very inefficiently, use a LinkedList () instead. /// - public class HashedArrayList : ArrayBase, IList, SCG.IList - { - #region Fields + /// + public override EventType ListenableEvents => underlying == null ? EventType.All : EventType.None; + /* /// - /// Has this list or view not been invalidated by some operation (by someone calling Dispose()) + /// /// - private bool isValid = true; + /// + public override event CollectionChangedHandler CollectionChanged + { + add + { + if (underlying == null) + base.CollectionChanged += value; + else + throw new UnlistenableEventException("Can't listen to a view"); + } + remove + { + if (underlying == null) + base.CollectionChanged -= value; + else + throw new UnlistenableEventException("Can't listen to a view"); + } + } - //TODO: wonder if we should save some memory on none-view situations by - // putting these three fields into a single ref field? /// - /// The underlying list if we are a view, null else. + /// /// - private HashedArrayList? underlying; - private WeakViewList>? views; - private WeakViewList>.Node? myWeakReference; + /// + public override event CollectionClearedHandler CollectionCleared + { + add + { + if (underlying == null) + base.CollectionCleared += value; + else + throw new UnlistenableEventException("Can't listen to a view"); + } + remove + { + if (underlying == null) + base.CollectionCleared -= value; + else + throw new UnlistenableEventException("Can't listen to a view"); + } + } /// - /// The size of the underlying list. + /// /// - private int UnderlyingSize => (underlying ?? this).size; + /// + public override event ItemsAddedHandler ItemsAdded + { + add + { + if (underlying == null) + base.ItemsAdded += value; + else + throw new UnlistenableEventException("Can't listen to a view"); + } + remove + { + if (underlying == null) + base.ItemsAdded -= value; + else + throw new UnlistenableEventException("Can't listen to a view"); + } + } /// - /// The underlying field of the FIFO property + /// /// - private bool fIFO = false; - private readonly HashSet> itemIndex; - #endregion - #region Events + /// + public override event ItemInsertedHandler ItemInserted + { + add + { + if (underlying == null) + base.ItemInserted += value; + else + throw new UnlistenableEventException("Can't listen to a view"); + } + remove + { + if (underlying == null) + base.ItemInserted -= value; + else + throw new UnlistenableEventException("Can't listen to a view"); + } + } /// /// /// /// - public override EventType ListenableEvents => underlying == null ? EventType.All : EventType.None; - - /* - /// - /// - /// - /// - public override event CollectionChangedHandler CollectionChanged - { - add - { - if (underlying == null) - base.CollectionChanged += value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - remove - { - if (underlying == null) - base.CollectionChanged -= value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - } - - /// - /// - /// - /// - public override event CollectionClearedHandler CollectionCleared - { - add - { - if (underlying == null) - base.CollectionCleared += value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - remove - { - if (underlying == null) - base.CollectionCleared -= value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - } - - /// - /// - /// - /// - public override event ItemsAddedHandler ItemsAdded - { - add - { - if (underlying == null) - base.ItemsAdded += value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - remove - { - if (underlying == null) - base.ItemsAdded -= value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - } - - /// - /// - /// - /// - public override event ItemInsertedHandler ItemInserted - { - add - { - if (underlying == null) - base.ItemInserted += value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - remove - { - if (underlying == null) - base.ItemInserted -= value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - } - - /// - /// - /// - /// - public override event ItemsRemovedHandler ItemsRemoved - { - add - { - if (underlying == null) - base.ItemsRemoved += value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - remove - { - if (underlying == null) - base.ItemsRemoved -= value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - } + public override event ItemsRemovedHandler ItemsRemoved + { + add + { + if (underlying == null) + base.ItemsRemoved += value; + else + throw new UnlistenableEventException("Can't listen to a view"); + } + remove + { + if (underlying == null) + base.ItemsRemoved -= value; + else + throw new UnlistenableEventException("Can't listen to a view"); + } + } - /// - /// - /// - /// - public override event ItemRemovedAtHandler ItemRemovedAt - { - add - { - if (underlying == null) - base.ItemRemovedAt += value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - remove - { - if (underlying == null) - base.ItemRemovedAt -= value; - else - throw new UnlistenableEventException("Can't listen to a view"); - } - } + /// + /// + /// + /// + public override event ItemRemovedAtHandler ItemRemovedAt + { + add + { + if (underlying == null) + base.ItemRemovedAt += value; + else + throw new UnlistenableEventException("Can't listen to a view"); + } + remove + { + if (underlying == null) + base.ItemRemovedAt -= value; + else + throw new UnlistenableEventException("Can't listen to a view"); + } + } - */ + */ - #endregion - #region Util + #endregion + #region Util - private bool Equals(T i1, T i2) { return itemequalityComparer.Equals(i1, i2); } + private bool Equals(T i1, T i2) { return itemEqualityComparer.Equals(i1, i2); } - /// - /// Increment or decrement the private size fields - /// - /// Increment (with sign) - private void AddToSize(int delta) + /// + /// Increment or decrement the private size fields + /// + /// Increment (with sign) + private void AddToSize(int delta) + { + size += delta; + if (underlying != null) { - size += delta; - if (underlying != null) - { - underlying.size += delta; - } + underlying.size += delta; } + } - #region Array handling - /// - /// Double the size of the internal array. - /// - protected override void Expand() - { Expand(2 * array.Length, UnderlyingSize); } + #region Array handling + /// + /// Double the size of the internal array. + /// + protected override void Expand() + { Expand(2 * array.Length, UnderlyingSize); } - /// - /// Expand the internal array, resetting the index of the first unused element. - /// - /// The new capacity (will be rounded upwards to a power of 2). - /// The new count of - protected override void Expand(int newcapacity, int newsize) + /// + /// Expand the internal array, resetting the index of the first unused element. + /// + /// The new capacity (will be rounded upwards to a power of 2). + /// The new count of + protected override void Expand(int newcapacity, int newsize) + { + if (underlying != null) { - if (underlying != null) - { - underlying.Expand(newcapacity, newsize); - } - else + underlying.Expand(newcapacity, newsize); + } + else + { + base.Expand(newcapacity, newsize); + if (views != null) { - base.Expand(newcapacity, newsize); - if (views != null) + foreach (HashedArrayList v in views) { - foreach (HashedArrayList v in views) - { - v.array = array; - } + v.array = array; } } } + } - #endregion + #endregion - #region Checks - /// - /// Check if it is valid to perform updates and increment stamp if so. - /// - /// If check fails by this list being a disposed view. - /// If check fails by this being a read only list. - protected override void UpdateCheck() + #region Checks + /// + /// Check if it is valid to perform updates and increment stamp if so. + /// + /// If check fails by this list being a disposed view. + /// If check fails by this being a read only list. + protected override void UpdateCheck() + { + ValidityCheck(); + base.UpdateCheck(); + if (underlying != null) { - ValidityCheck(); - base.UpdateCheck(); - if (underlying != null) - { - underlying.stamp++; - } + underlying.stamp++; } + } - /// - /// Check if we are a view that the underlying list has only been updated through us. - /// This method should be called from enumerators etc to guard against - /// modification of the base collection. - /// - /// if check fails. - private void ValidityCheck() + /// + /// Check if we are a view that the underlying list has only been updated through us. + /// This method should be called from enumerators etc to guard against + /// modification of the base collection. + /// + /// if check fails. + private void ValidityCheck() + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException(); - } + throw new ViewDisposedException(); } + } - /// - /// Check that the list has not been updated since a particular time. - /// To be used by enumerators and range - /// - /// If check fails by this list being a disposed view. - /// If the list *has* been updated since that time.. - /// The stamp indicating the time. - protected override void ModifyCheck(int stamp) + /// + /// Check that the list has not been updated since a particular time. + /// To be used by enumerators and range + /// + /// If check fails by this list being a disposed view. + /// If the list *has* been updated since that time.. + /// The stamp indicating the time. + protected override void ModifyCheck(int stamp) + { + ValidityCheck(); + if (this.stamp != stamp) { - ValidityCheck(); - if (this.stamp != stamp) - { - throw new CollectionModifiedException(); - } + throw new CollectionModifiedException(); } + } - #endregion + #endregion - #region Searching + #region Searching - /// - /// Internal version of IndexOf without modification checks. - /// - /// Item to look for - /// The index of first occurrence - private int IndexOfInner(T item) + /// + /// Internal version of IndexOf without modification checks. + /// + /// Item to look for + /// The index of first occurrence + private int IndexOfInner(T item) + { + System.Collections.Generic.KeyValuePair p = new(item, default); + if (itemIndex.Find(ref p) && p.Value >= offsetField && p.Value < offsetField + size) { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(item, default); - if (itemIndex.Find(ref p) && p.Value >= offsetField && p.Value < offsetField + size) - { - return p.Value - offsetField; - } - - return ~size; + return p.Value - offsetField; } - /// - /// Internal version of LastIndexOf without modification checks. - /// - /// Item to look for - /// The index of last occurrence - private int LastIndexOfInner(T item) + return ~size; + } + + /// + /// Internal version of LastIndexOf without modification checks. + /// + /// Item to look for + /// The index of last occurrence + private int LastIndexOfInner(T item) + { + return IndexOfInner(item); + } + #endregion + + #region Inserting + + /// + /// Internal version of Insert with no modification checks. + /// + /// if item already in list. + /// Index to insert at + /// Item to insert + protected override void InsertProtected(int i, T item) + { + System.Collections.Generic.KeyValuePair p = new(item, offsetField + i); + if (itemIndex.FindOrAdd(ref p)) { - return IndexOfInner(item); + throw new DuplicateNotAllowedException("Item already in indexed list: " + item); } - #endregion - #region Inserting + InsertBase(i, item); + ReIndex(i + offsetField + 1); + } - /// - /// Internal version of Insert with no modification checks. - /// - /// if item already in list. - /// Index to insert at - /// Item to insert - protected override void InsertProtected(int i, T item) + private void InsertBase(int i, T item) + { + if (UnderlyingSize == array.Length) { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(item, offsetField + i); - if (itemIndex.FindOrAdd(ref p)) - { - throw new DuplicateNotAllowedException("Item already in indexed list: " + item); - } - - InsertBase(i, item); - ReIndex(i + offsetField + 1); + Expand(); } - private void InsertBase(int i, T item) + i += offsetField; + if (i < UnderlyingSize) { - if (UnderlyingSize == array.Length) - { - Expand(); - } - - i += offsetField; - if (i < UnderlyingSize) - { - Array.Copy(array, i, array, i + 1, UnderlyingSize - i); - } - - array[i] = item; - AddToSize(1); - FixViewsAfterInsert(1, i); + Array.Copy(array, i, array, i + 1, UnderlyingSize - i); } - #endregion - #region Removing + array[i] = item; + AddToSize(1); + FixViewsAfterInsert(1, i); + } + #endregion - /// - /// Internal version of RemoveAt with no modification checks. - /// - /// Index to remove at - /// The removed item - private T RemoveAtInternal(int i) - { - i += offsetField; - FixViewsBeforeSingleRemove(i); - T retval = array[i]; - AddToSize(-1); - if (UnderlyingSize > i) - { - Array.Copy(array, i + 1, array, i, UnderlyingSize - i); - } + #region Removing - array[UnderlyingSize] = default; - itemIndex.Remove(new System.Collections.Generic.KeyValuePair(retval, default)); - ReIndex(i); - return retval; + /// + /// Internal version of RemoveAt with no modification checks. + /// + /// Index to remove at + /// The removed item + private T RemoveAtInternal(int i) + { + i += offsetField; + FixViewsBeforeSingleRemove(i); + T retval = array[i]; + AddToSize(-1); + if (UnderlyingSize > i) + { + Array.Copy(array, i + 1, array, i, UnderlyingSize - i); } - #endregion - #region Indexing + array[UnderlyingSize] = default; + itemIndex.Remove(new System.Collections.Generic.KeyValuePair(retval, default)); + ReIndex(i); + return retval; + } + #endregion + + #region Indexing - private void ReIndex(int start) { ReIndex(start, UnderlyingSize); } + private void ReIndex(int start) { ReIndex(start, UnderlyingSize); } - private void ReIndex(int start, int end) + private void ReIndex(int start, int end) + { + for (int j = start; j < end; j++) { - for (int j = start; j < end; j++) - { - itemIndex.UpdateOrAdd(new System.Collections.Generic.KeyValuePair(array[j], j)); - } + itemIndex.UpdateOrAdd(new System.Collections.Generic.KeyValuePair(array[j], j)); } - #endregion + } + #endregion - #region fixView utilities + #region fixView utilities - /// - /// - /// - /// The actual number of inserted nodes - /// - private void FixViewsAfterInsert(int added, int realInsertionIndex) + /// + /// + /// + /// The actual number of inserted nodes + /// + private void FixViewsAfterInsert(int added, int realInsertionIndex) + { + if (views != null) { - if (views != null) + foreach (HashedArrayList view in views) { - foreach (HashedArrayList view in views) + if (view != this) { - if (view != this) + if (view.offsetField < realInsertionIndex && view.offsetField + view.size > realInsertionIndex) { - if (view.offsetField < realInsertionIndex && view.offsetField + view.size > realInsertionIndex) - { - view.size += added; - } + view.size += added; + } - if (view.offsetField > realInsertionIndex || (view.offsetField == realInsertionIndex && view.size > 0)) - { - view.offsetField += added; - } + if (view.offsetField > realInsertionIndex || (view.offsetField == realInsertionIndex && view.size > 0)) + { + view.offsetField += added; } } } } + } - private void FixViewsBeforeSingleRemove(int realRemovalIndex) + private void FixViewsBeforeSingleRemove(int realRemovalIndex) + { + if (views != null) { - if (views != null) + foreach (HashedArrayList view in views) { - foreach (HashedArrayList view in views) + if (view != this) { - if (view != this) + if (view.offsetField <= realRemovalIndex && view.offsetField + view.size > realRemovalIndex) { - if (view.offsetField <= realRemovalIndex && view.offsetField + view.size > realRemovalIndex) - { - view.size--; - } + view.size--; + } - if (view.offsetField > realRemovalIndex) - { - view.offsetField--; - } + if (view.offsetField > realRemovalIndex) + { + view.offsetField--; } } } } + } - /// - /// Fix offsets and sizes of other views before removing an interval from this - /// - /// the start of the interval relative to the array/underlying - /// - private void FixViewsBeforeRemove(int start, int count) + /// + /// Fix offsets and sizes of other views before removing an interval from this + /// + /// the start of the interval relative to the array/underlying + /// + private void FixViewsBeforeRemove(int start, int count) + { + int clearend = start + count - 1; + if (views != null) { - int clearend = start + count - 1; - if (views != null) + foreach (HashedArrayList view in views) { - foreach (HashedArrayList view in views) + if (view == this) { - if (view == this) - { - continue; - } + continue; + } - int viewoffset = view.offsetField, viewend = viewoffset + view.size - 1; - if (start < viewoffset) + int viewoffset = view.offsetField, viewend = viewoffset + view.size - 1; + if (start < viewoffset) + { + if (clearend < viewoffset) { - if (clearend < viewoffset) - { - view.offsetField = viewoffset - count; - } - else - { - view.offsetField = start; - view.size = clearend < viewend ? viewend - clearend : 0; - } + view.offsetField = viewoffset - count; } - else if (start <= viewend) + else { - view.size = clearend <= viewend ? view.size - count : start - viewoffset; + view.offsetField = start; + view.size = clearend < viewend ? viewend - clearend : 0; } } + else if (start <= viewend) + { + view.size = clearend <= viewend ? view.size - count : start - viewoffset; + } } } + } - /// - /// - /// - /// - /// - /// The position of View(otherOffset, otherSize) wrt. this view - private MutualViewPosition ViewPosition(int otherOffset, int otherSize) + /// + /// + /// + /// + /// + /// The position of View(otherOffset, otherSize) wrt. this view + private MutualViewPosition ViewPosition(int otherOffset, int otherSize) + { + int end = offsetField + size, otherEnd = otherOffset + otherSize; + if (otherOffset >= end || otherEnd <= offsetField) { - int end = offsetField + size, otherEnd = otherOffset + otherSize; - if (otherOffset >= end || otherEnd <= offsetField) - { - return MutualViewPosition.NonOverlapping; - } - - if (size == 0 || (otherOffset <= offsetField && end <= otherEnd)) - { - return MutualViewPosition.Contains; - } + return MutualViewPosition.NonOverlapping; + } - if (otherSize == 0 || (offsetField <= otherOffset && otherEnd <= end)) - { - return MutualViewPosition.ContainedIn; - } + if (size == 0 || (otherOffset <= offsetField && end <= otherEnd)) + { + return MutualViewPosition.Contains; + } - return MutualViewPosition.Overlapping; + if (otherSize == 0 || (offsetField <= otherOffset && otherEnd <= end)) + { + return MutualViewPosition.ContainedIn; } - //TODO: make version that fits the new, more forgiving rules for disposing - private void DisposeOverlappingViews(bool reverse) + return MutualViewPosition.Overlapping; + } + + //TODO: make version that fits the new, more forgiving rules for disposing + private void DisposeOverlappingViews(bool reverse) + { + if (views != null) { - if (views != null) + foreach (HashedArrayList view in views) { - foreach (HashedArrayList view in views) + if (view != this) { - if (view != this) + switch (ViewPosition(view.offsetField, view.size)) { - switch (ViewPosition(view.offsetField, view.size)) - { - case MutualViewPosition.ContainedIn: - if (reverse) - { - view.offsetField = 2 * offsetField + size - view.size - view.offsetField; - } - else - { - view.Dispose(); - } - - break; - case MutualViewPosition.Overlapping: + case MutualViewPosition.ContainedIn: + if (reverse) + { + view.offsetField = 2 * offsetField + size - view.size - view.offsetField; + } + else + { view.Dispose(); - break; - case MutualViewPosition.Contains: - case MutualViewPosition.NonOverlapping: - break; - } + } + + break; + case MutualViewPosition.Overlapping: + view.Dispose(); + break; + case MutualViewPosition.Contains: + case MutualViewPosition.NonOverlapping: + break; } } } } - #endregion + } + #endregion - #endregion + #endregion - #region Position, PositionComparer and ViewHandler nested types - private class PositionComparer : SCG.IComparer + #region Position, PositionComparer and ViewHandler nested types + private class PositionComparer : SCG.IComparer + { + public int Compare(Position a, Position b) { - public int Compare(Position a, Position b) - { - return a.Index.CompareTo(b.Index); - } + return a.Index.CompareTo(b.Index); } + } - /// - /// During RemoveAll, we need to cache the original endpoint indices of views (??? also for HashedArrayList?) - /// - private struct Position + /// + /// During RemoveAll, we need to cache the original endpoint indices of views (??? also for HashedArrayList?) + /// + private readonly struct Position + { + public HashedArrayList? View { get; } + + public int Index { get; } + + public Position(HashedArrayList view, bool left) { - public HashedArrayList? View { get; } + View = view; + Index = left ? view.offsetField : view.offsetField + view.size - 1; + } - public int Index { get; } + public Position(int index) + { + Index = index; + View = null; + } + } - public Position(HashedArrayList view, bool left) + /// + /// Handle the update of (other) views during a multi-remove operation. + /// + private struct ViewHandler + { + private readonly HashedArrayList? leftEnds; + private readonly HashedArrayList? rightEnds; + private int leftEndIndex, rightEndIndex; + internal readonly int viewCount; + internal ViewHandler(HashedArrayList list) + { + leftEndIndex = rightEndIndex = viewCount = 0; + leftEnds = rightEnds = null; + if (list.views != null) { - View = view; - Index = left ? view.offsetField : view.offsetField + view.size - 1; + foreach (HashedArrayList v in list.views) + { + if (v != list) + { + if (leftEnds == null || rightEnds == null) + { + leftEnds = []; + rightEnds = []; + } + leftEnds.Add(new Position(v, true)); + rightEnds.Add(new Position(v, false)); + } + } } - public Position(int index) + if (leftEnds == null || rightEnds == null) { - Index = index; - View = null; + return; } - } + viewCount = leftEnds.Count; + leftEnds.Sort(new PositionComparer()); + rightEnds.Sort(new PositionComparer()); + } /// - /// Handle the update of (other) views during a multi-remove operation. + /// This is to be called with realindex pointing to the first node to be removed after a (stretch of) node that was not removed /// - private struct ViewHandler + /// + /// + internal void SkipEndpoints(int removed, int realindex) { - private readonly HashedArrayList? leftEnds; - private readonly HashedArrayList? rightEnds; - private int leftEndIndex, rightEndIndex; - internal readonly int viewCount; - internal ViewHandler(HashedArrayList list) + if (viewCount > 0) { - leftEndIndex = rightEndIndex = viewCount = 0; - leftEnds = rightEnds = null; - if (list.views != null) + Position endpoint; + while (leftEndIndex < viewCount && (endpoint = leftEnds![leftEndIndex]).Index <= realindex) { - foreach (HashedArrayList v in list.views) - { - if (v != list) - { - if (leftEnds == null || rightEnds == null) - { - leftEnds = new HashedArrayList(); - rightEnds = new HashedArrayList(); - } - leftEnds.Add(new Position(v, true)); - rightEnds.Add(new Position(v, false)); - } - } + HashedArrayList view = endpoint.View!; + view.offsetField -= removed; + view.size += removed; + leftEndIndex++; } - - if (leftEnds == null || rightEnds == null) + while (rightEndIndex < viewCount && (endpoint = rightEnds![rightEndIndex]).Index < realindex) { - return; + endpoint.View!.size -= removed; + rightEndIndex++; } - - viewCount = leftEnds.Count; - leftEnds.Sort(new PositionComparer()); - rightEnds.Sort(new PositionComparer()); } - /// - /// This is to be called with realindex pointing to the first node to be removed after a (stretch of) node that was not removed - /// - /// - /// - internal void SkipEndpoints(int removed, int realindex) + } + internal void UpdateViewSizesAndCounts(int removed, int realindex) + { + if (viewCount > 0) { - if (viewCount > 0) + Position endpoint; + while (leftEndIndex < viewCount && (endpoint = leftEnds![leftEndIndex]).Index <= realindex) { - Position endpoint; - while (leftEndIndex < viewCount && (endpoint = leftEnds![leftEndIndex]).Index <= realindex) - { - HashedArrayList view = endpoint.View!; - view.offsetField -= removed; - view.size += removed; - leftEndIndex++; - } - while (rightEndIndex < viewCount && (endpoint = rightEnds![rightEndIndex]).Index < realindex) - { - endpoint.View!.size -= removed; - rightEndIndex++; - } + HashedArrayList view = endpoint.View!; + view!.offsetField = view.Offset - removed; + view.size += removed; + leftEndIndex++; } - } - internal void UpdateViewSizesAndCounts(int removed, int realindex) - { - if (viewCount > 0) + while (rightEndIndex < viewCount && (endpoint = rightEnds![rightEndIndex]).Index < realindex) { - Position endpoint; - while (leftEndIndex < viewCount && (endpoint = leftEnds![leftEndIndex]).Index <= realindex) - { - HashedArrayList view = endpoint.View!; - view!.offsetField = view.Offset - removed; - view.size += removed; - leftEndIndex++; - } - while (rightEndIndex < viewCount && (endpoint = rightEnds![rightEndIndex]).Index < realindex) - { - endpoint.View!.size -= removed; - rightEndIndex++; - } + endpoint.View!.size -= removed; + rightEndIndex++; } } } - #endregion - - #region Constructors - /// - /// Create an array list with default item equalityComparer and initial capacity 8 items. - /// - public HashedArrayList() : this(8) { } - + } + #endregion - /// - /// Create an array list with external item equalityComparer and initial capacity 8 items. - /// - /// The external item equalitySCG.Comparer - public HashedArrayList(SCG.IEqualityComparer itemequalityComparer) : this(8, itemequalityComparer) { } + #region Constructors + /// + /// Create an array list with default item equalityComparer and initial capacity 8 items. + /// + public HashedArrayList() : this(8) { } - /// - /// Create an array list with default item equalityComparer and prescribed initial capacity. - /// - /// The prescribed capacity - public HashedArrayList(int capacity) : this(capacity, EqualityComparer.Default) { } + /// + /// Create an array list with external item equalityComparer and initial capacity 8 items. + /// + /// The external item equalitySCG.Comparer + public HashedArrayList(SCG.IEqualityComparer itemequalityComparer) : this(8, itemequalityComparer) { } - /// - /// Create an array list with external item equalityComparer and prescribed initial capacity. - /// - /// The prescribed capacity - /// The external item equalitySCG.Comparer - public HashedArrayList(int capacity, SCG.IEqualityComparer itemequalityComparer) - : base(capacity, itemequalityComparer) - { - itemIndex = new HashSet>(new KeyValuePairEqualityComparer(itemequalityComparer)); - } + /// + /// Create an array list with default item equalityComparer and prescribed initial capacity. + /// + /// The prescribed capacity + public HashedArrayList(int capacity) : this(capacity, EqualityComparer.Default) { } - #endregion + #endregion - #region IList Members + #region IList Members - /// - /// - /// if this list is empty. - /// The first item in this list. - public virtual T First + /// + /// + /// if this list is empty. + /// The first item in this list. + public virtual T First + { + get { - get + ValidityCheck(); + if (size == 0) { - ValidityCheck(); - if (size == 0) - { - throw new NoSuchItemException(); - } - - return array[offsetField]; + throw new NoSuchItemException(); } + + return array[offsetField]; } + } - /// - /// - /// if this list is empty. - /// The last item in this list. - public virtual T Last + /// + /// + /// if this list is empty. + /// The last item in this list. + public virtual T Last + { + get { - get + ValidityCheck(); + if (size == 0) { - ValidityCheck(); - if (size == 0) - { - throw new NoSuchItemException(); - } - - return array[offsetField + size - 1]; + throw new NoSuchItemException(); } - } - - - /// - /// Since Add(T item) always add at the end of the list, - /// this describes if list has FIFO or LIFO semantics. - /// - /// True if the Remove() operation removes from the - /// start of the list, false if it removes from the end. The default for a new array list is false. - public virtual bool FIFO - { - get { ValidityCheck(); return fIFO; } - set { UpdateCheck(); fIFO = value; } - } - /// - /// - /// - public virtual bool IsFixedSize - { - get { ValidityCheck(); return false; } + return array[offsetField + size - 1]; } + } - /// - /// On this list, this indexer is read/write. - /// - /// if index is negative or - /// >= the size of the collection. - /// By the get operation - /// if the item already is present somewhere else in the list. - /// The index'th item of this list. - /// The index of the item to fetch or store. - public virtual T this[int index] - { - get - { - ValidityCheck(); - if (index < 0 || index >= size) - { - throw new IndexOutOfRangeException(); - } - - return array[offsetField + index]; - } - set - { - UpdateCheck(); - if (index < 0 || index >= size) - { - throw new IndexOutOfRangeException(); - } - - index += offsetField; - T item = array[index]; - - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(value, index); - if (itemequalityComparer.Equals(value, item)) - { - array[index] = value; - itemIndex.Update(p); - } - else if (!itemIndex.FindOrAdd(ref p)) - { - itemIndex.Remove(new System.Collections.Generic.KeyValuePair(item, default)); - array[index] = value; - } - else - { - throw new DuplicateNotAllowedException("Item already in indexed list"); - } (underlying ?? this).RaiseForSetThis(index, value, item); - } - } + /// + /// Since Add(T item) always add at the end of the list, + /// this describes if list has FIFO or LIFO semantics. + /// + /// True if the Remove() operation removes from the + /// start of the list, false if it removes from the end. The default for a new array list is false. + public virtual bool FIFO + { + get { ValidityCheck(); return fIFO; } + set { UpdateCheck(); fIFO = value; } + } - /// - /// - /// - /// - public virtual Speed IndexingSpeed => Speed.Constant; + /// + /// + /// + public virtual bool IsFixedSize + { + get { ValidityCheck(); return false; } + } - /// - /// Insert an item at a specific index location in this list. - /// - /// if index is negative or - /// > the size of the collection. - /// - /// If the item is already present in the list. - /// The index at which to insert. - /// The item to insert. - public virtual void Insert(int index, T item) + /// + /// On this list, this indexer is read/write. + /// + /// if index is negative or + /// >= the size of the collection. + /// By the get operation + /// if the item already is present somewhere else in the list. + /// The index'th item of this list. + /// The index of the item to fetch or store. + public virtual T this[int index] + { + get { - UpdateCheck(); - if (index < 0 || index > size) + ValidityCheck(); + if (index < 0 || index >= size) { throw new IndexOutOfRangeException(); } - InsertProtected(index, item); - (underlying ?? this).RaiseForInsert(index + offsetField, item); - } - - /// - /// Insert an item at the end of a compatible view, used as a pointer. - /// The pointer must be a view on the same list as - /// this and the endpoint of pointer must be - /// a valid insertion point of this - /// - /// If pointer - /// is not a view on or the same list as this - /// ?????? if the endpoint of - /// pointer is not inside this - /// if the list has - /// AllowsDuplicates==false and the item is - /// already in the list. - /// - /// - public void Insert(IList pointer, T item) - { - if ((pointer == null) || ((pointer.Underlying ?? pointer) != (underlying ?? this))) - { - throw new IncompatibleViewException(); - } - - Insert(pointer.Offset + pointer.Count - Offset, item); + return array[offsetField + index]; } - - /// - /// Insert into this list all items from an enumerable collection starting - /// at a particular index. - /// - /// if index is negative or - /// > the size of the collection. - /// If items - /// contains duplicates or some item already present in the list. - /// Index to start inserting at - /// Items to insert - public virtual void InsertAll(int index, SCG.IEnumerable items) + set { UpdateCheck(); - if (index < 0 || index > size) + if (index < 0 || index >= size) { throw new IndexOutOfRangeException(); } index += offsetField; - int toadd = CountItems(items); - if (toadd == 0) - { - return; - } - - if (toadd + UnderlyingSize > array.Length) - { - Expand(toadd + UnderlyingSize, UnderlyingSize); - } + T item = array[index]; - if (UnderlyingSize > index) + System.Collections.Generic.KeyValuePair p = new(value, index); + if (itemEqualityComparer.Equals(value, item)) { - Array.Copy(array, index, array, index + toadd, UnderlyingSize - index); + array[index] = value; + itemIndex.Update(p); } - - int i = index; - try + else if (!itemIndex.FindOrAdd(ref p)) { - - foreach (T item in items) - { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(item, i); - if (itemIndex.FindOrAdd(ref p)) - { - throw new DuplicateNotAllowedException("Item already in indexed list"); - } - - array[i++] = item; - } + itemIndex.Remove(new System.Collections.Generic.KeyValuePair(item, default)); + array[index] = value; } - finally + else { - int added = i - index; - if (added < toadd) - { - Array.Copy(array, index + toadd, array, i, UnderlyingSize - index); - Array.Clear(array, UnderlyingSize + added, toadd - added); - } - if (added > 0) - { - AddToSize(added); - ReIndex(i); - FixViewsAfterInsert(added, index); - (underlying ?? this).RaiseForInsertAll(index, added); - } - } + throw new DuplicateNotAllowedException("Item already in indexed list"); + } (underlying ?? this).RaiseForSetThis(index, value, item); } - private void RaiseForInsertAll(int index, int added) - { - if (ActiveEvents != 0) - { - if ((ActiveEvents & (EventType.Added | EventType.Inserted)) != 0) - { - for (int j = index; j < index + added; j++) - { - RaiseItemInserted(array[j], j); - RaiseItemsAdded(array[j], 1); - } - } + } - RaiseCollectionChanged(); - } - } + /// + /// + /// + /// + public virtual Speed IndexingSpeed => Speed.Constant; - /// - /// Insert an item at the front of this list; - /// - /// If the item is already in the list - /// The item to insert. - public virtual void InsertFirst(T item) + + /// + /// Insert an item at a specific index location in this list. + /// + /// if index is negative or + /// > the size of the collection. + /// + /// If the item is already present in the list. + /// The index at which to insert. + /// The item to insert. + public virtual void Insert(int index, T item) + { + UpdateCheck(); + if (index < 0 || index > size) { - UpdateCheck(); - InsertProtected(0, item); - (underlying ?? this).RaiseForInsert(offsetField, item); + throw new IndexOutOfRangeException(); } + InsertProtected(index, item); + (underlying ?? this).RaiseForInsert(index + offsetField, item); + } - /// - /// Insert an item at the back of this list. - /// - /// If the item is already in the list - /// The item to insert. - public virtual void InsertLast(T item) + /// + /// Insert an item at the end of a compatible view, used as a pointer. + /// The pointer must be a view on the same list as + /// this and the endpoint of pointer must be + /// a valid insertion point of this + /// + /// If pointer + /// is not a view on or the same list as this + /// ?????? if the endpoint of + /// pointer is not inside this + /// if the list has + /// AllowsDuplicates==false and the item is + /// already in the list. + /// + /// + public void Insert(IList pointer, T item) + { + if ((pointer == null) || ((pointer.Underlying ?? pointer) != (underlying ?? this))) { - UpdateCheck(); - InsertProtected(size, item); - (underlying ?? this).RaiseForInsert(size - 1 + offsetField, item); + throw new IncompatibleViewException(); } + Insert(pointer.Offset + pointer.Count - Offset, item); + } - //NOTE: if the filter throws an exception, no result will be returned. - /// - /// Create a new list consisting of the items of this list satisfying a - /// certain predicate. - /// The new list will be of type HashedArrayList - /// - /// The filter delegate defining the predicate. - /// The new list. - public virtual IList FindAll(Func filter) + /// + /// Insert into this list all items from an enumerable collection starting + /// at a particular index. + /// + /// if index is negative or + /// > the size of the collection. + /// If items + /// contains duplicates or some item already present in the list. + /// Index to start inserting at + /// Items to insert + public virtual void InsertAll(int index, SCG.IEnumerable items) + { + UpdateCheck(); + if (index < 0 || index > size) { - ValidityCheck(); - int stamp = this.stamp; - HashedArrayList res = new HashedArrayList(itemequalityComparer); - int j = 0, rescap = res.array.Length; - for (int i = 0; i < size; i++) - { - T a = array[offsetField + i]; - bool found = filter(a); - ModifyCheck(stamp); - if (found) - { - if (j == rescap) - { - res.Expand(rescap = 2 * rescap, j); - } - - res.array[j++] = a; - } - } - res.size = j; - res.ReIndex(0); - return res; + throw new IndexOutOfRangeException(); } - - /// - /// Create a new list consisting of the results of mapping all items of this - /// list. The new list will use the default item equalityComparer for the item type V. - /// The new list will be of type HashedArrayList - /// - /// If mapper - /// creates duplicates - /// The type of items of the new list - /// The delegate defining the map. - /// The new list. - public virtual IList Map(Func mapper) + index += offsetField; + int toadd = CountItems(items); + if (toadd == 0) { - ValidityCheck(); - - HashedArrayList res = new HashedArrayList(size); - - return Map(mapper, res); + return; } - /// - /// Create a new list consisting of the results of mapping all items of this - /// list. The new list will use a specified item equalityComparer for the item type. - /// The new list will be of type HashedArrayList - /// - /// If mapper - /// creates duplicates - /// The type of items of the new list - /// The delegate defining the map. - /// The item equalityComparer to use for the new list - /// The new list. - public virtual IList Map(Func mapper, SCG.IEqualityComparer itemequalityComparer) + if (toadd + UnderlyingSize > array.Length) { - ValidityCheck(); - - HashedArrayList res = new HashedArrayList(size, itemequalityComparer); + Expand(toadd + UnderlyingSize, UnderlyingSize); + } - return Map(mapper, res); + if (UnderlyingSize > index) + { + Array.Copy(array, index, array, index + toadd, UnderlyingSize - index); } - private IList Map(Func mapper, HashedArrayList res) + int i = index; + try { - int stamp = this.stamp; - if (size > 0) + + foreach (T item in items) { - for (int i = 0; i < size; i++) + System.Collections.Generic.KeyValuePair p = new(item, i); + if (itemIndex.FindOrAdd(ref p)) { - V mappeditem = mapper(array[offsetField + i]); - ModifyCheck(stamp); - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(mappeditem, i); - if (res.itemIndex.FindOrAdd(ref p)) - { - throw new ArgumentException("Mapped item already in indexed list"); - } - - res.array[i] = mappeditem; + throw new DuplicateNotAllowedException("Item already in indexed list"); } - } - res.size = size; - return res; + array[i++] = item; + } } - - /// - /// Remove one item from the list: from the front if FIFO - /// is true, else from the back. - /// - /// if this list is empty. - /// The removed item. - public virtual T Remove() + finally { - UpdateCheck(); - if (size == 0) + int added = i - index; + if (added < toadd) { - throw new NoSuchItemException("List is empty"); + Array.Copy(array, index + toadd, array, i, UnderlyingSize - index); + Array.Clear(array, UnderlyingSize + added, toadd - added); + } + if (added > 0) + { + AddToSize(added); + ReIndex(i); + FixViewsAfterInsert(added, index); + (underlying ?? this).RaiseForInsertAll(index, added); } - - T item = RemoveAtInternal(fIFO ? 0 : size - 1); - (underlying ?? this).RaiseForRemove(item); - return item; } - - /// - /// Remove one item from the front of the list. - /// - /// if this list is empty. - /// The removed item. - public virtual T RemoveFirst() + } + private void RaiseForInsertAll(int index, int added) + { + if (ActiveEvents != 0) { - UpdateCheck(); - if (size == 0) + if ((ActiveEvents & (EventType.Added | EventType.Inserted)) != 0) { - throw new NoSuchItemException("List is empty"); + for (int j = index; j < index + added; j++) + { + RaiseItemInserted(array[j], j); + RaiseItemsAdded(array[j], 1); + } } - T item = RemoveAtInternal(0); - (underlying ?? this).RaiseForRemoveAt(offsetField, item); - return item; + RaiseCollectionChanged(); } + } + /// + /// Insert an item at the front of this list; + /// + /// If the item is already in the list + /// The item to insert. + public virtual void InsertFirst(T item) + { + UpdateCheck(); + InsertProtected(0, item); + (underlying ?? this).RaiseForInsert(offsetField, item); + } - /// - /// Remove one item from the back of the list. - /// - /// if this list is empty. - /// The removed item. - public virtual T RemoveLast() - { - UpdateCheck(); - if (size == 0) - { - throw new NoSuchItemException("List is empty"); - } - T item = RemoveAtInternal(size - 1); - (underlying ?? this).RaiseForRemoveAt(size + offsetField, item); - return item; + /// + /// Insert an item at the back of this list. + /// + /// If the item is already in the list + /// The item to insert. + public virtual void InsertLast(T item) + { + UpdateCheck(); + InsertProtected(size, item); + (underlying ?? this).RaiseForInsert(size - 1 + offsetField, item); + } + + + //NOTE: if the filter throws an exception, no result will be returned. + /// + /// Create a new list consisting of the items of this list satisfying a + /// certain predicate. + /// The new list will be of type HashedArrayList + /// + /// The filter delegate defining the predicate. + /// The new list. + public virtual IList FindAll(Func filter) + { + ValidityCheck(); + int stamp = this.stamp; + HashedArrayList res = new(itemEqualityComparer); + int j = 0, rescap = res.array.Length; + for (int i = 0; i < size; i++) + { + T a = array[offsetField + i]; + bool found = filter(a); + ModifyCheck(stamp); + if (found) + { + if (j == rescap) + { + res.Expand(rescap = 2 * rescap, j); + } + + res.array[j++] = a; + } } + res.size = j; + res.ReIndex(0); + return res; + } - /// - /// Create a list view on this list. - /// - /// if the start or count is negative - /// or the range does not fit within list. - /// The index in this list of the start of the view. - /// The size of the view. - /// The new list view. - public virtual IList? View(int start, int count) - { - ValidityCheck(); - CheckRange(start, count); - views ??= new WeakViewList>(); - HashedArrayList retval = (HashedArrayList)MemberwiseClone(); + /// + /// Create a new list consisting of the results of mapping all items of this + /// list. The new list will use the default item equalityComparer for the item type V. + /// The new list will be of type HashedArrayList + /// + /// If mapper + /// creates duplicates + /// The type of items of the new list + /// The delegate defining the map. + /// The new list. + public virtual IList Map(Func mapper) + { + ValidityCheck(); + HashedArrayList res = new(size); - retval.underlying = underlying ?? (this); - retval.offsetField = start + offsetField; - retval.size = count; - retval.myWeakReference = views.Add(retval); - return retval; - } + return Map(mapper, res); + } - /// - /// Create a list view on this list containing the (first) occurrence of a particular item. - /// Returns null if the item is not in this list. - /// - /// The item to find. - /// The new list view. - public virtual IList? ViewOf(T item) + /// + /// Create a new list consisting of the results of mapping all items of this + /// list. The new list will use a specified item equalityComparer for the item type. + /// The new list will be of type HashedArrayList + /// + /// If mapper + /// creates duplicates + /// The type of items of the new list + /// The delegate defining the map. + /// The item equalityComparer to use for the new list + /// The new list. + public virtual IList Map(Func mapper, SCG.IEqualityComparer itemequalityComparer) + { + ValidityCheck(); + + HashedArrayList res = new(size, itemequalityComparer); + + return Map(mapper, res); + } + + private HashedArrayList Map(Func mapper, HashedArrayList res) + { + int stamp = this.stamp; + if (size > 0) { - int index = IndexOfInner(item); - if (index < 0) + for (int i = 0; i < size; i++) { - return null; + V mappeditem = mapper(array[offsetField + i]); + ModifyCheck(stamp); + System.Collections.Generic.KeyValuePair p = new(mappeditem, i); + if (res.itemIndex.FindOrAdd(ref p)) + { + throw new ArgumentException("Mapped item already in indexed list"); + } + + res.array[i] = mappeditem; } + } + + res.size = size; + return res; + } - return View(index, 1); + /// + /// Remove one item from the list: from the front if FIFO + /// is true, else from the back. + /// + /// if this list is empty. + /// The removed item. + public virtual T Remove() + { + UpdateCheck(); + if (size == 0) + { + throw new NoSuchItemException("List is empty"); } + T item = RemoveAtInternal(fIFO ? 0 : size - 1); + (underlying ?? this).RaiseForRemove(item); + return item; + } - /// - /// Create a list view on this list containing the last occurrence of a particular item. - /// Returns null if the item is not in this list. - /// - /// The item to find. - /// The new list view. - public virtual IList? LastViewOf(T item) + /// + /// Remove one item from the front of the list. + /// + /// if this list is empty. + /// The removed item. + public virtual T RemoveFirst() + { + UpdateCheck(); + if (size == 0) { - int index = LastIndexOfInner(item); - if (index < 0) - { - return null; - } + throw new NoSuchItemException("List is empty"); + } - return View(index, 1); + T item = RemoveAtInternal(0); + (underlying ?? this).RaiseForRemoveAt(offsetField, item); + return item; + } + + + /// + /// Remove one item from the back of the list. + /// + /// if this list is empty. + /// The removed item. + public virtual T RemoveLast() + { + UpdateCheck(); + if (size == 0) + { + throw new NoSuchItemException("List is empty"); } - /// - /// Null if this list is not a view. - /// - /// Underlying list for view. - public virtual IList? Underlying => underlying; + T item = RemoveAtInternal(size - 1); + (underlying ?? this).RaiseForRemoveAt(size + offsetField, item); + return item; + } + /// + /// Create a list view on this list. + /// + /// if the start or count is negative + /// or the range does not fit within list. + /// The index in this list of the start of the view. + /// The size of the view. + /// The new list view. + public virtual IList? View(int start, int count) + { + ValidityCheck(); + CheckRange(start, count); + views ??= new WeakViewList>(); - /// - /// - /// Offset for this list view or 0 for an underlying list. - public virtual int Offset => offsetField; + HashedArrayList retval = (HashedArrayList)MemberwiseClone(); - /// - /// - /// - /// - public virtual bool IsValid => isValid; - /// - /// Slide this list view along the underlying list. - /// - /// if this list is not a view. - /// if the operation - /// would bring either end of the view outside the underlying list. - /// The signed amount to slide: positive to slide - /// towards the end. - public virtual IList Slide(int offset) - { - if (!TrySlide(offset, size)) - { - throw new ArgumentOutOfRangeException(nameof(offset)); - } + retval.underlying = underlying ?? (this); + retval.offsetField = start + offsetField; + retval.size = count; + retval.myWeakReference = views.Add(retval); + return retval; + } - return this; + /// + /// Create a list view on this list containing the (first) occurrence of a particular item. + /// Returns null if the item is not in this list. + /// + /// The item to find. + /// The new list view. + public virtual IList? ViewOf(T item) + { + int index = IndexOfInner(item); + if (index < 0) + { + return null; } + return View(index, 1); + } - /// - /// Slide this list view along the underlying list, changing its size. - /// - /// if this list is not a view. - /// if the operation - /// would bring either end of the view outside the underlying list. - /// The signed amount to slide: positive to slide - /// towards the end. - /// The new size of the view. - public virtual IList Slide(int offset, int size) - { - if (!TrySlide(offset, size)) - { - throw new ArgumentOutOfRangeException(); - } - return this; + /// + /// Create a list view on this list containing the last occurrence of a particular item. + /// Returns null if the item is not in this list. + /// + /// The item to find. + /// The new list view. + public virtual IList? LastViewOf(T item) + { + int index = LastIndexOfInner(item); + if (index < 0) + { + return null; } - /// - /// - /// - /// if this list is not a view. - /// - /// - public virtual bool TrySlide(int offset) + return View(index, 1); + } + + /// + /// Null if this list is not a view. + /// + /// Underlying list for view. + public virtual IList? Underlying => underlying; + + + /// + /// + /// Offset for this list view or 0 for an underlying list. + public virtual int Offset => offsetField; + + /// + /// + /// + /// + public virtual bool IsValid => isValid; + + /// + /// Slide this list view along the underlying list. + /// + /// if this list is not a view. + /// if the operation + /// would bring either end of the view outside the underlying list. + /// The signed amount to slide: positive to slide + /// towards the end. + public virtual IList Slide(int offset) + { + if (!TrySlide(offset, size)) { - return TrySlide(offset, size); + throw new ArgumentOutOfRangeException(nameof(offset)); } - /// - /// - /// - /// if this list is not a view. - /// - /// - /// - public virtual bool TrySlide(int offset, int size) + return this; + } + + + /// + /// Slide this list view along the underlying list, changing its size. + /// + /// if this list is not a view. + /// if the operation + /// would bring either end of the view outside the underlying list. + /// The signed amount to slide: positive to slide + /// towards the end. + /// The new size of the view. + public virtual IList Slide(int offset, int size) + { + if (!TrySlide(offset, size)) { - UpdateCheck(); - if (underlying == null) - { - throw new NotAViewException("Not a view"); - } + throw new ArgumentOutOfRangeException(nameof(offset)); + } - int newoffset = offsetField + offset; - int newsize = size; + return this; + } - if (newoffset < 0 || newsize < 0 || newoffset + newsize > UnderlyingSize) - { - return false; - } + /// + /// + /// + /// if this list is not a view. + /// + /// + public virtual bool TrySlide(int offset) + { + return TrySlide(offset, size); + } - offsetField = newoffset; - this.size = newsize; - return true; + /// + /// + /// + /// if this list is not a view. + /// + /// + /// + public virtual bool TrySlide(int offset, int size) + { + UpdateCheck(); + if (underlying == null) + { + throw new NotAViewException("Not a view"); } - /// - /// - /// Returns null if otherView is strictly to the left of this view - /// - /// - /// If otherView does not have the same underlying list as this - /// - public virtual IList? Span(IList otherView) + int newoffset = offsetField + offset; + int newsize = size; + + if (newoffset < 0 || newsize < 0 || newoffset + newsize > UnderlyingSize) { - if ((otherView == null) || ((otherView.Underlying ?? otherView) != (underlying ?? this))) - { - throw new IncompatibleViewException(); - } + return false; + } - if (otherView.Offset + otherView.Count - Offset < 0) - { - return null; - } + offsetField = newoffset; + this.size = newsize; + return true; + } - return (underlying ?? this).View(Offset, otherView.Offset + otherView.Count - Offset); + /// + /// + /// Returns null if otherView is strictly to the left of this view + /// + /// + /// If otherView does not have the same underlying list as this + /// + public virtual IList? Span(IList otherView) + { + if ((otherView == null) || ((otherView.Underlying ?? otherView) != (underlying ?? this))) + { + throw new IncompatibleViewException(); } - /// - /// Reverse the list so the items are in the opposite sequence order. - /// - public virtual void Reverse() + if (otherView.Offset + otherView.Count - Offset < 0) { - UpdateCheck(); - if (size == 0) - { - return; - } - - for (int i = 0, length = size / 2, end = offsetField + size - 1; i < length; i++) - { - T swap = array[offsetField + i]; - - array[offsetField + i] = array[end - i]; - array[end - i] = swap; - } - ReIndex(offsetField, offsetField + size); - //TODO: be more forgiving wrt. disposing - DisposeOverlappingViews(true); - (underlying ?? this).RaiseCollectionChanged(); + return null; } - /// - /// Check if this list is sorted according to the default sorting order - /// for the item type T, as defined by the class - /// - /// if T is not comparable - /// True if the list is sorted, else false. - public bool IsSorted() { return IsSorted(SCG.Comparer.Default); } + return (underlying ?? this).View(Offset, otherView.Offset + otherView.Count - Offset); + } - /// - /// Check if this list is sorted according to a specific sorting order. - /// - /// The comparer defining the sorting order. - /// True if the list is sorted, else false. - public virtual bool IsSorted(SCG.IComparer c) + /// + /// Reverse the list so the items are in the opposite sequence order. + /// + public virtual void Reverse() + { + UpdateCheck(); + if (size == 0) { - ValidityCheck(); - for (int i = offsetField + 1, end = offsetField + size; i < end; i++) - { - if (c.Compare(array[i - 1], array[i]) > 0) - { - return false; - } - } - - return true; + return; } - /// - /// Sort the items of the list according to the default sorting order - /// for the item type T, as defined by the Comparer[T] class - /// (). - /// - /// if T is not comparable - public virtual void Sort() + for (int i = 0, length = size / 2, end = offsetField + size - 1; i < length; i++) { - Sort(SCG.Comparer.Default); + (array[end - i], array[offsetField + i]) = (array[offsetField + i], array[end - i]); } + ReIndex(offsetField, offsetField + size); + //TODO: be more forgiving wrt. disposing + DisposeOverlappingViews(true); + (underlying ?? this).RaiseCollectionChanged(); + } + /// + /// Check if this list is sorted according to the default sorting order + /// for the item type T, as defined by the class + /// + /// if T is not comparable + /// True if the list is sorted, else false. + public bool IsSorted() { return IsSorted(SCG.Comparer.Default); } - /// - /// Sort the items of the list according to a specific sorting order. - /// - /// The comparer defining the sorting order. - public virtual void Sort(SCG.IComparer comparer) + /// + /// Check if this list is sorted according to a specific sorting order. + /// + /// The comparer defining the sorting order. + /// True if the list is sorted, else false. + public virtual bool IsSorted(SCG.IComparer c) + { + ValidityCheck(); + for (int i = offsetField + 1, end = offsetField + size; i < end; i++) { - UpdateCheck(); - if (size == 0) + if (c.Compare(array[i - 1], array[i]) > 0) { - return; + return false; } + } + + return true; + } - Sorting.IntroSort(array, offsetField, size, comparer); - DisposeOverlappingViews(false); - ReIndex(offsetField, offsetField + size); - (underlying ?? this).RaiseCollectionChanged(); + /// + /// Sort the items of the list according to the default sorting order + /// for the item type T, as defined by the Comparer[T] class + /// (). + /// + /// if T is not comparable + public virtual void Sort() + { + Sort(SCG.Comparer.Default); + } + + + /// + /// Sort the items of the list according to a specific sorting order. + /// + /// The comparer defining the sorting order. + public virtual void Sort(SCG.IComparer comparer) + { + UpdateCheck(); + if (size == 0) + { + return; } + Sorting.IntroSort(array, offsetField, size, comparer); + DisposeOverlappingViews(false); + ReIndex(offsetField, offsetField + size); + (underlying ?? this).RaiseCollectionChanged(); + } - /// - /// Randomly shuffle the items of this list. - /// - public virtual void Shuffle() { Shuffle(new C5Random()); } + /// + /// Randomly shuffle the items of this list. + /// + public virtual void Shuffle() { Shuffle(new C5Random()); } - /// - /// Shuffle the items of this list according to a specific random source. - /// - /// The random source. - public virtual void Shuffle(Random rnd) + + /// + /// Shuffle the items of this list according to a specific random source. + /// + /// The random source. + public virtual void Shuffle(Random rnd) + { + UpdateCheck(); + if (size == 0) { - UpdateCheck(); - if (size == 0) - { - return; - } + return; + } - for (int i = offsetField, top = offsetField + size, end = top - 1; i < end; i++) + for (int i = offsetField, top = offsetField + size, end = top - 1; i < end; i++) + { + int j = rnd.Next(i, top); + if (j != i) { - int j = rnd.Next(i, top); - if (j != i) - { - T tmp = array[i]; - array[i] = array[j]; - array[j] = tmp; - } + (array[j], array[i]) = (array[i], array[j]); } - DisposeOverlappingViews(false); - ReIndex(offsetField, offsetField + size); - (underlying ?? this).RaiseCollectionChanged(); } - #endregion + DisposeOverlappingViews(false); + ReIndex(offsetField, offsetField + size); + (underlying ?? this).RaiseCollectionChanged(); + } + #endregion - #region IIndexed Members + #region IIndexed Members - /// - /// Search for an item in the list going forwards from the start. - /// - /// Item to search for. - /// Index of item from start. - public virtual int IndexOf(T item) { ValidityCheck(); return IndexOfInner(item); } + /// + /// Search for an item in the list going forwards from the start. + /// + /// Item to search for. + /// Index of item from start. + public virtual int IndexOf(T item) { ValidityCheck(); return IndexOfInner(item); } - /// - /// Search for an item in the list going backwards from the end. - /// - /// Item to search for. - /// Index of item from the end. - public virtual int LastIndexOf(T item) { ValidityCheck(); return LastIndexOfInner(item); } + /// + /// Search for an item in the list going backwards from the end. + /// + /// Item to search for. + /// Index of item from the end. + public virtual int LastIndexOf(T item) { ValidityCheck(); return LastIndexOfInner(item); } - /// - /// Remove the item at a specific position of the list. - /// - /// if index is negative or - /// >= the size of the collection. - /// The index of the item to remove. - /// The removed item. - public virtual T RemoveAt(int index) + /// + /// Remove the item at a specific position of the list. + /// + /// if index is negative or + /// >= the size of the collection. + /// The index of the item to remove. + /// The removed item. + public virtual T RemoveAt(int index) + { + UpdateCheck(); + if (index < 0 || index >= size) { - UpdateCheck(); - if (index < 0 || index >= size) - { - throw new IndexOutOfRangeException("Index out of range for sequenced collection"); - } - - T item = RemoveAtInternal(index); - (underlying ?? this).RaiseForRemoveAt(offsetField + index, item); - return item; + throw new IndexOutOfRangeException("Index out of range for sequenced collection"); } + T item = RemoveAtInternal(index); + (underlying ?? this).RaiseForRemoveAt(offsetField + index, item); + return item; + } - /// - /// Remove all items in an index interval. - /// - /// If start - /// and count does not describe a valid interval in the list - /// The index of the first item to remove. - /// The number of items to remove. - public virtual void RemoveInterval(int start, int count) + + /// + /// Remove all items in an index interval. + /// + /// If start + /// and count does not describe a valid interval in the list + /// The index of the first item to remove. + /// The number of items to remove. + public virtual void RemoveInterval(int start, int count) + { + UpdateCheck(); + if (count == 0) { - UpdateCheck(); - if (count == 0) - { - return; - } + return; + } - CheckRange(start, count); - start += offsetField; - FixViewsBeforeRemove(start, count); - var p = new SCG.KeyValuePair(); - for (int i = start, end = start + count; i < end; i++) - { - p = new SCG.KeyValuePair(array[i], p.Value); - itemIndex.Remove(p); - } - Array.Copy(array, start + count, array, start, UnderlyingSize - start - count); - AddToSize(-count); - Array.Clear(array, UnderlyingSize, count); - ReIndex(start); - (underlying ?? this).RaiseForRemoveInterval(start, count); + CheckRange(start, count); + start += offsetField; + FixViewsBeforeRemove(start, count); + var p = new SCG.KeyValuePair(); + for (int i = start, end = start + count; i < end; i++) + { + p = new SCG.KeyValuePair(array[i], p.Value); + itemIndex.Remove(p); } + Array.Copy(array, start + count, array, start, UnderlyingSize - start - count); + AddToSize(-count); + Array.Clear(array, UnderlyingSize, count); + ReIndex(start); + (underlying ?? this).RaiseForRemoveInterval(start, count); + } + + private void RaiseForRemoveInterval(int start, int count) + { + if (ActiveEvents != 0) + { + RaiseCollectionCleared(size == 0, count, start); + RaiseCollectionChanged(); + } + } + #endregion + + #region ICollection Members + + /// + /// The value is symbolic indicating the type of asymptotic complexity + /// in terms of the size of this collection (worst-case or amortized as + /// relevant). + /// + /// Speed.Linear + public virtual Speed ContainsSpeed => Speed.Constant; + + /// + /// + /// + /// + public override int GetUnsequencedHashCode() + { ValidityCheck(); return base.GetUnsequencedHashCode(); } + + /// + /// + /// + /// + /// + public override bool UnsequencedEquals(ICollection that) + { ValidityCheck(); return base.UnsequencedEquals(that); } + + /// + /// Check if this collection contains (an item equivalent to according to the + /// itemequalityComparer) a particular value. + /// + /// The value to check for. + /// True if the items is in this collection. + public virtual bool Contains(T item) + { ValidityCheck(); return IndexOfInner(item) >= 0; } + + + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, return in the ref argument (a + /// binary copy of) the actual value found. + /// + /// The value to look for. + /// True if the items is in this collection. + public virtual bool Find(ref T item) + { + ValidityCheck(); - private void RaiseForRemoveInterval(int start, int count) + int i; + + if ((i = IndexOfInner(item)) >= 0) { - if (ActiveEvents != 0) - { - RaiseCollectionCleared(size == 0, count, start); - RaiseCollectionChanged(); - } + item = array[offsetField + i]; + return true; } - #endregion - #region ICollection Members + return false; + } - /// - /// The value is symbolic indicating the type of asymptotic complexity - /// in terms of the size of this collection (worst-case or amortized as - /// relevant). - /// - /// Speed.Linear - public virtual Speed ContainsSpeed => Speed.Constant; - /// - /// - /// - /// - public override int GetUnsequencedHashCode() - { ValidityCheck(); return base.GetUnsequencedHashCode(); } + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// to with a binary copy of the supplied value. This will only update the first + /// mathching item. + /// + /// Value to update. + /// True if the item was found and hence updated. + public virtual bool Update(T item) + { + return Update(item, out _); + } - /// - /// - /// - /// - /// - public override bool UnsequencedEquals(ICollection that) - { ValidityCheck(); return base.UnsequencedEquals(that); } + /// + /// + /// + /// + /// + /// + public virtual bool Update(T item, out T olditem) + { + UpdateCheck(); + int i; - /// - /// Check if this collection contains (an item equivalent to according to the - /// itemequalityComparer) a particular value. - /// - /// The value to check for. - /// True if the items is in this collection. - public virtual bool Contains(T item) - { ValidityCheck(); return IndexOfInner(item) >= 0; } + if ((i = IndexOfInner(item)) >= 0) + { + olditem = array[offsetField + i]; + array[offsetField + i] = item; + itemIndex.Update(new System.Collections.Generic.KeyValuePair(item, offsetField + i)); + (underlying ?? this).RaiseForUpdate(item, olditem); + return true; + } + olditem = default; + return false; + } - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, return in the ref argument (a - /// binary copy of) the actual value found. - /// - /// The value to look for. - /// True if the items is in this collection. - public virtual bool Find(ref T item) + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, return in the ref argument (a + /// binary copy of) the actual value found. Else, add the item to the collection. + /// + /// The value to look for. + /// True if the item was found (hence not added). + public virtual bool FindOrAdd(ref T item) + { + UpdateCheck(); + if (Find(ref item)) { - ValidityCheck(); + return true; + } - int i; + Add(item); + return false; + } - if ((i = IndexOfInner(item)) >= 0) - { - item = array[offsetField + i]; - return true; - } - return false; + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// to with a binary copy of the supplied value. This will only update the first + /// matching item. + /// + /// Value to update. + /// True if the item was found and hence updated. + public virtual bool UpdateOrAdd(T item) + { + UpdateCheck(); + if (Update(item)) + { + return true; } + Add(item); + return false; + } - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// to with a binary copy of the supplied value. This will only update the first - /// mathching item. - /// - /// Value to update. - /// True if the item was found and hence updated. - public virtual bool Update(T item) + /// + /// + /// + /// + /// + /// + public virtual bool UpdateOrAdd(T item, out T olditem) + { + UpdateCheck(); + if (Update(item, out olditem)) { - return Update(item, out _); + return true; } - /// - /// - /// - /// - /// - /// - public virtual bool Update(T item, out T olditem) - { - UpdateCheck(); - int i; + Add(item); + olditem = default; + return false; + } - if ((i = IndexOfInner(item)) >= 0) - { - olditem = array[offsetField + i]; - array[offsetField + i] = item; - itemIndex.Update(new System.Collections.Generic.KeyValuePair(item, offsetField + i)); - (underlying ?? this).RaiseForUpdate(item, olditem); - return true; - } + /// + /// Remove a particular item from this list. The item will be searched + /// for from the end of the list if FIFO == false (the default), + /// else from the start. + /// + /// The value to remove. + /// True if the item was found (and removed). + public virtual bool Remove(T item) + { + UpdateCheck(); - olditem = default; - return false; - } + int i = fIFO ? IndexOfInner(item) : LastIndexOfInner(item); - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, return in the ref argument (a - /// binary copy of) the actual value found. Else, add the item to the collection. - /// - /// The value to look for. - /// True if the item was found (hence not added). - public virtual bool FindOrAdd(ref T item) + if (i < 0) { - UpdateCheck(); - if (Find(ref item)) - { - return true; - } - - Add(item); return false; } + T removeditem = RemoveAtInternal(i); + (underlying ?? this).RaiseForRemove(removeditem); + return true; + } - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// to with a binary copy of the supplied value. This will only update the first - /// matching item. - /// - /// Value to update. - /// True if the item was found and hence updated. - public virtual bool UpdateOrAdd(T item) - { - UpdateCheck(); - if (Update(item)) - { - return true; - } - Add(item); - return false; - } + /// + /// Remove the first copy of a particular item from this collection if found. + /// If an item was removed, report a binary copy of the actual item removed in + /// the argument. The item will be searched + /// for from the end of the list if FIFO == false (the default), + /// else from the start. + /// + /// The value to remove. + /// The removed value. + /// True if the item was found (and removed). + public virtual bool Remove(T item, out T removeditem) + { + UpdateCheck(); - /// - /// - /// - /// - /// - /// - public virtual bool UpdateOrAdd(T item, out T olditem) - { - UpdateCheck(); - if (Update(item, out olditem)) - { - return true; - } + int i = fIFO ? IndexOfInner(item) : LastIndexOfInner(item); - Add(item); - olditem = default; + if (i < 0) + { + removeditem = default; return false; } - /// - /// Remove a particular item from this list. The item will be searched - /// for from the end of the list if FIFO == false (the default), - /// else from the start. - /// - /// The value to remove. - /// True if the item was found (and removed). - public virtual bool Remove(T item) - { - UpdateCheck(); - - int i = fIFO ? IndexOfInner(item) : LastIndexOfInner(item); + removeditem = RemoveAtInternal(i); + (underlying ?? this).RaiseForRemove(removeditem); + return true; + } - if (i < 0) - { - return false; - } - T removeditem = RemoveAtInternal(i); - (underlying ?? this).RaiseForRemove(removeditem); - return true; + //TODO: remove from end or according to FIFO? + /// + /// Remove all items in another collection from this one, taking multiplicities into account. + /// Matching items will be removed from the front. Current implementation is not optimal. + /// + /// The items to remove. + public virtual void RemoveAll(SCG.IEnumerable items) + { + UpdateCheck(); + if (size == 0) + { + return; } - - - /// - /// Remove the first copy of a particular item from this collection if found. - /// If an item was removed, report a binary copy of the actual item removed in - /// the argument. The item will be searched - /// for from the end of the list if FIFO == false (the default), - /// else from the start. - /// - /// The value to remove. - /// The removed value. - /// True if the item was found (and removed). - public virtual bool Remove(T item, out T removeditem) + //TODO: reactivate the old code for small sizes + HashBag toremove = new(itemEqualityComparer); + toremove.AddAll(items); + if (toremove.Count == 0) { - UpdateCheck(); - - int i = fIFO ? IndexOfInner(item) : LastIndexOfInner(item); - - if (i < 0) - { - removeditem = default; - return false; - } - - removeditem = RemoveAtInternal(i); - (underlying ?? this).RaiseForRemove(removeditem); - return true; + return; } - - //TODO: remove from end or according to FIFO? - /// - /// Remove all items in another collection from this one, taking multiplicities into account. - /// Matching items will be removed from the front. Current implementation is not optimal. - /// - /// The items to remove. - public virtual void RemoveAll(SCG.IEnumerable items) + RaiseForRemoveAllHandler raiseHandler = new(underlying ?? this); + bool mustFire = raiseHandler.MustFire; + ViewHandler viewHandler = new(this); + int j = offsetField; + int removed = 0; + int i = offsetField, end = offsetField + size; + var p = new SCG.KeyValuePair(); + while (i < end) { - UpdateCheck(); - if (size == 0) - { - return; - } - //TODO: reactivate the old code for small sizes - HashBag toremove = new HashBag(itemequalityComparer); - toremove.AddAll(items); - if (toremove.Count == 0) - { - return; - } - - RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); - bool mustFire = raiseHandler.MustFire; - ViewHandler viewHandler = new ViewHandler(this); - int j = offsetField; - int removed = 0; - int i = offsetField, end = offsetField + size; - var p = new SCG.KeyValuePair(); - while (i < end) + T item; + //pass by a stretch of nodes + while (i < end && !toremove.Contains(item = array[i])) { - T item; - //pass by a stretch of nodes - while (i < end && !toremove.Contains(item = array[i])) - { - if (j < i) - { - p = new SCG.KeyValuePair(item, j); - itemIndex.Update(p); - } - //if (j(item, p.Value); - itemIndex.Remove(p); - if (mustFire) - { - raiseHandler.Remove(item); - } - - removed++; - i++; - viewHandler.UpdateViewSizesAndCounts(removed, i); + p = new SCG.KeyValuePair(item, j); + itemIndex.Update(p); } + //if (j(item, p.Value); + itemIndex.Remove(p); + if (mustFire) + { + raiseHandler.Remove(item); + } - viewHandler.UpdateViewSizesAndCounts(removed, UnderlyingSize); - Array.Copy(array, offsetField + size, array, j, UnderlyingSize - offsetField - size); - AddToSize(-removed); - Array.Clear(array, UnderlyingSize, removed); - ReIndex(j); - if (mustFire) - { - raiseHandler.Raise(); + removed++; + i++; + viewHandler.UpdateViewSizesAndCounts(removed, i); } } + if (removed == 0) + { + return; + } - /* - /// - /// - /// - /// - void RemoveAll(Func predicate) + viewHandler.UpdateViewSizesAndCounts(removed, UnderlyingSize); + Array.Copy(array, offsetField + size, array, j, UnderlyingSize - offsetField - size); + AddToSize(-removed); + Array.Clear(array, UnderlyingSize, removed); + ReIndex(j); + if (mustFire) { - updatecheck(); - if (size == 0) - return; - RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); - bool mustFire = raiseHandler.MustFire; - ViewHandler viewHandler = new ViewHandler(this); - int j = offsetField; - int removed = 0; - int i = offsetField, end = offsetField + size; - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(); - while (i < end) + raiseHandler.Raise(); + } + } + + /* + /// + /// + /// + /// + void RemoveAll(Func predicate) + { + updatecheck(); + if (size == 0) + return; + RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); + bool mustFire = raiseHandler.MustFire; + ViewHandler viewHandler = new ViewHandler(this); + int j = offsetField; + int removed = 0; + int i = offsetField, end = offsetField + size; + System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(); + while (i < end) + { + T item; + //pass by a stretch of nodes + while (i < end && !predicate(item = array[i])) { - T item; - //pass by a stretch of nodes - while (i < end && !predicate(item = array[i])) - { - updatecheck(); - if (j < i) - { - p.Key = item; - p.Value = j; - itemIndex.Update(p); - } - //if (j - /// Remove all items from this collection, resetting internal array size. - /// - public override void Clear() - { - if (underlying == null) - { - UpdateCheck(); - if (size == 0) - { - return; + p.Value = j; + itemIndex.Update(p); } - - int oldsize = size; - FixViewsBeforeRemove(0, size); - itemIndex.Clear(); - array = new T[8]; - size = 0; - (underlying ?? this).RaiseForRemoveInterval(offsetField, oldsize); + //if (j - /// Remove all items not in some other collection from this one, taking multiplicities into account. - /// Items are retained front first. - /// - /// The items to retain. - public virtual void RetainAll(SCG.IEnumerable items) + /// + /// Remove all items from this collection, resetting internal array size. + /// + public override void Clear() + { + if (underlying == null) { UpdateCheck(); if (size == 0) @@ -1878,579 +1841,627 @@ public virtual void RetainAll(SCG.IEnumerable items) return; } - HashBag toretain = new HashBag(itemequalityComparer); - toretain.AddAll(items); - if (toretain.Count == 0) + int oldsize = size; + FixViewsBeforeRemove(0, size); + itemIndex.Clear(); + array = new T[8]; + size = 0; + (underlying ?? this).RaiseForRemoveInterval(offsetField, oldsize); + } + else + { + RemoveInterval(0, size); + } + } + + /// + /// Remove all items not in some other collection from this one, taking multiplicities into account. + /// Items are retained front first. + /// + /// The items to retain. + public virtual void RetainAll(SCG.IEnumerable items) + { + UpdateCheck(); + if (size == 0) + { + return; + } + + HashBag toretain = new(itemEqualityComparer); + toretain.AddAll(items); + if (toretain.Count == 0) + { + Clear(); + return; + } + RaiseForRemoveAllHandler raiseHandler = new(underlying ?? this); + bool mustFire = raiseHandler.MustFire; + ViewHandler viewHandler = new(this); + int j = offsetField; + int removed = 0; + int i = offsetField, end = offsetField + size; + System.Collections.Generic.KeyValuePair p = new(); + while (i < end) + { + T item; + //pass by a stretch of nodes + while (i < end && toretain.Remove(item = array[i])) { - Clear(); - return; + if (j < i) + { + p = new SCG.KeyValuePair(item, j); + itemIndex.Update(p); + } + //if (j p = new SCG.KeyValuePair(); - while (i < end) + viewHandler.SkipEndpoints(removed, i); + //Remove a stretch of nodes + while (i < end && !toretain.Contains(item = array[i])) { - T item; - //pass by a stretch of nodes - while (i < end && toretain.Remove(item = array[i])) + p = new SCG.KeyValuePair(item, p.Value); + itemIndex.Remove(p); + if (mustFire) { - if (j < i) - { - p = new SCG.KeyValuePair(item, j); - itemIndex.Update(p); - } - //if (j(item, p.Value); - itemIndex.Remove(p); - if (mustFire) - { - raiseHandler.Remove(item); - } - removed++; - i++; - viewHandler.UpdateViewSizesAndCounts(removed, i); - } - } - if (removed == 0) - { - return; + removed++; + i++; + viewHandler.UpdateViewSizesAndCounts(removed, i); } - - viewHandler.UpdateViewSizesAndCounts(removed, UnderlyingSize); - Array.Copy(array, offsetField + size, array, j, UnderlyingSize - offsetField - size); - AddToSize(-removed); - Array.Clear(array, UnderlyingSize, removed); - ReIndex(j); - raiseHandler.Raise(); } - - /* - /// - /// - /// - /// - void RetainAll(Func predicate) + if (removed == 0) { - updatecheck(); - if (size == 0) - return; - RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); - bool mustFire = raiseHandler.MustFire; - ViewHandler viewHandler = new ViewHandler(this); - int j = offsetField; - int removed = 0; - int i = offsetField, end = offsetField + size; - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(); - while (i < end) + return; + } + + viewHandler.UpdateViewSizesAndCounts(removed, UnderlyingSize); + Array.Copy(array, offsetField + size, array, j, UnderlyingSize - offsetField - size); + AddToSize(-removed); + Array.Clear(array, UnderlyingSize, removed); + ReIndex(j); + raiseHandler.Raise(); + } + + /* + /// + /// + /// + /// + void RetainAll(Func predicate) + { + updatecheck(); + if (size == 0) + return; + RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); + bool mustFire = raiseHandler.MustFire; + ViewHandler viewHandler = new ViewHandler(this); + int j = offsetField; + int removed = 0; + int i = offsetField, end = offsetField + size; + System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(); + while (i < end) + { + T item; + //pass by a stretch of nodes + while (i < end && predicate(item = array[i])) { - T item; - //pass by a stretch of nodes - while (i < end && predicate(item = array[i])) - { - updatecheck(); - if (j < i) - { - p.Key = item; - p.Value = j; - itemIndex.Update(p); - } - //if (j - /// Check if this collection contains all the values in another collection, - /// taking multiplicities into account. - /// Current implementation is not optimal. - /// - /// The - /// True if all values in itemsis in this collection. - public virtual bool ContainsAll(SCG.IEnumerable items) + /// + /// Check if this collection contains all the values in another collection, + /// taking multiplicities into account. + /// Current implementation is not optimal. + /// + /// The + /// True if all values in itemsis in this collection. + public virtual bool ContainsAll(SCG.IEnumerable items) + { + ValidityCheck(); + foreach (T item in items) { - ValidityCheck(); - foreach (T item in items) + if (IndexOfInner(item) < 0) { - if (IndexOfInner(item) < 0) - { - return false; - } + return false; } + } - return true; + return true; - } + } - /// - /// Count the number of items of the collection equal to a particular value. - /// Returns 0 if and only if the value is not in the collection. - /// - /// The value to count. - /// The number of copies found. - public virtual int ContainsCount(T item) - { - ValidityCheck(); - return IndexOfInner(item) >= 0 ? 1 : 0; + /// + /// Count the number of items of the collection equal to a particular value. + /// Returns 0 if and only if the value is not in the collection. + /// + /// The value to count. + /// The number of copies found. + public virtual int ContainsCount(T item) + { + ValidityCheck(); + return IndexOfInner(item) >= 0 ? 1 : 0; - } + } - /// - /// - /// - /// - public virtual ICollectionValue UniqueItems() - { - return this; + /// + /// + /// + /// + public virtual ICollectionValue UniqueItems() + { + return this; - } + } - /// - /// - /// - /// - public virtual ICollectionValue> ItemMultiplicities() - { - return new MultiplicityOne(this); + /// + /// + /// + /// + public virtual ICollectionValue> ItemMultiplicities() + { + return new MultiplicityOne(this); - } + } - /// - /// Remove all items equal to a given one. - /// - /// The value to remove. - public virtual void RemoveAllCopies(T item) - { - Remove(item); + /// + /// Remove all items equal to a given one. + /// + /// The value to remove. + public virtual void RemoveAllCopies(T item) + { + Remove(item); - } + } - //TODO: check views - /// - /// Check the integrity of the internal data structures of this array list. - /// - /// True if check does not fail. - public override bool Check() - { - bool retval = true; + //TODO: check views + /// + /// Check the integrity of the internal data structures of this array list. + /// + /// True if check does not fail. + public override bool Check() + { + bool retval = true; - if (UnderlyingSize > array.Length) - { - Logger.Log(string.Format("underlyingsize ({0}) > array.Length ({1})", size, array.Length)); - return false; - } + if (UnderlyingSize > array.Length) + { + Logger.Log(string.Format("underlyingsize ({0}) > array.Length ({1})", size, array.Length)); + return false; + } - if (offsetField + size > UnderlyingSize) - { - Logger.Log(string.Format("offset({0})+size({1}) > underlyingsize ({2})", offsetField, size, UnderlyingSize)); - return false; - } + if (offsetField + size > UnderlyingSize) + { + Logger.Log(string.Format("offset({0})+size({1}) > underlyingsize ({2})", offsetField, size, UnderlyingSize)); + return false; + } - if (offsetField < 0) - { - Logger.Log(string.Format("offset({0}) < 0", offsetField)); - return false; - } + if (offsetField < 0) + { + Logger.Log(string.Format("offset({0}) < 0", offsetField)); + return false; + } - for (int i = 0; i < UnderlyingSize; i++) + for (int i = 0; i < UnderlyingSize; i++) + { + if (array[i] == null) { - if (array[i] == null) - { - Logger.Log(string.Format("Bad element: null at (base)index {0}", i)); - retval = false; - } + Logger.Log(string.Format("Bad element: null at (base)index {0}", i)); + retval = false; } + } - for (int i = UnderlyingSize, length = array.Length; i < length; i++) + for (int i = UnderlyingSize, length = array.Length; i < length; i++) + { + if (!Equals(array[i], default)) { - if (!Equals(array[i], default)) - { - Logger.Log(string.Format("Bad element: != default(T) at (base)index {0}", i)); - retval = false; - } + Logger.Log(string.Format("Bad element: != default(T) at (base)index {0}", i)); + retval = false; } + } + { + HashedArrayList u = underlying ?? this; + if (u.views != null) { - HashedArrayList u = underlying ?? this; - if (u.views != null) + foreach (HashedArrayList v in u.views) { - foreach (HashedArrayList v in u.views) + if (u.array != v.array) { - if (u.array != v.array) - { - Logger.Log(string.Format("View from {0} of length {1} has different base array than the underlying list", v.offsetField, v.size)); - retval = false; - } + Logger.Log(string.Format("View from {0} of length {1} has different base array than the underlying list", v.offsetField, v.size)); + retval = false; } } } + } + + if (UnderlyingSize != itemIndex.Count) + { + Logger.Log(string.Format("size ({0})!= index.Count ({1})", size, itemIndex.Count)); + retval = false; + } + + for (int i = 0; i < UnderlyingSize; i++) + { + var p = new SCG.KeyValuePair(array[i], default); - if (UnderlyingSize != itemIndex.Count) + if (!itemIndex.Find(ref p)) { - Logger.Log(string.Format("size ({0})!= index.Count ({1})", size, itemIndex.Count)); + Logger.Log(string.Format("Item {1} at {0} not in hashindex", i, array[i])); retval = false; } - for (int i = 0; i < UnderlyingSize; i++) + if (p.Value != i) { - var p = new SCG.KeyValuePair(array[i], default); - - if (!itemIndex.Find(ref p)) - { - Logger.Log(string.Format("Item {1} at {0} not in hashindex", i, array[i])); - retval = false; - } - - if (p.Value != i) - { - Logger.Log(string.Format("Item {1} at {0} has hashindex {2}", i, array[i], p.Value)); - retval = false; - } + Logger.Log(string.Format("Item {1} at {0} has hashindex {2}", i, array[i], p.Value)); + retval = false; } - return retval; } + return retval; + } - #endregion + #endregion - #region IExtensible Members + #region IExtensible Members - /// - /// - /// - /// True, indicating array list has bag semantics. - public virtual bool AllowsDuplicates => false; + /// + /// + /// + /// True, indicating array list has bag semantics. + public virtual bool AllowsDuplicates => false; - /// - /// By convention this is true for any collection with set semantics. - /// - /// True if only one representative of a group of equal items - /// is kept in the collection together with the total count. - public virtual bool DuplicatesByCounting => true; + /// + /// By convention this is true for any collection with set semantics. + /// + /// True if only one representative of a group of equal items + /// is kept in the collection together with the total count. + public virtual bool DuplicatesByCounting => true; - /// - /// Add an item to end of this list. - /// - /// The item to add. - /// True - public virtual bool Add(T item) + /// + /// Add an item to end of this list. + /// + /// The item to add. + /// True + public virtual bool Add(T item) + { + UpdateCheck(); + System.Collections.Generic.KeyValuePair p = new(item, size + offsetField); + if (itemIndex.FindOrAdd(ref p)) { - UpdateCheck(); - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(item, size + offsetField); - if (itemIndex.FindOrAdd(ref p)) - { - return false; - } - - InsertBase(size, item); - ReIndex(size + offsetField); - (underlying ?? this).RaiseForAdd(item); - return true; + return false; } + InsertBase(size, item); + ReIndex(size + offsetField); + (underlying ?? this).RaiseForAdd(item); + return true; + } - /// - /// Add the elements from another collection to this collection. - /// - /// - public virtual void AddAll(SCG.IEnumerable items) + + /// + /// Add the elements from another collection to this collection. + /// + /// + public virtual void AddAll(SCG.IEnumerable items) + { + UpdateCheck(); + int toadd = CountItems(items); + if (toadd == 0) { - UpdateCheck(); - int toadd = CountItems(items); - if (toadd == 0) - { - return; - } + return; + } - if (toadd + UnderlyingSize > array.Length) - { - Expand(toadd + UnderlyingSize, UnderlyingSize); - } + if (toadd + UnderlyingSize > array.Length) + { + Expand(toadd + UnderlyingSize, UnderlyingSize); + } - int i = size + offsetField; - if (UnderlyingSize > i) - { - Array.Copy(array, i, array, i + toadd, UnderlyingSize - i); - } + int i = size + offsetField; + if (UnderlyingSize > i) + { + Array.Copy(array, i, array, i + toadd, UnderlyingSize - i); + } - try + try + { + foreach (T item in items) { - foreach (T item in items) + System.Collections.Generic.KeyValuePair p = new(item, i); + if (itemIndex.FindOrAdd(ref p)) { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(item, i); - if (itemIndex.FindOrAdd(ref p)) - { - continue; - } - - array[i++] = item; + continue; } + + array[i++] = item; } - finally + } + finally + { + int added = i - size - offsetField; + if (added < toadd) { - int added = i - size - offsetField; - if (added < toadd) - { - Array.Copy(array, size + offsetField + toadd, array, i, UnderlyingSize - size - offsetField); - Array.Clear(array, UnderlyingSize + added, toadd - added); - } - if (added > 0) - { - AddToSize(added); - ReIndex(i); - FixViewsAfterInsert(added, i - added); - (underlying ?? this).RaiseForAddAll(i - added, added); - } + Array.Copy(array, size + offsetField + toadd, array, i, UnderlyingSize - size - offsetField); + Array.Clear(array, UnderlyingSize + added, toadd - added); + } + if (added > 0) + { + AddToSize(added); + ReIndex(i); + FixViewsAfterInsert(added, i - added); + (underlying ?? this).RaiseForAddAll(i - added, added); } } - private void RaiseForAddAll(int start, int added) + } + private void RaiseForAddAll(int start, int added) + { + if ((ActiveEvents & EventType.Added) != 0) { - if ((ActiveEvents & EventType.Added) != 0) + for (int i = start, end = start + added; i < end; i++) { - for (int i = start, end = start + added; i < end; i++) - { - RaiseItemsAdded(array[i], 1); - } + RaiseItemsAdded(array[i], 1); } - - RaiseCollectionChanged(); } - #endregion + RaiseCollectionChanged(); + } - #region IDirectedEnumerable Members + #endregion - /// - /// Create a collection containing the same items as this collection, but - /// whose enumerator will enumerate the items backwards. The new collection - /// will become invalid if the original is modified. Method typically used as in - /// foreach (T x in coll.Backwards()) {...} - /// - /// The backwards collection. - IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } + #region IDirectedEnumerable Members - #endregion + /// + /// Create a collection containing the same items as this collection, but + /// whose enumerator will enumerate the items backwards. The new collection + /// will become invalid if the original is modified. Method typically used as in + /// foreach (T x in coll.Backwards()) {...} + /// + /// The backwards collection. + IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } - #region ICollectionValue Members - /// - /// - /// - /// The number of items in this collection - public override int Count { get { ValidityCheck(); return size; } } - #endregion + #endregion - #region IEnumerable Members - //TODO: make tests of all calls on a disposed view throws the right exception! (Which should be C5.InvalidListViewException) - /// - /// Create an enumerator for the collection - /// - /// The enumerator - public override SCG.IEnumerator GetEnumerator() - { - ValidityCheck(); - return base.GetEnumerator(); - } - #endregion + #region ICollectionValue Members + /// + /// + /// + /// The number of items in this collection + public override int Count { get { ValidityCheck(); return size; } } + #endregion - #region IDisposable Members + #region IEnumerable Members + //TODO: make tests of all calls on a disposed view throws the right exception! (Which should be C5.InvalidListViewException) + /// + /// Create an enumerator for the collection + /// + /// The enumerator + public override SCG.IEnumerator GetEnumerator() + { + ValidityCheck(); + return base.GetEnumerator(); + } + #endregion - /// - /// Invalidate this list. If a view, just invalidate the view. - /// If not a view, invalidate the list and all views on it. - /// - public virtual void Dispose() - { - Dispose(false); - } + #region IDisposable Members + + /// + /// Invalidate this list. If a view, just invalidate the view. + /// If not a view, invalidate the list and all views on it. + /// + public virtual void Dispose() + { + GC.SuppressFinalize(this); + + Dispose(false); + } - private void Dispose(bool disposingUnderlying) + private void Dispose(bool disposingUnderlying) + { + if (isValid) { - if (isValid) + if (underlying != null) { - if (underlying != null) + isValid = false; + if (!disposingUnderlying && views != null) { - isValid = false; - if (!disposingUnderlying && views != null) - { - views.Remove(myWeakReference!); - } - - underlying = null; - views = null; - myWeakReference = null; + views.Remove(myWeakReference!); } - else + + underlying = null; + views = null; + myWeakReference = null; + } + else + { + //isValid = false; + if (views != null) { - //isValid = false; - if (views != null) + foreach (HashedArrayList view in views) { - foreach (HashedArrayList view in views) - { - view.Dispose(true); - } + view.Dispose(true); } - - Clear(); } + + Clear(); } } + } - #endregion + #endregion + + #region ISerializable Members + /* +/// +/// +/// +/// +/// +public HashedArrayList(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : + this(info.GetInt32("sz"),(SCG.IEqualityComparer)(info.GetValue("eq",typeof(SCG.IEqualityComparer)))) +{ + size = info.GetInt32("sz"); + for (int i = 0; i < size; i++) + { + array[i] = (T)(info.GetValue("elem" + i,typeof(T))); + } + reindex(0); +} - #region ISerializable Members - /* - /// - /// - /// - /// - /// - public HashedArrayList(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : - this(info.GetInt32("sz"),(SCG.IEqualityComparer)(info.GetValue("eq",typeof(SCG.IEqualityComparer)))) +/// +/// +/// +/// +/// +public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) +{ + info.AddValue("sz", size); + info.AddValue("eq", EqualityComparer); + for (int i = 0; i < size; i++) + { + info.AddValue("elem" + i, array[i + offset]); + } +} +*/ + #endregion + + #region System.Collections.Generic.IList Members + + void System.Collections.Generic.IList.RemoveAt(int index) { - size = info.GetInt32("sz"); - for (int i = 0; i < size; i++) - { - array[i] = (T)(info.GetValue("elem" + i,typeof(T))); - } - reindex(0); + RemoveAt(index); } - /// - /// - /// - /// - /// - public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) + void System.Collections.Generic.ICollection.Add(T item) { - info.AddValue("sz", size); - info.AddValue("eq", EqualityComparer); - for (int i = 0; i < size; i++) - { - info.AddValue("elem" + i, array[i + offset]); - } + Add(item); } -*/ - #endregion - #region System.Collections.Generic.IList Members + #endregion - void System.Collections.Generic.IList.RemoveAt(int index) + #region System.Collections.ICollection Members + + bool System.Collections.ICollection.IsSynchronized => false; + + [Obsolete] + object System.Collections.ICollection.SyncRoot => underlying != null ? ((System.Collections.ICollection)underlying).SyncRoot : array; + + void System.Collections.ICollection.CopyTo(Array arr, int index) + { + if (index < 0 || index + Count > arr.Length) { - RemoveAt(index); + throw new ArgumentOutOfRangeException(nameof(index)); } - void System.Collections.Generic.ICollection.Add(T item) + foreach (T item in this) { - Add(item); + arr.SetValue(item, index++); } + } - #endregion - - #region System.Collections.ICollection Members - - bool System.Collections.ICollection.IsSynchronized => false; + #endregion - [Obsolete] - Object System.Collections.ICollection.SyncRoot => underlying != null ? ((System.Collections.ICollection)underlying).SyncRoot : array; + #region System.Collections.IList Members - void System.Collections.ICollection.CopyTo(Array arr, int index) + object? System.Collections.IList.this[int index] + { + get => this[index]!; + set { - if (index < 0 || index + Count > arr.Length) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } + if (value is null && default(T) is not null) throw new ArgumentNullException(nameof(value)); + if (value is not T) throw new ArgumentException("Wrong type", nameof(value)); - foreach (T item in this) - { - arr.SetValue(item, index++); - } + this[index] = (T)value; } + } - #endregion + int System.Collections.IList.Add(object? value) + { + if (value is null && default(T) is not null) throw new ArgumentNullException(nameof(value)); + if (value is not T) throw new ArgumentException("Wrong type", nameof(value)); - #region System.Collections.IList Members + bool added = Add((T)value); + // What position to report if item not added? SC.IList.Add doesn't say + return added ? Count - 1 : -1; + } - Object System.Collections.IList.this[int index] - { - get => this[index]!; - set => this[index] = (T)value; - } + bool System.Collections.IList.Contains(object? value) + { + if (value is null && default(T) is not null) return false; + if (value is not T) return false; - int System.Collections.IList.Add(Object o) - { - bool added = Add((T)o); - // What position to report if item not added? SC.IList.Add doesn't say - return added ? Count - 1 : -1; - } + return Contains((T)value); + } - bool System.Collections.IList.Contains(Object o) - { - return Contains((T)o); - } + int System.Collections.IList.IndexOf(object? value) + { + if (value is null && default(T) is not null) return -1; + if (value is not T) return -1; - int System.Collections.IList.IndexOf(Object o) - { - return Math.Max(-1, IndexOf((T)o)); - } + return Math.Max(-1, IndexOf((T)value)); + } - void System.Collections.IList.Insert(int index, Object o) - { - Insert(index, (T)o); - } + void System.Collections.IList.Insert(int index, object? value) + { + if (value is null && default(T) is not null) throw new ArgumentNullException(nameof(value)); + if (value is not T) throw new ArgumentException("Wrong type", nameof(value)); - void System.Collections.IList.Remove(Object o) - { - Remove((T)o); - } + Insert(index, (T)value); + } - void System.Collections.IList.RemoveAt(int index) - { - RemoveAt(index); - } + void System.Collections.IList.Remove(object? value) + { + if (value is null && default(T) is not null) return; + if (value is not T) return; - #endregion + Remove((T)value); } + + void System.Collections.IList.RemoveAt(int index) + { + RemoveAt(index); + } + + #endregion } diff --git a/C5/Arrays/SortedArray.cs b/C5/Arrays/SortedArray.cs index af0a5182..33e23c31 100644 --- a/C5/Arrays/SortedArray.cs +++ b/C5/Arrays/SortedArray.cs @@ -3,1452 +3,1451 @@ using System; using SCG = System.Collections.Generic; -namespace C5 + +namespace C5; + +/// +/// A collection class implementing a sorted dynamic array data structure. +/// +public class SortedArray : ArrayBase, IIndexedSorted { + #region Events + /// - /// A collection class implementing a sorted dynamic array data structure. + /// /// - public class SortedArray : ArrayBase, IIndexedSorted - { - #region Events + /// + public override EventType ListenableEvents => EventType.Basic; - /// - /// - /// - /// - public override EventType ListenableEvents => EventType.Basic; + #endregion - #endregion + #region Fields - #region Fields + private readonly SCG.IComparer _comparer; - private readonly SCG.IComparer _comparer; + #endregion - #endregion + #region Util + /// + /// + /// + /// The item to search for + /// The least index, middle, for which array[middle] >= item + /// True if item found + private bool BinarySearch(T item, out int middle) + { + int bottom = 0, top = size; + + middle = top / 2; - #region Util - /// - /// - /// - /// The item to search for - /// The least index, middle, for which array[middle] >= item - /// True if item found - private bool BinarySearch(T item, out int middle) + while (top > bottom) { - int bottom = 0, top = size; + int comparer; - middle = top / 2; + if ((comparer = _comparer.Compare(array[middle], item)) == 0) + { + return true; + } - while (top > bottom) + if (comparer > 0) { - int comparer; + top = middle; + } + else + { + bottom = middle + 1; + } - if ((comparer = _comparer.Compare(array[middle], item)) == 0) - { - return true; - } + middle = bottom + ((top - bottom) / 2); + } - if (comparer > 0) - { - top = middle; - } - else - { - bottom = middle + 1; - } + return false; + } - middle = bottom + ((top - bottom) / 2); - } + private int IndexOfInner(T item) + { - return false; + if (BinarySearch(item, out int ind)) + { + return ind; } - private int IndexOfInner(T item) - { + return ~ind; + } - if (BinarySearch(item, out int ind)) - { - return ind; - } + #endregion - return ~ind; - } + #region Constructors - #endregion - - #region Constructors - - /// - /// Create a dynamic sorted array with a natural comparer - /// (and item equalityComparer, assumed compatible) - /// - /// If T is not comparable. - /// - public SortedArray() : this(8) { } - - - /// - /// Create a dynamic sorted array with a natural comparer - /// (and item equalityComparer, assumed compatible) - /// and prescribed initial capacity. - /// - /// If T is not comparable. - /// - /// The capacity - public SortedArray(int capacity) - : this(capacity, SCG.Comparer.Default, EqualityComparer.Default) { } - - - /// - /// Create a dynamic sorted array with an external comparer. - /// The itemequalityComparer will be compatible - /// since the - /// default equalityComparer for T () - /// is unlikely to be compatible with the external comparer. This makes the - /// array inadequate for use as item in a collection of unsequenced or sequenced sets or bags - /// ( and ) - /// - /// - /// The comparer - public SortedArray(SCG.IComparer comparer) - : this(8, comparer) { } - - /// - /// Create a dynamic sorted array with an external comparer - /// and prescribed initial capacity. - /// The itemequalityComparer will be a compatible - /// since the - /// default equalityComparer for T () - /// is unlikely to be compatible with the external comparer. This makes the - /// sorted array inadequate for use as item in a collection of unsequenced or sequenced sets or bags - /// ( and ) - /// - /// - /// The capacity - /// The comparer - public SortedArray(int capacity, SCG.IComparer comparer) - : this(capacity, comparer, new ComparerZeroHashCodeEqualityComparer(comparer)) { } - - /// - /// Create a dynamic sorted array with an external comparer, an external item equalityComparer - /// and prescribed initial capacity. This is the constructor to use if the collection - /// will be used as item in a hash table based collection. - /// - /// The capacity - /// The item comparer - /// The item equalityComparer (assumed compatible) - public SortedArray(int capacity, SCG.IComparer comparer, SCG.IEqualityComparer equalityComparer) - : base(capacity, equalityComparer) - { - _comparer = comparer ?? throw new NullReferenceException("Comparer cannot be null"); - } + /// + /// Create a dynamic sorted array with a natural comparer + /// (and item equalityComparer, assumed compatible) + /// + /// If T is not comparable. + /// + public SortedArray() : this(8) { } - #endregion - #region IIndexedSorted Members + /// + /// Create a dynamic sorted array with a natural comparer + /// (and item equalityComparer, assumed compatible) + /// and prescribed initial capacity. + /// + /// If T is not comparable. + /// + /// The capacity + public SortedArray(int capacity) + : this(capacity, SCG.Comparer.Default, EqualityComparer.Default) { } - /// - /// Determine the number of items at or above a supplied threshold. - /// - /// The lower bound (inclusive) - /// The number of matching items. - public int CountFrom(T bot) - { - BinarySearch(bot, out int lo); - return size - lo; - } + /// + /// Create a dynamic sorted array with an external comparer. + /// The itemequalityComparer will be compatible + /// since the + /// default equalityComparer for T () + /// is unlikely to be compatible with the external comparer. This makes the + /// array inadequate for use as item in a collection of unsequenced or sequenced sets or bags + /// ( and ) + /// + /// + /// The comparer + public SortedArray(SCG.IComparer comparer) + : this(8, comparer) { } + /// + /// Create a dynamic sorted array with an external comparer + /// and prescribed initial capacity. + /// The itemequalityComparer will be a compatible + /// since the + /// default equalityComparer for T () + /// is unlikely to be compatible with the external comparer. This makes the + /// sorted array inadequate for use as item in a collection of unsequenced or sequenced sets or bags + /// ( and ) + /// + /// + /// The capacity + /// The comparer + public SortedArray(int capacity, SCG.IComparer comparer) + : this(capacity, comparer, new ComparerZeroHashCodeEqualityComparer(comparer)) { } - /// - /// Determine the number of items between two supplied thresholds. - /// - /// The lower bound (inclusive) - /// The upper bound (exclusive) - /// The number of matching items. - public int CountFromTo(T bot, T top) - { + /// + /// Create a dynamic sorted array with an external comparer, an external item equalityComparer + /// and prescribed initial capacity. This is the constructor to use if the collection + /// will be used as item in a hash table based collection. + /// + /// The capacity + /// The item comparer + /// The item equalityComparer (assumed compatible) + public SortedArray(int capacity, SCG.IComparer comparer, SCG.IEqualityComparer equalityComparer) + : base(capacity, equalityComparer) + { + _comparer = comparer ?? throw new NullReferenceException("Comparer cannot be null"); + } - BinarySearch(bot, out int lo); - BinarySearch(top, out int hi); - return hi > lo ? hi - lo : 0; - } + #endregion + #region IIndexedSorted Members - /// - /// Determine the number of items below a supplied threshold. - /// - /// The upper bound (exclusive) - /// The number of matching items. - public int CountTo(T top) - { + /// + /// Determine the number of items at or above a supplied threshold. + /// + /// The lower bound (inclusive) + /// The number of matching items. + public int CountFrom(T bot) + { - BinarySearch(top, out int hi); - return hi; - } + BinarySearch(bot, out int lo); + return size - lo; + } - /// - /// Query this sorted collection for items greater than or equal to a supplied value. - /// - /// The lower bound (inclusive). - /// The result directed collection. - public IDirectedCollectionValue RangeFrom(T bot) - { + /// + /// Determine the number of items between two supplied thresholds. + /// + /// The lower bound (inclusive) + /// The upper bound (exclusive) + /// The number of matching items. + public int CountFromTo(T bot, T top) + { - BinarySearch(bot, out int lo); - return new Range(this, lo, size - lo, true); - } + BinarySearch(bot, out int lo); + BinarySearch(top, out int hi); + return hi > lo ? hi - lo : 0; + } - /// - /// Query this sorted collection for items between two supplied values. - /// - /// The lower bound (inclusive). - /// The upper bound (exclusive). - /// The result directed collection. - public IDirectedCollectionValue RangeFromTo(T bot, T top) - { + /// + /// Determine the number of items below a supplied threshold. + /// + /// The upper bound (exclusive) + /// The number of matching items. + public int CountTo(T top) + { - BinarySearch(bot, out int lo); - BinarySearch(top, out int hi); + BinarySearch(top, out int hi); + return hi; + } - int sz = hi - lo; - return new Range(this, lo, sz, true); - } + /// + /// Query this sorted collection for items greater than or equal to a supplied value. + /// + /// The lower bound (inclusive). + /// The result directed collection. + public IDirectedCollectionValue RangeFrom(T bot) + { + BinarySearch(bot, out int lo); + return new Range(this, lo, size - lo, true); + } - /// - /// Query this sorted collection for items less than a supplied value. - /// - /// The upper bound (exclusive). - /// The result directed collection. - public IDirectedCollectionValue RangeTo(T top) - { - BinarySearch(top, out int hi); - return new Range(this, 0, hi, true); - } + /// + /// Query this sorted collection for items between two supplied values. + /// + /// The lower bound (inclusive). + /// The upper bound (exclusive). + /// The result directed collection. + public IDirectedCollectionValue RangeFromTo(T bot, T top) + { + BinarySearch(bot, out int lo); + BinarySearch(top, out int hi); - /// - /// Create a new indexed sorted collection consisting of the items of this - /// indexed sorted collection satisfying a certain predicate. - /// - /// The filter delegate defining the predicate. - /// The new indexed sorted collection. - public IIndexedSorted FindAll(Func f) - { - SortedArray res = new SortedArray(_comparer); - int j = 0, rescap = res.array.Length; + int sz = hi - lo; - for (int i = 0; i < size; i++) - { - T a = array[i]; + return new Range(this, lo, sz, true); + } - if (f(a)) - { - if (j == rescap) - { - res.Expand(rescap = 2 * rescap, j); - } - res.array[j++] = a; - } - } + /// + /// Query this sorted collection for items less than a supplied value. + /// + /// The upper bound (exclusive). + /// The result directed collection. + public IDirectedCollectionValue RangeTo(T top) + { + + BinarySearch(top, out int hi); + return new Range(this, 0, hi, true); + } - res.size = j; - return res; - } + /// + /// Create a new indexed sorted collection consisting of the items of this + /// indexed sorted collection satisfying a certain predicate. + /// + /// The filter delegate defining the predicate. + /// The new indexed sorted collection. + public IIndexedSorted FindAll(Func f) + { + SortedArray res = new(_comparer); + int j = 0, rescap = res.array.Length; - /// - /// Create a new indexed sorted collection consisting of the results of - /// mapping all items of this list. - /// if the map is not increasing over - /// the items of this collection (with respect to the two given comparison - /// relations). - /// - /// The delegate definging the map. - /// The comparion relation to use for the result. - /// The new sorted collection. - public IIndexedSorted Map(Func m, SCG.IComparer c) + for (int i = 0; i < size; i++) { - SortedArray res = new SortedArray(size, c); + T a = array[i]; - if (size > 0) + if (f(a)) { - V oldv = res.array[0] = m(array[0]), newv; - - for (int i = 1; i < size; i++) + if (j == rescap) { - if (c.Compare(oldv, newv = res.array[i] = m(array[i])) >= 0) - { - throw new ArgumentException("mapper not monotonic"); - } - - oldv = newv; + res.Expand(rescap = 2 * rescap, j); } - } - res.size = size; - return res; + res.array[j++] = a; + } } - #endregion - - #region ISorted Members + res.size = j; + return res; + } - /// - /// Find the strict predecessor of item in the sorted array, - /// that is, the greatest item in the collection smaller than the item. - /// - /// The item to find the predecessor for. - /// The predecessor, if any; otherwise the default value for T. - /// True if item has a predecessor; otherwise false. - public bool TryPredecessor(T item, out T res) - { - BinarySearch(item, out int lo); - if (lo == 0) - { - res = default; - return false; - } - else - { - res = array[lo - 1]; - return true; - } - } + /// + /// Create a new indexed sorted collection consisting of the results of + /// mapping all items of this list. + /// if the map is not increasing over + /// the items of this collection (with respect to the two given comparison + /// relations). + /// + /// The delegate definging the map. + /// The comparion relation to use for the result. + /// The new sorted collection. + public IIndexedSorted Map(Func m, SCG.IComparer c) + { + SortedArray res = new(size, c); - /// - /// Find the strict successor of item in the sorted array, - /// that is, the least item in the collection greater than the supplied value. - /// - /// The item to find the successor for. - /// The successor, if any; otherwise the default value for T. - /// True if item has a successor; otherwise false. - public bool TrySuccessor(T item, out T res) + if (size > 0) { - if (BinarySearch(item, out int hi)) - { - hi++; - } + V oldv = res.array[0] = m(array[0]), newv; - if (hi >= size) + for (int i = 1; i < size; i++) { - res = default; - return false; - } - else - { - res = array[hi]; - return true; + if (c.Compare(oldv, newv = res.array[i] = m(array[i])) >= 0) + { + throw new ArgumentException("mapper not monotonic"); + } + + oldv = newv; } } + res.size = size; + return res; + } - /// - /// Find the weak predecessor of item in the sorted array, - /// that is, the greatest item in the collection smaller than or equal to the item. - /// - /// The item to find the weak predecessor for. - /// The weak predecessor, if any; otherwise the default value for T. - /// True if item has a weak predecessor; otherwise false. - public bool TryWeakPredecessor(T item, out T res) - { + #endregion - if (!BinarySearch(item, out int lo)) - { - lo--; - } + #region ISorted Members - if (lo < 0) - { - res = default; - return false; - } - else - { - res = array[lo]; - return true; - } + /// + /// Find the strict predecessor of item in the sorted array, + /// that is, the greatest item in the collection smaller than the item. + /// + /// The item to find the predecessor for. + /// The predecessor, if any; otherwise the default value for T. + /// True if item has a predecessor; otherwise false. + public bool TryPredecessor(T item, out T res) + { + BinarySearch(item, out int lo); + if (lo == 0) + { + res = default; + return false; } + else + { + res = array[lo - 1]; + return true; + } + } - /// - /// Find the weak successor of item in the sorted array, - /// that is, the least item in the collection greater than or equal to the supplied value. - /// - /// The item to find the weak successor for. - /// The weak successor, if any; otherwise the default value for T. - /// True if item has a weak successor; otherwise false. - public bool TryWeakSuccessor(T item, out T res) + /// + /// Find the strict successor of item in the sorted array, + /// that is, the least item in the collection greater than the supplied value. + /// + /// The item to find the successor for. + /// The successor, if any; otherwise the default value for T. + /// True if item has a successor; otherwise false. + public bool TrySuccessor(T item, out T res) + { + if (BinarySearch(item, out int hi)) { + hi++; + } - BinarySearch(item, out int hi); - if (hi >= size) - { - res = default; - return false; - } - else - { - res = array[hi]; - return true; - } + if (hi >= size) + { + res = default; + return false; } + else + { + res = array[hi]; + return true; + } + } - /// - /// Find the strict predecessor in the sorted collection of a particular value, - /// i.e. the largest item in the collection less than the supplied value. - /// - /// if no such element exists (the - /// supplied value is less than or equal to the minimum of this collection.) - /// The item to find the predecessor for. - /// The predecessor. - public T Predecessor(T item) + /// + /// Find the weak predecessor of item in the sorted array, + /// that is, the greatest item in the collection smaller than or equal to the item. + /// + /// The item to find the weak predecessor for. + /// The weak predecessor, if any; otherwise the default value for T. + /// True if item has a weak predecessor; otherwise false. + public bool TryWeakPredecessor(T item, out T res) + { + if (!BinarySearch(item, out int lo)) { + lo--; + } - BinarySearch(item, out int lo); - if (lo == 0) - { - throw new NoSuchItemException(); - } - - return array[lo - 1]; + if (lo < 0) + { + res = default; + return false; + } + else + { + res = array[lo]; + return true; } + } + + /// + /// Find the weak successor of item in the sorted array, + /// that is, the least item in the collection greater than or equal to the supplied value. + /// + /// The item to find the weak successor for. + /// The weak successor, if any; otherwise the default value for T. + /// True if item has a weak successor; otherwise false. + public bool TryWeakSuccessor(T item, out T res) + { - /// - /// Find the strict successor in the sorted collection of a particular value, - /// i.e. the least item in the collection greater than the supplied value. - /// - /// if no such element exists (the - /// supplied value is greater than or equal to the maximum of this collection.) - /// The item to find the successor for. - /// The successor. - public T Successor(T item) + BinarySearch(item, out int hi); + if (hi >= size) { + res = default; + return false; + } + else + { + res = array[hi]; + return true; + } + } - if (BinarySearch(item, out int hi)) - { - hi++; - } - if (hi >= size) - { - throw new NoSuchItemException(); - } + /// + /// Find the strict predecessor in the sorted collection of a particular value, + /// i.e. the largest item in the collection less than the supplied value. + /// + /// if no such element exists (the + /// supplied value is less than or equal to the minimum of this collection.) + /// The item to find the predecessor for. + /// The predecessor. + public T Predecessor(T item) + { - return array[hi]; + BinarySearch(item, out int lo); + if (lo == 0) + { + throw new NoSuchItemException(); } + return array[lo - 1]; + } - /// - /// Find the weak predecessor in the sorted collection of a particular value, - /// i.e. the largest item in the collection less than or equal to the supplied value. - /// if no such element exists (the - /// supplied value is less than the minimum of this collection.) - /// - /// The item to find the weak predecessor for. - /// The weak predecessor. - public T WeakPredecessor(T item) - { - if (!BinarySearch(item, out int lo)) - { - lo--; - } + /// + /// Find the strict successor in the sorted collection of a particular value, + /// i.e. the least item in the collection greater than the supplied value. + /// + /// if no such element exists (the + /// supplied value is greater than or equal to the maximum of this collection.) + /// The item to find the successor for. + /// The successor. + public T Successor(T item) + { - if (lo < 0) - { - throw new NoSuchItemException(); - } + if (BinarySearch(item, out int hi)) + { + hi++; + } - return array[lo]; + if (hi >= size) + { + throw new NoSuchItemException(); } + return array[hi]; + } - /// - /// Find the weak successor in the sorted collection of a particular value, - /// i.e. the least item in the collection greater than or equal to the supplied value. - /// - /// if no such element exists (the - /// supplied value is greater than the maximum of this collection.) - /// The item to find the weak successor for. - /// The weak successor. - public T WeakSuccessor(T item) - { - BinarySearch(item, out int hi); - if (hi >= size) - { - throw new NoSuchItemException(); - } + /// + /// Find the weak predecessor in the sorted collection of a particular value, + /// i.e. the largest item in the collection less than or equal to the supplied value. + /// if no such element exists (the + /// supplied value is less than the minimum of this collection.) + /// + /// The item to find the weak predecessor for. + /// The weak predecessor. + public T WeakPredecessor(T item) + { - return array[hi]; + if (!BinarySearch(item, out int lo)) + { + lo--; } - - /// - /// Perform a search in the sorted collection for the ranges in which a - /// non-increasing (i.e. weakly decreasing) function from the item type to - /// int is - /// negative, zero respectively positive. If the supplied cut function is - /// not non-increasing, the result of this call is undefined. - /// - /// The cut function T to int, given - /// as an IComparable<T> object, where the cut function is - /// the c.CompareTo(T that) method. - /// Returns the largest item in the collection, where the - /// cut function is positive (if any). - /// True if the cut function is positive somewhere - /// on this collection. - /// Returns the least item in the collection, where the - /// cut function is negative (if any). - /// True if the cut function is negative somewhere - /// on this collection. - /// - public bool Cut(IComparable c, out T low, out bool lowIsValid, out T high, out bool highIsValid) + if (lo < 0) { - int lbest = -1, rbest = size; + throw new NoSuchItemException(); + } - low = default; - lowIsValid = false; - high = default; - highIsValid = false; + return array[lo]; + } - int bot = 0, top = size, mid, comp = -1, sol; - mid = top / 2; - while (top > bot) - { - if ((comp = c.CompareTo(array[mid])) == 0) - { - break; - } + /// + /// Find the weak successor in the sorted collection of a particular value, + /// i.e. the least item in the collection greater than or equal to the supplied value. + /// + /// if no such element exists (the + /// supplied value is greater than the maximum of this collection.) + /// The item to find the weak successor for. + /// The weak successor. + public T WeakSuccessor(T item) + { - if (comp < 0) - { rbest = top = mid; } - else - { lbest = mid; bot = mid + 1; } + BinarySearch(item, out int hi); + if (hi >= size) + { + throw new NoSuchItemException(); + } - mid = (bot + top) / 2; - } + return array[hi]; + } - if (comp != 0) - { - if (lbest >= 0) { lowIsValid = true; low = array[lbest]; } - if (rbest < size) { highIsValid = true; high = array[rbest]; } + /// + /// Perform a search in the sorted collection for the ranges in which a + /// non-increasing (i.e. weakly decreasing) function from the item type to + /// int is + /// negative, zero respectively positive. If the supplied cut function is + /// not non-increasing, the result of this call is undefined. + /// + /// The cut function T to int, given + /// as an IComparable<T> object, where the cut function is + /// the c.CompareTo(T that) method. + /// Returns the largest item in the collection, where the + /// cut function is positive (if any). + /// True if the cut function is positive somewhere + /// on this collection. + /// Returns the least item in the collection, where the + /// cut function is negative (if any). + /// True if the cut function is negative somewhere + /// on this collection. + /// + public bool Cut(IComparable c, out T low, out bool lowIsValid, out T high, out bool highIsValid) + { + int lbest = -1, rbest = size; - return false; - } + low = default; + lowIsValid = false; + high = default; + highIsValid = false; - sol = mid; - bot = sol - 1; + int bot = 0, top = size, mid, comp = -1, sol; - //Invariant: c.Compare(array[x]) < 0 when rbest <= x < size - // c.Compare(array[x]) >= 0 when x < bot) - //(Assuming c.Compare monotonic) - while (rbest > bot) + mid = top / 2; + while (top > bot) + { + if ((comp = c.CompareTo(array[mid])) == 0) { - mid = (bot + rbest) / 2; - if (c.CompareTo(array[mid]) < 0) - { rbest = mid; } - else - { bot = mid + 1; } + break; } + if (comp < 0) + { rbest = top = mid; } + else + { lbest = mid; bot = mid + 1; } + + mid = (bot + top) / 2; + } + + if (comp != 0) + { + if (lbest >= 0) { lowIsValid = true; low = array[lbest]; } + if (rbest < size) { highIsValid = true; high = array[rbest]; } - top = sol + 1; + return false; + } - //Invariant: c.Compare(array[x]) > 0 when 0 <= x <= lbest - // c.Compare(array[x]) <= 0 when x>top) - //(Assuming c.Compare monotonic) - while (top > lbest) - { - mid = (lbest + top + 1) / 2; - if (c.CompareTo(array[mid]) > 0) - { lbest = mid; } - else - { top = mid - 1; } - } + sol = mid; + bot = sol - 1; - if (lbest >= 0) { lowIsValid = true; low = array[lbest]; } + //Invariant: c.Compare(array[x]) < 0 when rbest <= x < size + // c.Compare(array[x]) >= 0 when x < bot) + //(Assuming c.Compare monotonic) + while (rbest > bot) + { + mid = (bot + rbest) / 2; + if (c.CompareTo(array[mid]) < 0) + { rbest = mid; } + else + { bot = mid + 1; } + } - return true; + if (rbest < size) { highIsValid = true; high = array[rbest]; } + + top = sol + 1; + + //Invariant: c.Compare(array[x]) > 0 when 0 <= x <= lbest + // c.Compare(array[x]) <= 0 when x>top) + //(Assuming c.Compare monotonic) + while (top > lbest) + { + mid = (lbest + top + 1) / 2; + if (c.CompareTo(array[mid]) > 0) + { lbest = mid; } + else + { top = mid - 1; } } + if (lbest >= 0) { lowIsValid = true; low = array[lbest]; } - IDirectedEnumerable ISorted.RangeFrom(T bot) - { return RangeFrom(bot); } + return true; + } - IDirectedEnumerable ISorted.RangeFromTo(T bot, T top) - { return RangeFromTo(bot, top); } + IDirectedEnumerable ISorted.RangeFrom(T bot) + { return RangeFrom(bot); } - IDirectedEnumerable ISorted.RangeTo(T top) - { return RangeTo(top); } + IDirectedEnumerable ISorted.RangeFromTo(T bot, T top) + { return RangeFromTo(bot, top); } - /// - /// Create a directed collection with the same items as this collection. - /// - /// The result directed collection. - public IDirectedCollectionValue RangeAll() - { return new Range(this, 0, size, true); } + IDirectedEnumerable ISorted.RangeTo(T top) + { return RangeTo(top); } - /// - /// Add all the items from another collection with an enumeration order that - /// is increasing in the items. - /// if the enumerated items turns out - /// not to be in increasing order. - /// - /// The collection to add. - public void AddSorted(SCG.IEnumerable items) - { - //Unless items have <=1 elements we would expect it to be - //too expensive to do repeated inserts, thus: - UpdateCheck(); + /// + /// Create a directed collection with the same items as this collection. + /// + /// The result directed collection. + public IDirectedCollectionValue RangeAll() + { return new Range(this, 0, size, true); } - int j = 0, i = 0, c, itemcount = CountItems(items), numAdded = 0; - SortedArray res = new SortedArray(size + itemcount, _comparer); - T lastitem = default; - T[] addedItems = new T[itemcount]; - foreach (T item in items) - { - while (i < size && (c = _comparer.Compare(array[i], item)) <= 0) - { - lastitem = res.array[j++] = array[i++]; - if (c == 0) - { - goto next; - } - } + /// + /// Add all the items from another collection with an enumeration order that + /// is increasing in the items. + /// if the enumerated items turns out + /// not to be in increasing order. + /// + /// The collection to add. + public void AddSorted(SCG.IEnumerable items) + { + //Unless items have <=1 elements we would expect it to be + //too expensive to do repeated inserts, thus: + UpdateCheck(); + + int j = 0, i = 0, c, itemcount = CountItems(items), numAdded = 0; + SortedArray res = new(size + itemcount, _comparer); + T lastitem = default; + T[] addedItems = new T[itemcount]; - if (j > 0 && _comparer.Compare(lastitem, item) >= 0) + foreach (T item in items) + { + while (i < size && (c = _comparer.Compare(array[i], item)) <= 0) + { + lastitem = res.array[j++] = array[i++]; + if (c == 0) { - throw new ArgumentException("Argument not sorted"); + goto next; } - - addedItems[numAdded++] = lastitem = res.array[j++] = item; - next: - c = -1; } - while (i < size) + if (j > 0 && _comparer.Compare(lastitem, item) >= 0) { - res.array[j++] = array[i++]; + throw new ArgumentException("Argument not sorted"); } - size = j; - array = res.array; - RaiseForAddAll(addedItems, numAdded); + addedItems[numAdded++] = lastitem = res.array[j++] = item; + next: + c = -1; } - - /// - /// Remove all items of this collection above or at a supplied threshold. - /// - /// The lower threshold (inclusive). - public void RemoveRangeFrom(T low) + while (i < size) { + res.array[j++] = array[i++]; + } - BinarySearch(low, out int lowind); - if (lowind == size) - { - return; - } + size = j; + array = res.array; + RaiseForAddAll(addedItems, numAdded); + } - T[] removed = new T[size - lowind]; - Array.Copy(array, lowind, removed, 0, removed.Length); - Array.Reverse(removed); - Array.Clear(array, lowind, size - lowind); - size = lowind; + /// + /// Remove all items of this collection above or at a supplied threshold. + /// + /// The lower threshold (inclusive). + public void RemoveRangeFrom(T low) + { - RaiseForRemoveRange(removed); + BinarySearch(low, out int lowind); + if (lowind == size) + { + return; } + T[] removed = new T[size - lowind]; + Array.Copy(array, lowind, removed, 0, removed.Length); + Array.Reverse(removed); - /// - /// Remove all items of this collection between two supplied thresholds. - /// - /// The lower threshold (inclusive). - /// The upper threshold (exclusive). - public void RemoveRangeFromTo(T low, T hi) - { + Array.Clear(array, lowind, size - lowind); + size = lowind; - BinarySearch(low, out int lowind); - BinarySearch(hi, out int highind); - if (highind <= lowind) - { - return; - } + RaiseForRemoveRange(removed); + } - T[] removed = new T[highind - lowind]; - Array.Copy(array, lowind, removed, 0, removed.Length); - Array.Reverse(removed); - Array.Copy(array, highind, array, lowind, size - highind); - Array.Clear(array, size - highind + lowind, highind - lowind); - size -= highind - lowind; + /// + /// Remove all items of this collection between two supplied thresholds. + /// + /// The lower threshold (inclusive). + /// The upper threshold (exclusive). + public void RemoveRangeFromTo(T low, T hi) + { - RaiseForRemoveRange(removed); + BinarySearch(low, out int lowind); + BinarySearch(hi, out int highind); + if (highind <= lowind) + { + return; } + T[] removed = new T[highind - lowind]; + Array.Copy(array, lowind, removed, 0, removed.Length); + Array.Reverse(removed); - /// - /// Remove all items of this collection below a supplied threshold. - /// - /// The upper threshold (exclusive). - public void RemoveRangeTo(T hi) - { + Array.Copy(array, highind, array, lowind, size - highind); + Array.Clear(array, size - highind + lowind, highind - lowind); + size -= highind - lowind; - BinarySearch(hi, out int highind); - if (highind == 0) - { - return; - } + RaiseForRemoveRange(removed); + } - T[] removed = new T[highind]; - Array.Copy(array, 0, removed, 0, removed.Length); - Array.Copy(array, highind, array, 0, size - highind); - Array.Clear(array, size - highind, highind); - size -= highind; + /// + /// Remove all items of this collection below a supplied threshold. + /// + /// The upper threshold (exclusive). + public void RemoveRangeTo(T hi) + { - RaiseForRemoveRange(removed); + BinarySearch(hi, out int highind); + if (highind == 0) + { + return; } - private void RaiseForRemoveRange(T[] removed) + T[] removed = new T[highind]; + Array.Copy(array, 0, removed, 0, removed.Length); + + Array.Copy(array, highind, array, 0, size - highind); + Array.Clear(array, size - highind, highind); + size -= highind; + + RaiseForRemoveRange(removed); + } + + private void RaiseForRemoveRange(T[] removed) + { + foreach (T item in removed) { - foreach (T item in removed) - { - RaiseItemsRemoved(item, 1); - } + RaiseItemsRemoved(item, 1); + } - if (removed.Length > 0) - { - RaiseCollectionChanged(); - } + if (removed.Length > 0) + { + RaiseCollectionChanged(); } + } - #endregion + #endregion - #region ICollection Members - /// - /// The value is symbolic indicating the type of asymptotic complexity - /// in terms of the size of this collection (worst-case). - /// - /// Speed.Log - public Speed ContainsSpeed => Speed.Log; + #region ICollection Members + /// + /// The value is symbolic indicating the type of asymptotic complexity + /// in terms of the size of this collection (worst-case). + /// + /// Speed.Log + public Speed ContainsSpeed => Speed.Log; - /// - /// Remove all items from this collection, resetting internal array size. - /// - public override void Clear() + /// + /// Remove all items from this collection, resetting internal array size. + /// + public override void Clear() + { + int oldCount = size; + base.Clear(); + if (oldCount > 0) { - int oldCount = size; - base.Clear(); - if (oldCount > 0) - { - RaiseCollectionCleared(true, oldCount); - RaiseCollectionChanged(); - } + RaiseCollectionCleared(true, oldCount); + RaiseCollectionChanged(); } + } + + /// + /// Check if this collection contains (an item equivalent according to the + /// itemequalityComparer) to a particular value. + /// + /// The value to check for. + /// True if the items is in this collection. + public bool Contains(T item) + { + return BinarySearch(item, out _); + } + + + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, return in the ref argument (a + /// binary copy of) the actual value found. + /// + /// The value to look for. + /// True if the items is in this collection. + public bool Find(ref T item) + { - /// - /// Check if this collection contains (an item equivalent according to the - /// itemequalityComparer) to a particular value. - /// - /// The value to check for. - /// True if the items is in this collection. - public bool Contains(T item) + if (BinarySearch(item, out int ind)) { - return BinarySearch(item, out _); + item = array[ind]; + return true; } + return false; + } - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, return in the ref argument (a - /// binary copy of) the actual value found. - /// - /// The value to look for. - /// True if the items is in this collection. - public bool Find(ref T item) - { - if (BinarySearch(item, out int ind)) - { - item = array[ind]; - return true; - } + //This should probably just be bool Add(ref T item); !!! + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, return in the ref argument (a + /// binary copy of) the actual value found. Else, add the item to the collection. + /// + /// The value to look for. + /// True if the item was added (hence not found). + public bool FindOrAdd(ref T item) + { + UpdateCheck(); - return false; - } + if (BinarySearch(item, out int ind)) + { + item = array[ind]; + return true; + } - //This should probably just be bool Add(ref T item); !!! - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, return in the ref argument (a - /// binary copy of) the actual value found. Else, add the item to the collection. - /// - /// The value to look for. - /// True if the item was added (hence not found). - public bool FindOrAdd(ref T item) + if (size == array.Length) { - UpdateCheck(); + Expand(); + } + Array.Copy(array, ind, array, ind + 1, size - ind); + array[ind] = item; + size++; + RaiseForAdd(item); + return false; + } - if (BinarySearch(item, out int ind)) - { - item = array[ind]; - return true; - } - if (size == array.Length) - { - Expand(); - } + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// to with a binary copy of the supplied value. If the collection has bag semantics, + /// it is implementation dependent if this updates all equivalent copies in + /// the collection or just one. + /// + /// Value to update. + /// True if the item was found and hence updated. + public bool Update(T item) + { + return Update(item, out _); + } - Array.Copy(array, ind, array, ind + 1, size - ind); - array[ind] = item; - size++; - RaiseForAdd(item); - return false; - } + /// + /// + /// + /// + /// + /// + public bool Update(T item, out T olditem) + { + UpdateCheck(); - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// to with a binary copy of the supplied value. If the collection has bag semantics, - /// it is implementation dependent if this updates all equivalent copies in - /// the collection or just one. - /// - /// Value to update. - /// True if the item was found and hence updated. - public bool Update(T item) + if (BinarySearch(item, out int ind)) { - return Update(item, out _); + olditem = array[ind]; + array[ind] = item; + RaiseForUpdate(item, olditem); + return true; } - /// - /// - /// - /// - /// - /// - public bool Update(T item, out T olditem) - { - UpdateCheck(); + olditem = default; + return false; + } - if (BinarySearch(item, out int ind)) - { - olditem = array[ind]; - array[ind] = item; - RaiseForUpdate(item, olditem); - return true; - } + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// to with a binary copy of the supplied value; else add the value to the collection. + /// + /// Value to add or update. + /// True if the item was found and updated (hence not added). + public bool UpdateOrAdd(T item) + { + return UpdateOrAdd(item, out _); + } - olditem = default; - return false; - } + /// + /// + /// + /// + /// + /// + public bool UpdateOrAdd(T item, out T olditem) + { + UpdateCheck(); - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// to with a binary copy of the supplied value; else add the value to the collection. - /// - /// Value to add or update. - /// True if the item was found and updated (hence not added). - public bool UpdateOrAdd(T item) + if (BinarySearch(item, out int ind)) { - return UpdateOrAdd(item, out _); + olditem = array[ind]; + array[ind] = item; + RaiseForUpdate(item, olditem); + return true; } - /// - /// - /// - /// - /// - /// - public bool UpdateOrAdd(T item, out T olditem) + if (size == array.Length) { - UpdateCheck(); + Expand(); + } + Array.Copy(array, ind, array, ind + 1, size - ind); + array[ind] = item; + size++; + olditem = default; + RaiseForAdd(item); + return false; + } - if (BinarySearch(item, out int ind)) - { - olditem = array[ind]; - array[ind] = item; - RaiseForUpdate(item, olditem); - return true; - } - if (size == array.Length) - { - Expand(); - } + /// + /// Remove a particular item from this collection. If the collection has bag + /// semantics only one copy equivalent to the supplied item is removed. + /// + /// The value to remove. + /// True if the item was found (and removed). + public bool Remove(T item) + { - Array.Copy(array, ind, array, ind + 1, size - ind); - array[ind] = item; - size++; - olditem = default; - RaiseForAdd(item); - return false; + UpdateCheck(); + if (BinarySearch(item, out int ind)) + { + T removeditem = array[ind]; + Array.Copy(array, ind + 1, array, ind, size - ind - 1); + array[--size] = default; + RaiseForRemove(removeditem); + return true; } + return false; + } - /// - /// Remove a particular item from this collection. If the collection has bag - /// semantics only one copy equivalent to the supplied item is removed. - /// - /// The value to remove. - /// True if the item was found (and removed). - public bool Remove(T item) - { - UpdateCheck(); - if (BinarySearch(item, out int ind)) - { - T removeditem = array[ind]; - Array.Copy(array, ind + 1, array, ind, size - ind - 1); - array[--size] = default; - RaiseForRemove(removeditem); - return true; - } + /// + /// Remove a particular item from this collection if found. If the collection + /// has bag semantics only one copy equivalent to the supplied item is removed, + /// which one is implementation dependent. + /// If an item was removed, report a binary copy of the actual item removed in + /// the argument. + /// + /// The value to remove. + /// The removed value. + /// True if the item was found (and removed). + public bool Remove(T item, out T removeditem) + { - return false; + UpdateCheck(); + if (BinarySearch(item, out int ind)) + { + removeditem = array[ind]; + Array.Copy(array, ind + 1, array, ind, size - ind - 1); + array[--size] = default; + RaiseForRemove(removeditem); + return true; } + removeditem = default; + return false; + } - /// - /// Remove a particular item from this collection if found. If the collection - /// has bag semantics only one copy equivalent to the supplied item is removed, - /// which one is implementation dependent. - /// If an item was removed, report a binary copy of the actual item removed in - /// the argument. - /// - /// The value to remove. - /// The removed value. - /// True if the item was found (and removed). - public bool Remove(T item, out T removeditem) - { - UpdateCheck(); - if (BinarySearch(item, out int ind)) - { - removeditem = array[ind]; - Array.Copy(array, ind + 1, array, ind, size - ind - 1); - array[--size] = default; - RaiseForRemove(removeditem); - return true; - } + /// + /// Remove all items in another collection from this one. + /// + /// The items to remove. + public void RemoveAll(SCG.IEnumerable items) + { + //This is O(m*logn) with n bits extra storage + //(Not better to collect the m items and sort them) + UpdateCheck(); - removeditem = default; - return false; - } + RaiseForRemoveAllHandler raiseHandler = new(this); + bool mustFire = raiseHandler.MustFire; + int[] toremove = new int[(size >> 5) + 1]; + int j = 0; - /// - /// Remove all items in another collection from this one. - /// - /// The items to remove. - public void RemoveAll(SCG.IEnumerable items) + foreach (T item in items) { - //This is O(m*logn) with n bits extra storage - //(Not better to collect the m items and sort them) - UpdateCheck(); - - RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(this); - bool mustFire = raiseHandler.MustFire; - - int[] toremove = new int[(size >> 5) + 1]; - int j = 0; - - foreach (T item in items) + if (BinarySearch(item, out int ind)) { - if (BinarySearch(item, out int ind)) - { - toremove[ind >> 5] |= 1 << (ind & 31); - } + toremove[ind >> 5] |= 1 << (ind & 31); } + } - for (int i = 0; i < size; i++) + for (int i = 0; i < size; i++) + { + if ((toremove[i >> 5] & (1 << (i & 31))) == 0) { - if ((toremove[i >> 5] & (1 << (i & 31))) == 0) - { - array[j++] = array[i]; - } - else if (mustFire) - { - raiseHandler.Remove(array[i]); - } + array[j++] = array[i]; } - - Array.Clear(array, j, size - j); - size = j; - if (mustFire) + else if (mustFire) { - raiseHandler.Raise(); + raiseHandler.Remove(array[i]); } } - /// - /// Remove all items not in some other collection from this one. - /// - /// The items to retain. - public void RetainAll(SCG.IEnumerable items) + Array.Clear(array, j, size - j); + size = j; + if (mustFire) { - //This is O(m*logn) with n bits extra storage - //(Not better to collect the m items and sort them) - UpdateCheck(); + raiseHandler.Raise(); + } + } + + /// + /// Remove all items not in some other collection from this one. + /// + /// The items to retain. + public void RetainAll(SCG.IEnumerable items) + { + //This is O(m*logn) with n bits extra storage + //(Not better to collect the m items and sort them) + UpdateCheck(); - RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(this); - bool mustFire = raiseHandler.MustFire; + RaiseForRemoveAllHandler raiseHandler = new(this); + bool mustFire = raiseHandler.MustFire; - int[] toretain = new int[(size >> 5) + 1]; - int j = 0; + int[] toretain = new int[(size >> 5) + 1]; + int j = 0; - foreach (T item in items) + foreach (T item in items) + { + if (BinarySearch(item, out int ind)) { - if (BinarySearch(item, out int ind)) - { - toretain[ind >> 5] |= 1 << (ind & 31); - } + toretain[ind >> 5] |= 1 << (ind & 31); } + } - for (int i = 0; i < size; i++) + for (int i = 0; i < size; i++) + { + if ((toretain[i >> 5] & (1 << (i & 31))) != 0) { - if ((toretain[i >> 5] & (1 << (i & 31))) != 0) - { - array[j++] = array[i]; - } - else if (mustFire) - { - raiseHandler.Remove(array[i]); - } + array[j++] = array[i]; } - - Array.Clear(array, j, size - j); - size = j; - if (mustFire) + else if (mustFire) { - raiseHandler.Raise(); + raiseHandler.Remove(array[i]); } } - /// - /// Check if this collection contains all the values in another collection. - /// Multiplicities are not taken into account. - /// - /// The - /// True if all values in itemsis in this collection. - public bool ContainsAll(SCG.IEnumerable items) + Array.Clear(array, j, size - j); + size = j; + if (mustFire) { + raiseHandler.Raise(); + } + } + + /// + /// Check if this collection contains all the values in another collection. + /// Multiplicities are not taken into account. + /// + /// The + /// True if all values in itemsis in this collection. + public bool ContainsAll(SCG.IEnumerable items) + { - foreach (T item in items) + foreach (T item in items) + { + if (!BinarySearch(item, out _)) { - if (!BinarySearch(item, out _)) - { - return false; - } + return false; } - - return true; } + return true; + } - /// - /// Count the number of items of the collection equal to a particular value. - /// Returns 0 if and only if the value is not in the collection. - /// - /// The value to count. - /// The number of copies found (0 or 1). - public int ContainsCount(T item) - { - return BinarySearch(item, out _) ? 1 : 0; - } - /// - /// - /// - /// - public virtual ICollectionValue UniqueItems() { return this; } - - /// - /// - /// - /// - public virtual ICollectionValue> ItemMultiplicities() - { - return new MultiplicityOne(this); - } + /// + /// Count the number of items of the collection equal to a particular value. + /// Returns 0 if and only if the value is not in the collection. + /// + /// The value to count. + /// The number of copies found (0 or 1). + public int ContainsCount(T item) + { + return BinarySearch(item, out _) ? 1 : 0; + } + + /// + /// + /// + /// + public virtual ICollectionValue UniqueItems() { return this; } + + /// + /// + /// + /// + public virtual ICollectionValue> ItemMultiplicities() + { + return new MultiplicityOne(this); + } + + /// + /// Remove all (0 or 1) items equivalent to a given value. + /// + /// The value to remove. + public void RemoveAllCopies(T item) { Remove(item); } - /// - /// Remove all (0 or 1) items equivalent to a given value. - /// - /// The value to remove. - public void RemoveAllCopies(T item) { Remove(item); } + /// + /// Check the integrity of the internal data structures of this collection. + /// Only available in DEBUG builds??? + /// + /// True if check does not fail. + public override bool Check() + { + bool retval = true; - /// - /// Check the integrity of the internal data structures of this collection. - /// Only available in DEBUG builds??? - /// - /// True if check does not fail. - public override bool Check() + if (size > array.Length) { - bool retval = true; + Logger.Log(string.Format("Bad size ({0}) > array.Length ({1})", size, array.Length)); + return false; + } - if (size > array.Length) + for (int i = 0; i < size; i++) + { + if (array[i] == null) { - Logger.Log(string.Format("Bad size ({0}) > array.Length ({1})", size, array.Length)); + Logger.Log(string.Format("Bad element: null at index {0}", i)); return false; } - for (int i = 0; i < size; i++) + if (i > 0 && _comparer.Compare(array[i], array[i - 1]) <= 0) { - if (array[i] == null) - { - Logger.Log(string.Format("Bad element: null at index {0}", i)); - return false; - } - - if (i > 0 && _comparer.Compare(array[i], array[i - 1]) <= 0) - { - Logger.Log(string.Format("Inversion at index {0}", i)); - retval = false; - } + Logger.Log(string.Format("Inversion at index {0}", i)); + retval = false; } - - return retval; } - #endregion - - #region IExtensible Members - - /// - /// - /// - /// False since this collection has set semantics - public bool AllowsDuplicates => false; - - /// - /// By convention this is true for any collection with set semantics. - /// - /// True if only one representative of a group of equal items - /// is kept in the collection together with the total count. - public virtual bool DuplicatesByCounting => true; - - /// - /// Add an item to this collection if possible. If this collection has set - /// semantics, the item will be added if not already in the collection. If - /// bag semantics, the item will always be added. - /// - /// The item to add. - /// True if item was added. - public bool Add(T item) - { - UpdateCheck(); + return retval; + } + #endregion - if (BinarySearch(item, out int ind)) - { - return false; - } + #region IExtensible Members - InsertProtected(ind, item); - RaiseForAdd(item); - return true; - } + /// + /// + /// + /// False since this collection has set semantics + public bool AllowsDuplicates => false; - /// - /// Add an item to this collection if possible. - /// - /// The item to add. - void SCG.ICollection.Add(T item) - { - Add(item); - } + /// + /// By convention this is true for any collection with set semantics. + /// + /// True if only one representative of a group of equal items + /// is kept in the collection together with the total count. + public virtual bool DuplicatesByCounting => true; + + /// + /// Add an item to this collection if possible. If this collection has set + /// semantics, the item will be added if not already in the collection. If + /// bag semantics, the item will always be added. + /// + /// The item to add. + /// True if item was added. + public bool Add(T item) + { + UpdateCheck(); - /// - /// Add the elements from another collection with a more specialized item type - /// to this collection. Since this - /// collection has set semantics, only items not already in the collection - /// will be added. - /// - /// The items to add - public void AddAll(SCG.IEnumerable items) + if (BinarySearch(item, out int ind)) { - int toadd = CountItems(items), newsize = array.Length; - - while (newsize < size + toadd) { newsize *= 2; } + return false; + } - T[] newarr = new T[newsize]; + InsertProtected(ind, item); + RaiseForAdd(item); + return true; + } - toadd = 0; - foreach (T item in items) - { - newarr[size + toadd++] = item; - } + /// + /// Add an item to this collection if possible. + /// + /// The item to add. + void SCG.ICollection.Add(T item) + { + Add(item); + } - Sorting.IntroSort(newarr, size, toadd, _comparer); - int j = 0, i = 0, numAdded = 0; - T lastitem = default; - T[] addedItems = new T[toadd]; + /// + /// Add the elements from another collection with a more specialized item type + /// to this collection. Since this + /// collection has set semantics, only items not already in the collection + /// will be added. + /// + /// The items to add + public void AddAll(SCG.IEnumerable items) + { + int toadd = CountItems(items), newsize = array.Length; - //The following eliminates duplicates (including duplicates in input) - //while merging the old and new collection - for (int k = size, klimit = size + toadd; k < klimit; k++) - { - while (i < size && _comparer.Compare(array[i], newarr[k]) <= 0) - { - lastitem = newarr[j++] = array[i++]; - } + while (newsize < size + toadd) { newsize *= 2; } - if (j == 0 || _comparer.Compare(lastitem, newarr[k]) < 0) - { - addedItems[numAdded++] = lastitem = newarr[j++] = newarr[k]; - } - } + T[] newarr = new T[newsize]; - while (i < size) - { - newarr[j++] = array[i++]; - } + toadd = 0; + foreach (T item in items) + { + newarr[size + toadd++] = item; + } - Array.Clear(newarr, j, size + toadd - j); - size = j; - array = newarr; + Sorting.IntroSort(newarr, size, toadd, _comparer); - RaiseForAddAll(addedItems, numAdded); - } + int j = 0, i = 0, numAdded = 0; + T lastitem = default; + T[] addedItems = new T[toadd]; - private void RaiseForAddAll(T[] addedItems, int numAdded) + //The following eliminates duplicates (including duplicates in input) + //while merging the old and new collection + for (int k = size, klimit = size + toadd; k < klimit; k++) { - if ((ActiveEvents & EventType.Added) != 0) + while (i < size && _comparer.Compare(array[i], newarr[k]) <= 0) { - for (int i = 0; i < numAdded; i += 1) - { - RaiseItemsAdded(addedItems[i], 1); - } + lastitem = newarr[j++] = array[i++]; } - if (numAdded > 0) + if (j == 0 || _comparer.Compare(lastitem, newarr[k]) < 0) { - RaiseCollectionChanged(); + addedItems[numAdded++] = lastitem = newarr[j++] = newarr[k]; } } - #endregion + while (i < size) + { + newarr[j++] = array[i++]; + } - #region IPriorityQueue Members + Array.Clear(newarr, j, size + toadd - j); + size = j; + array = newarr; + + RaiseForAddAll(addedItems, numAdded); + } - /// - /// Find the current least item of this priority queue. - /// - /// The least item. - public T FindMin() + private void RaiseForAddAll(T[] addedItems, int numAdded) + { + if ((ActiveEvents & EventType.Added) != 0) { - if (size == 0) + for (int i = 0; i < numAdded; i += 1) { - throw new NoSuchItemException(); + RaiseItemsAdded(addedItems[i], 1); } - - return array[0]; } - /// - /// Remove the least item from this priority queue. - /// - /// The removed item. - public T DeleteMin() + if (numAdded > 0) { - UpdateCheck(); - if (size == 0) - { - throw new NoSuchItemException(); - } + RaiseCollectionChanged(); + } + } - T retval = array[0]; + #endregion - size--; - Array.Copy(array, 1, array, 0, size); - array[size] = default; - RaiseForRemove(retval); - return retval; + #region IPriorityQueue Members + + /// + /// Find the current least item of this priority queue. + /// + /// The least item. + public T FindMin() + { + if (size == 0) + { + throw new NoSuchItemException(); } + return array[0]; + } - /// - /// Find the current largest item of this priority queue. - /// - /// The largest item. - public T FindMax() + /// + /// Remove the least item from this priority queue. + /// + /// The removed item. + public T DeleteMin() + { + UpdateCheck(); + if (size == 0) { - if (size == 0) - { - throw new NoSuchItemException(); - } - - return array[size - 1]; + throw new NoSuchItemException(); } + T retval = array[0]; + + size--; + Array.Copy(array, 1, array, 0, size); + array[size] = default; + RaiseForRemove(retval); + return retval; + } + - /// - /// Remove the largest item from this priority queue. - /// - /// The removed item. - public T DeleteMax() + /// + /// Find the current largest item of this priority queue. + /// + /// The largest item. + public T FindMax() + { + if (size == 0) { - UpdateCheck(); - if (size == 0) - { - throw new NoSuchItemException(); - } + throw new NoSuchItemException(); + } + + return array[size - 1]; + } - T retval = array[size - 1]; - size--; - array[size] = default; - RaiseForRemove(retval); - return retval; + /// + /// Remove the largest item from this priority queue. + /// + /// The removed item. + public T DeleteMax() + { + UpdateCheck(); + if (size == 0) + { + throw new NoSuchItemException(); } - /// - /// The comparer object supplied at creation time for this collection - /// - /// The comparer - public SCG.IComparer Comparer => _comparer; + T retval = array[size - 1]; - #endregion + size--; + array[size] = default; + RaiseForRemove(retval); + return retval; + } - #region IIndexed Members + /// + /// The comparer object supplied at creation time for this collection + /// + /// The comparer + public SCG.IComparer Comparer => _comparer; - /// - /// if i is negative or - /// >= the size of the collection. - /// - /// The i'th item of this list. - /// the index to lookup - public T this[int i] - { - get - { - if (i < 0 || i >= size) - { - throw new IndexOutOfRangeException(); - } + #endregion - return array[i]; - } - } + #region IIndexed Members - /// - /// - /// - /// - public virtual Speed IndexingSpeed => Speed.Constant; - - /// - /// Searches for an item in the list going forwards from the start. - /// - /// Item to search for. - /// Index of item from start. - public int IndexOf(T item) { return IndexOfInner(item); } - - - /// - /// Searches for an item in the list going backwards from the end. - /// - /// Item to search for. - /// Index of item from the end. - public int LastIndexOf(T item) { return IndexOfInner(item); } - - - /// - /// Remove the item at a specific position of the list. - /// if i is negative or - /// >= the size of the collection. - /// - /// The index of the item to remove. - /// The removed item. - public T RemoveAt(int i) + /// + /// if i is negative or + /// >= the size of the collection. + /// + /// The i'th item of this list. + /// the index to lookup + public T this[int i] + { + get { if (i < 0 || i >= size) { - throw new IndexOutOfRangeException("Index out of range for sequenced collectionvalue"); + throw new IndexOutOfRangeException(); } - UpdateCheck(); + return array[i]; + } + } - T retval = array[i]; + /// + /// + /// + /// + public virtual Speed IndexingSpeed => Speed.Constant; - size--; - Array.Copy(array, i + 1, array, i, size - i); - array[size] = default; - RaiseForRemoveAt(i, retval); - return retval; - } + /// + /// Searches for an item in the list going forwards from the start. + /// + /// Item to search for. + /// Index of item from start. + public int IndexOf(T item) { return IndexOfInner(item); } - /// - /// Remove all items in an index interval. - /// ???. - /// - /// The index of the first item to remove. - /// The number of items to remove. - public void RemoveInterval(int start, int count) + + /// + /// Searches for an item in the list going backwards from the end. + /// + /// Item to search for. + /// Index of item from the end. + public int LastIndexOf(T item) { return IndexOfInner(item); } + + + /// + /// Remove the item at a specific position of the list. + /// if i is negative or + /// >= the size of the collection. + /// + /// The index of the item to remove. + /// The removed item. + public T RemoveAt(int i) + { + if (i < 0 || i >= size) { - UpdateCheck(); - CheckRange(start, count); - Array.Copy(array, start + count, array, start, size - start - count); - size -= count; - Array.Clear(array, size, count); - RaiseForRemoveInterval(count); + throw new IndexOutOfRangeException("Index out of range for sequenced collectionvalue"); } - private void RaiseForRemoveInterval(int count) + UpdateCheck(); + + T retval = array[i]; + + size--; + Array.Copy(array, i + 1, array, i, size - i); + array[size] = default; + RaiseForRemoveAt(i, retval); + return retval; + } + + /// + /// Remove all items in an index interval. + /// ???. + /// + /// The index of the first item to remove. + /// The number of items to remove. + public void RemoveInterval(int start, int count) + { + UpdateCheck(); + CheckRange(start, count); + Array.Copy(array, start + count, array, start, size - start - count); + size -= count; + Array.Clear(array, size, count); + RaiseForRemoveInterval(count); + } + + private void RaiseForRemoveInterval(int count) + { + if (ActiveEvents != 0 && count > 0) { - if (ActiveEvents != 0 && count > 0) - { - RaiseCollectionCleared(size == 0, count); - RaiseCollectionChanged(); - } + RaiseCollectionCleared(size == 0, count); + RaiseCollectionChanged(); } + } - #endregion + #endregion - #region IDirectedEnumerable Members + #region IDirectedEnumerable Members - /// - /// Create a collection containing the same items as this collection, but - /// whose enumerator will enumerate the items backwards. The new collection - /// will become invalid if the original is modified. Method typically used as in - /// foreach (T x in coll.Backwards()) {...} - /// - /// The backwards collection. - IDirectedEnumerable IDirectedEnumerable.Backwards() - { return Backwards(); } + /// + /// Create a collection containing the same items as this collection, but + /// whose enumerator will enumerate the items backwards. The new collection + /// will become invalid if the original is modified. Method typically used as in + /// foreach (T x in coll.Backwards()) {...} + /// + /// The backwards collection. + IDirectedEnumerable IDirectedEnumerable.Backwards() + { return Backwards(); } - #endregion - } + #endregion } \ No newline at end of file diff --git a/C5/BaseClasses/ArrayBase.cs b/C5/BaseClasses/ArrayBase.cs index 6b0a0fe3..d5590e51 100644 --- a/C5/BaseClasses/ArrayBase.cs +++ b/C5/BaseClasses/ArrayBase.cs @@ -1,330 +1,332 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// Base class for collection classes of dynamic array type implementations. +/// +public abstract class ArrayBase : SequencedBase { + #region Fields + /// + /// The actual internal array container. Will be extended on demand. + /// + protected T[] array; + /// - /// Base class for collection classes of dynamic array type implementations. + /// The offset into the internal array container of the first item. The offset is 0 for a + /// base dynamic array and may be positive for an updatable view into a base dynamic array. /// - public abstract class ArrayBase : SequencedBase + protected int offsetField; + #endregion + + #region Util + /// + /// Double the size of the internal array. + /// + protected virtual void Expand() { - #region Fields - /// - /// The actual internal array container. Will be extended on demand. - /// - protected T[] array; + Expand(checked(2 * array.Length), size); + } - /// - /// The offset into the internal array container of the first item. The offset is 0 for a - /// base dynamic array and may be positive for an updatable view into a base dynamic array. - /// - protected int offsetField; - #endregion - #region Util - /// - /// Double the size of the internal array. - /// - protected virtual void Expand() + /// + /// Expand the internal array container. + /// + /// The new size of the internal array - + /// will be rounded upwards to a power of 2. + /// The (new) size of the (base) collection. + protected virtual void Expand(int newcapacity, int newsize) + { + System.Diagnostics.Debug.Assert(newcapacity >= newsize); + + int newlength = array.Length; + + while (newlength < newcapacity) { - Expand(checked(2 * array.Length), size); + newlength = checked(newlength * 2); } + T[] newarray = new T[newlength]; - /// - /// Expand the internal array container. - /// - /// The new size of the internal array - - /// will be rounded upwards to a power of 2. - /// The (new) size of the (base) collection. - protected virtual void Expand(int newcapacity, int newsize) + Array.Copy(array, newarray, newsize); + array = newarray; + } + + + /// + /// Insert an item at a specific index, moving items to the right + /// upwards and expanding the array if necessary. + /// + /// The index at which to insert. + /// The item to insert. + protected virtual void InsertProtected(int i, T item) + { + if (size == array.Length) { - System.Diagnostics.Debug.Assert(newcapacity >= newsize); + Expand(); + } - int newlength = array.Length; + if (i < size) + { + Array.Copy(array, i, array, i + 1, size - i); + } - while (newlength < newcapacity) - { - newlength = checked(newlength * 2); - } + array[i] = item; + size++; + } - T[] newarray = new T[newlength]; + #endregion - Array.Copy(array, newarray, newsize); - array = newarray; + #region Constructors + + /// + /// Create an empty ArrayBase object. + /// + /// The initial capacity of the internal array container. + /// Will be rounded upwards to the nearest power of 2 greater than or equal to 8. + /// The item equalityComparer to use, primarily for item equality + protected ArrayBase(int capacity, System.Collections.Generic.IEqualityComparer itemequalityComparer) + : base(itemequalityComparer) + { + int newlength = 8; + while (newlength < capacity) + { + newlength *= 2; } + array = new T[newlength]; + } - /// - /// Insert an item at a specific index, moving items to the right - /// upwards and expanding the array if necessary. - /// - /// The index at which to insert. - /// The item to insert. - protected virtual void InsertProtected(int i, T item) - { - if (size == array.Length) - { - Expand(); - } + #endregion - if (i < size) - { - Array.Copy(array, i, array, i + 1, size - i); - } + #region IIndexed members - array[i] = item; - size++; + /// + /// + /// If the arguments does not describe a + /// valid range in the indexed collection, cf. . + /// The directed collection of items in a specific index interval. + /// The low index of the interval (inclusive). + /// The size of the range. + public virtual IDirectedCollectionValue this[int start, int count] + { + get + { + CheckRange(start, count); + return new Range(this, start, count, true); } + } - #endregion + #endregion - #region Constructors + #region IEditableCollection members + /// + /// Remove all items and reset size of internal array container. + /// + public virtual void Clear() + { + UpdateCheck(); + array = new T[8]; + size = 0; + } - /// - /// Create an empty ArrayBase object. - /// - /// The initial capacity of the internal array container. - /// Will be rounded upwards to the nearest power of 2 greater than or equal to 8. - /// The item equalityComparer to use, primarily for item equality - protected ArrayBase(int capacity, System.Collections.Generic.IEqualityComparer itemequalityComparer) - : base(itemequalityComparer) - { - int newlength = 8; - while (newlength < capacity) - { - newlength *= 2; - } - array = new T[newlength]; - } + /// + /// Create an array containing (copies) of the items of this collection in enumeration order. + /// + /// The new array + public override T[] ToArray() + { + T[] res = new T[size]; - #endregion + Array.Copy(array, offsetField, res, 0, size); + return res; + } - #region IIndexed members - /// - /// - /// If the arguments does not describe a - /// valid range in the indexed collection, cf. . - /// The directed collection of items in a specific index interval. - /// The low index of the interval (inclusive). - /// The size of the range. - public virtual IDirectedCollectionValue this[int start, int count] + /// + /// Perform an internal consistency (invariant) test on the array base. + /// + /// True if test succeeds. + public virtual bool Check() + { + bool retval = true; + + if (size > array.Length) { - get + Logger.Log(string.Format("Bad size ({0}) > array.Length ({1})", size, array.Length)); + return false; + } + + for (int i = 0; i < size; i++) + { + if (array[i] == null) { - CheckRange(start, count); - return new Range(this, start, count, true); + Logger.Log(string.Format("Bad element: null at index {0}", i)); + return false; } } - #endregion + return retval; + } - #region IEditableCollection members - /// - /// Remove all items and reset size of internal array container. - /// - public virtual void Clear() - { - UpdateCheck(); - array = new T[8]; - size = 0; - } + #endregion + #region IDirectedCollection Members - /// - /// Create an array containing (copies) of the items of this collection in enumeration order. - /// - /// The new array - public override T[] ToArray() - { - T[] res = new T[size]; + /// + /// Create a directed collection with the same contents as this one, but + /// opposite enumeration sequence. + /// + /// The mirrored collection. + public override IDirectedCollectionValue Backwards() { return this[0, size].Backwards(); } - Array.Copy(array, offsetField, res, 0, size); - return res; - } + #endregion + /// + /// Choose some item of this collection. The result is the last item in the internal array, + /// making it efficient to remove. + /// + /// if collection is empty. + /// + public override T Choose() { if (size > 0) { return array[size - 1]; } throw new NoSuchItemException(); } - /// - /// Perform an internal consistency (invariant) test on the array base. - /// - /// True if test succeeds. - public virtual bool Check() + #region IEnumerable Members + /// + /// Create an enumerator for this array based collection. + /// + /// The enumerator + public override System.Collections.Generic.IEnumerator GetEnumerator() + { + int thestamp = stamp, theend = size + offsetField, thestart = offsetField; + + for (int i = thestart; i < theend; i++) { - bool retval = true; + ModifyCheck(thestamp); + yield return array[i]; + } + } + #endregion - if (size > array.Length) - { - Logger.Log(string.Format("Bad size ({0}) > array.Length ({1})", size, array.Length)); - return false; - } + #region Range nested class + /// + /// A helper class for defining results of interval queries on array based collections. + /// + protected class Range : DirectedCollectionValueBase, IDirectedCollectionValue + { + private int start; + private readonly int count; + private int delta; + private readonly int stamp; + private readonly ArrayBase thebase; - for (int i = 0; i < size; i++) - { - if (array[i] == null) - { - Logger.Log(string.Format("Bad element: null at index {0}", i)); - return false; - } - } - return retval; + internal Range(ArrayBase thebase, int start, int count, bool forwards) + { + this.thebase = thebase; stamp = thebase.stamp; + delta = forwards ? 1 : -1; + this.start = start + thebase.offsetField; this.count = count; } - #endregion + /// + /// + /// + /// if underlying collection has been modified. + /// True if this collection is empty. + public override bool IsEmpty { get { thebase.ModifyCheck(stamp); return count == 0; } } - #region IDirectedCollection Members /// - /// Create a directed collection with the same contents as this one, but - /// opposite enumeration sequence. + /// /// - /// The mirrored collection. - public override IDirectedCollectionValue Backwards() { return this[0, size].Backwards(); } - - #endregion + /// if underlying collection has been modified. + /// The number of items in the range + public override int Count { get { thebase.ModifyCheck(stamp); return count; } } /// - /// Choose some item of this collection. The result is the last item in the internal array, - /// making it efficient to remove. + /// The value is symbolic indicating the type of asymptotic complexity + /// in terms of the size of this collection (worst-case or amortized as + /// relevant). /// - /// if collection is empty. - /// - public override T Choose() { if (size > 0) { return array[size - 1]; } throw new NoSuchItemException(); } + /// A characterization of the speed of the + /// if underlying collection has been modified. + /// Count property in this collection. + public override Speed CountSpeed { get { thebase.ModifyCheck(stamp); return Speed.Constant; } } - #region IEnumerable Members /// - /// Create an enumerator for this array based collection. + /// Choose some item of this collection. /// - /// The enumerator - public override System.Collections.Generic.IEnumerator GetEnumerator() + /// if underlying collection has been modified. + /// if range is empty. + /// + public override T Choose() { - int thestamp = stamp, theend = size + offsetField, thestart = offsetField; - - for (int i = thestart; i < theend; i++) + thebase.ModifyCheck(stamp); + if (count == 0) { - ModifyCheck(thestamp); - yield return array[i]; + throw new NoSuchItemException(); } + + return thebase.array[start]; } - #endregion - #region Range nested class + /// - /// A helper class for defining results of interval queries on array based collections. + /// Create an enumerator for this range of an array based collection. /// - protected class Range : DirectedCollectionValueBase, IDirectedCollectionValue + /// if underlying collection has been modified. + /// The enumerator + public override System.Collections.Generic.IEnumerator GetEnumerator() { - private int start; - private readonly int count; - private int delta; - private readonly int stamp; - private readonly ArrayBase thebase; - - - internal Range(ArrayBase thebase, int start, int count, bool forwards) - { - this.thebase = thebase; stamp = thebase.stamp; - delta = forwards ? 1 : -1; - this.start = start + thebase.offsetField; this.count = count; - } - - /// - /// - /// - /// if underlying collection has been modified. - /// True if this collection is empty. - public override bool IsEmpty { get { thebase.ModifyCheck(stamp); return count == 0; } } - - - /// - /// - /// - /// if underlying collection has been modified. - /// The number of items in the range - public override int Count { get { thebase.ModifyCheck(stamp); return count; } } - - /// - /// The value is symbolic indicating the type of asymptotic complexity - /// in terms of the size of this collection (worst-case or amortized as - /// relevant). - /// - /// A characterization of the speed of the - /// if underlying collection has been modified. - /// Count property in this collection. - public override Speed CountSpeed { get { thebase.ModifyCheck(stamp); return Speed.Constant; } } - - /// - /// Choose some item of this collection. - /// - /// if underlying collection has been modified. - /// if range is empty. - /// - public override T Choose() + for (int i = 0; i < count; i++) { thebase.ModifyCheck(stamp); - if (count == 0) - { - throw new NoSuchItemException(); - } - - return thebase.array[start]; - } - - - /// - /// Create an enumerator for this range of an array based collection. - /// - /// if underlying collection has been modified. - /// The enumerator - public override System.Collections.Generic.IEnumerator GetEnumerator() - { - for (int i = 0; i < count; i++) - { - thebase.ModifyCheck(stamp); - yield return thebase.array[start + delta * i]; - } + yield return thebase.array[start + delta * i]; } + } - /// - /// Create an array collection range with the same contents as this one, but - /// opposite enumeration sequence. - /// - /// if underlying collection has been modified. - /// The mirrored collection. - public override IDirectedCollectionValue Backwards() - { - thebase.ModifyCheck(stamp); + /// + /// Create an array collection range with the same contents as this one, but + /// opposite enumeration sequence. + /// + /// if underlying collection has been modified. + /// The mirrored collection. + public override IDirectedCollectionValue Backwards() + { + thebase.ModifyCheck(stamp); - Range res = (Range)MemberwiseClone(); + Range res = (Range)MemberwiseClone(); - res.delta = -delta; - res.start = start + (count - 1) * delta; - return res; - } + res.delta = -delta; + res.start = start + (count - 1) * delta; + return res; + } - IDirectedEnumerable C5.IDirectedEnumerable.Backwards() - { - return Backwards(); - } + IDirectedEnumerable C5.IDirectedEnumerable.Backwards() + { + return Backwards(); + } - /// - /// Forwards if same, else Backwards - /// - /// if underlying collection has been modified. - /// The enumeration direction relative to the original collection. - public override Direction Direction + /// + /// Forwards if same, else Backwards + /// + /// if underlying collection has been modified. + /// The enumeration direction relative to the original collection. + public override Direction Direction + { + get { - get - { - thebase.ModifyCheck(stamp); - return delta > 0 ? Direction.Forwards : Direction.Backwards; - } + thebase.ModifyCheck(stamp); + return delta > 0 ? Direction.Forwards : Direction.Backwards; } } - #endregion } + #endregion } \ No newline at end of file diff --git a/C5/BaseClasses/CollectionBase.cs b/C5/BaseClasses/CollectionBase.cs index c539457c..badc8a78 100644 --- a/C5/BaseClasses/CollectionBase.cs +++ b/C5/BaseClasses/CollectionBase.cs @@ -1,336 +1,338 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// Base class (abstract) for ICollection implementations. +/// +public abstract class CollectionBase : CollectionValueBase { + #region Fields + + /// + /// The underlying field of the ReadOnly property + /// + protected bool isReadOnlyBase = false; + + /// + /// The current stamp value + /// + protected int stamp; + /// - /// Base class (abstract) for ICollection implementations. + /// The number of items in the collection /// - public abstract class CollectionBase : CollectionValueBase + protected int size; + + /// + /// The item equalityComparer of the collection + /// + protected readonly System.Collections.Generic.IEqualityComparer itemEqualityComparer; + private int iUnSequencedHashCode, iUnSequencedHashCodeStamp = -1; + + #endregion + + /// + /// + /// + /// + protected CollectionBase(System.Collections.Generic.IEqualityComparer itemequalityComparer) { - #region Fields - - /// - /// The underlying field of the ReadOnly property - /// - protected bool isReadOnlyBase = false; - - /// - /// The current stamp value - /// - protected int stamp; - - /// - /// The number of items in the collection - /// - protected int size; - - /// - /// The item equalityComparer of the collection - /// - protected readonly System.Collections.Generic.IEqualityComparer itemequalityComparer; - private int iUnSequencedHashCode, iUnSequencedHashCodeStamp = -1; - - #endregion - - /// - /// - /// - /// - protected CollectionBase(System.Collections.Generic.IEqualityComparer itemequalityComparer) - { - this.itemequalityComparer = itemequalityComparer ?? throw new NullReferenceException("Item EqualityComparer cannot be null."); - } + this.itemEqualityComparer = itemequalityComparer ?? throw new NullReferenceException("Item EqualityComparer cannot be null."); + } - #region Util + #region Util - /// - /// Utility method for range checking. - /// - /// if the start or count is negative or - /// if the range does not fit within collection size. - /// start of range - /// size of range - protected void CheckRange(int start, int count) + /// + /// Utility method for range checking. + /// + /// if the start or count is negative or + /// if the range does not fit within collection size. + /// start of range + /// size of range + protected void CheckRange(int start, int count) + { + if (start < 0 || count < 0 || start + count > size) { - if (start < 0 || count < 0 || start + count > size) - { - throw new ArgumentOutOfRangeException(); - } + throw new ArgumentOutOfRangeException(); } + } - /// - /// Compute the unsequenced hash code of a collection - /// - /// The collection to compute hash code for - /// The item equalitySCG.Comparer - /// The hash code - public static int ComputeHashCode(ICollectionValue items, System.Collections.Generic.IEqualityComparer itemequalityComparer) - { - int h = 0; - - //But still heuristic: - //Note: the three odd factors should really be random, - //but there will be a problem with serialization/deserialization! - //Two products is too few - foreach (T item in items) - { - uint h1 = (uint)itemequalityComparer.GetHashCode(item); + /// + /// Compute the unsequenced hash code of a collection + /// + /// The collection to compute hash code for + /// The item equalitySCG.Comparer + /// The hash code + public static int ComputeHashCode(ICollectionValue items, System.Collections.Generic.IEqualityComparer itemequalityComparer) + { + int h = 0; - h += (int)((h1 * 1529784657 + 1) ^ (h1 * 2912831877) ^ (h1 * 1118771817 + 2)); - } + //But still heuristic: + //Note: the three odd factors should really be random, + //but there will be a problem with serialization/deserialization! + //Two products is too few + foreach (T item in items) + { + uint h1 = (uint)itemequalityComparer.GetHashCode(item); - return h; - /* - The pairs (-1657792980, -1570288808) and (1862883298, -272461342) gives the same - unsequenced hashcode with this hashfunction. The pair was found with code like + h += (int)((h1 * 1529784657 + 1) ^ (h1 * 2912831877) ^ (h1 * 1118771817 + 2)); + } - HashDictionary set = new HashDictionary(); - Random rnd = new C5Random(12345); - while (true) + return h; + /* + The pairs (-1657792980, -1570288808) and (1862883298, -272461342) gives the same + unsequenced hashcode with this hashfunction. The pair was found with code like + + HashDictionary set = new HashDictionary(); + Random rnd = new C5Random(12345); + while (true) + { + int[] a = new int[2]; + a[0] = rnd.Next(); a[1] = rnd.Next(); + int h = unsequencedhashcode(a); + int[] b = a; + if (set.FindOrAdd(h, ref b)) { - int[] a = new int[2]; - a[0] = rnd.Next(); a[1] = rnd.Next(); - int h = unsequencedhashcode(a); - int[] b = a; - if (set.FindOrAdd(h, ref b)) - { - Logger.Log(string.Format("Code {5}, Pair ({1},{2}) number {0} matched other pair ({3},{4})", set.Count, a[0], a[1], b[0], b[1], h)); - } + Logger.Log(string.Format("Code {5}, Pair ({1},{2}) number {0} matched other pair ({3},{4})", set.Count, a[0], a[1], b[0], b[1], h)); } - */ + } + */ - } + } + + // static Type isortedtype = typeof(ISorted); - // static Type isortedtype = typeof(ISorted); - - /// - /// Examine if collection1 and collection2 are equal as unsequenced collections - /// using the specified item equalityComparer (assumed compatible with the two collections). - /// - /// The first collection - /// The second collection - /// The item equalityComparer to use for comparison - /// True if equal - public static bool StaticEquals(ICollection collection1, ICollection collection2, System.Collections.Generic.IEqualityComparer itemequalityComparer) + /// + /// Examine if collection1 and collection2 are equal as unsequenced collections + /// using the specified item equalityComparer (assumed compatible with the two collections). + /// + /// The first collection + /// The second collection + /// The item equalityComparer to use for comparison + /// True if equal + public static bool StaticEquals(ICollection collection1, ICollection collection2, System.Collections.Generic.IEqualityComparer itemequalityComparer) + { + if (ReferenceEquals(collection1, collection2)) { - if (object.ReferenceEquals(collection1, collection2)) - { - return true; - } + return true; + } - // bug20070227: - if (collection1 == null || collection2 == null) - { - return false; - } + // bug20070227: + if (collection1 == null || collection2 == null) + { + return false; + } - if (collection1.Count != collection2.Count) - { - return false; - } + if (collection1.Count != collection2.Count) + { + return false; + } - //This way we might run through both enumerations twice, but - //probably not (if the hash codes are good) - //TODO: check equal equalityComparers, at least here! - if (collection1.GetUnsequencedHashCode() != collection2.GetUnsequencedHashCode()) - { - return false; - } + //This way we might run through both enumerations twice, but + //probably not (if the hash codes are good) + //TODO: check equal equalityComparers, at least here! + if (collection1.GetUnsequencedHashCode() != collection2.GetUnsequencedHashCode()) + { + return false; + } - //TODO: move this to the sorted implementation classes? - //Really depends on speed of InstanceOfType: we could save a cast + //TODO: move this to the sorted implementation classes? + //Really depends on speed of InstanceOfType: we could save a cast + { + if (collection1 is ISorted stit && collection2 is ISorted stat && stit.Comparer == stat.Comparer) { - if (collection1 is ISorted stit && collection2 is ISorted stat && stit.Comparer == stat.Comparer) + using System.Collections.Generic.IEnumerator dat = collection2.GetEnumerator(), dit = collection1.GetEnumerator(); + while (dit.MoveNext()) { - using System.Collections.Generic.IEnumerator dat = collection2.GetEnumerator(), dit = collection1.GetEnumerator(); - while (dit.MoveNext()) + dat.MoveNext(); + if (!itemequalityComparer.Equals(dit.Current, dat.Current)) { - dat.MoveNext(); - if (!itemequalityComparer.Equals(dit.Current, dat.Current)) - { - return false; - } + return false; } - return true; } + return true; } + } - if (!collection1.AllowsDuplicates && (collection2.AllowsDuplicates || collection2.ContainsSpeed >= collection1.ContainsSpeed)) + if (!collection1.AllowsDuplicates && (collection2.AllowsDuplicates || collection2.ContainsSpeed >= collection1.ContainsSpeed)) + { + foreach (T x in collection1) { - foreach (T x in collection1) + if (!collection2.Contains(x)) { - if (!collection2.Contains(x)) - { - return false; - } + return false; } } - else if (!collection2.AllowsDuplicates) + } + else if (!collection2.AllowsDuplicates) + { + foreach (T x in collection2) { - foreach (T x in collection2) + if (!collection1.Contains(x)) { - if (!collection1.Contains(x)) - { - return false; - } + return false; } } - // Now tit.AllowsDuplicates && tat.AllowsDuplicates - else if (collection1.DuplicatesByCounting && collection2.DuplicatesByCounting) + } + // Now tit.AllowsDuplicates && tat.AllowsDuplicates + else if (collection1.DuplicatesByCounting && collection2.DuplicatesByCounting) + { + foreach (T item in collection2) { - foreach (T item in collection2) + if (collection1.ContainsCount(item) != collection2.ContainsCount(item)) { - if (collection1.ContainsCount(item) != collection2.ContainsCount(item)) - { - return false; - } + return false; } } - else + } + else + { + // To avoid an O(n^2) algorithm, we make an aux hashtable to hold the count of items + // bug20101103: HashDictionary dict = new HashDictionary(); + HashDictionary dict = new(itemequalityComparer); + foreach (T item in collection2) { - // To avoid an O(n^2) algorithm, we make an aux hashtable to hold the count of items - // bug20101103: HashDictionary dict = new HashDictionary(); - HashDictionary dict = new HashDictionary(itemequalityComparer); - foreach (T item in collection2) + int count = 1; + if (dict.FindOrAdd(item, ref count)) { - int count = 1; - if (dict.FindOrAdd(item, ref count)) - { - dict[item] = count + 1; - } + dict[item] = count + 1; } - foreach (T item in collection1) + } + foreach (T item in collection1) + { + var i = item; + if (dict.Find(ref i, out int count) && count > 0) { - var i = item; - if (dict.Find(ref i, out int count) && count > 0) - { - dict[item] = count - 1; - } - else - { - return false; - } + dict[item] = count - 1; + } + else + { + return false; } - return true; } - return true; } + return true; + } - /// - /// Get the unsequenced collection hash code of this collection: from the cached - /// value if present and up to date, else (re)compute. - /// - /// The hash code - public virtual int GetUnsequencedHashCode() - { - if (iUnSequencedHashCodeStamp == stamp) - { - return iUnSequencedHashCode; - } - iUnSequencedHashCode = ComputeHashCode(this, itemequalityComparer); - iUnSequencedHashCodeStamp = stamp; + /// + /// Get the unsequenced collection hash code of this collection: from the cached + /// value if present and up to date, else (re)compute. + /// + /// The hash code + public virtual int GetUnsequencedHashCode() + { + if (iUnSequencedHashCodeStamp == stamp) + { return iUnSequencedHashCode; } + iUnSequencedHashCode = ComputeHashCode(this, itemEqualityComparer); + iUnSequencedHashCodeStamp = stamp; + return iUnSequencedHashCode; + } - /// - /// Check if the contents of otherCollection is equal to the contents of this - /// in the unsequenced sense. Uses the item equality comparer of this collection - /// - /// The collection to compare to. - /// True if equal - public virtual bool UnsequencedEquals(ICollection otherCollection) - { - return otherCollection != null && StaticEquals((ICollection)this, otherCollection, itemequalityComparer); - } + /// + /// Check if the contents of otherCollection is equal to the contents of this + /// in the unsequenced sense. Uses the item equality comparer of this collection + /// + /// The collection to compare to. + /// True if equal + public virtual bool UnsequencedEquals(ICollection otherCollection) + { + return otherCollection != null && StaticEquals((ICollection)this, otherCollection, itemEqualityComparer); + } - /// - /// Check if the collection has been modified since a specified time, expressed as a stamp value. - /// - /// if this collection has been updated - /// since a target time - /// The stamp identifying the target time - protected virtual void ModifyCheck(int thestamp) + + /// + /// Check if the collection has been modified since a specified time, expressed as a stamp value. + /// + /// if this collection has been updated + /// since a target time + /// The stamp identifying the target time + protected virtual void ModifyCheck(int thestamp) + { + if (stamp != thestamp) { - if (stamp != thestamp) - { - throw new CollectionModifiedException(); - } + throw new CollectionModifiedException(); } + } - /// - /// Check if it is valid to perform update operations, and if so increment stamp. - /// - /// If collection is read-only - protected virtual void UpdateCheck() + /// + /// Check if it is valid to perform update operations, and if so increment stamp. + /// + /// If collection is read-only + protected virtual void UpdateCheck() + { + if (isReadOnlyBase) { - if (isReadOnlyBase) - { - throw new ReadOnlyCollectionException(); - } - - stamp++; + throw new ReadOnlyCollectionException(); } - #endregion + stamp++; + } + + #endregion - #region ICollection members + #region ICollection members - /// - /// - /// - /// True if this collection is read only - public virtual bool IsReadOnly => isReadOnlyBase; + /// + /// + /// + /// True if this collection is read only + public virtual bool IsReadOnly => isReadOnlyBase; - #endregion + #endregion - #region ICollectionValue members - /// - /// - /// - /// The size of this collection - public override int Count => size; + #region ICollectionValue members + /// + /// + /// + /// The size of this collection + public override int Count => size; - /// - /// The value is symbolic indicating the type of asymptotic complexity - /// in terms of the size of this collection (worst-case or amortized as - /// relevant). - /// - /// A characterization of the speed of the - /// Count property in this collection. - public override Speed CountSpeed => Speed.Constant; + /// + /// The value is symbolic indicating the type of asymptotic complexity + /// in terms of the size of this collection (worst-case or amortized as + /// relevant). + /// + /// A characterization of the speed of the + /// Count property in this collection. + public override Speed CountSpeed => Speed.Constant; - #endregion + #endregion - #region IExtensible members + #region IExtensible members - /// - /// - /// - /// - public virtual System.Collections.Generic.IEqualityComparer EqualityComparer => itemequalityComparer; + /// + /// + /// + /// + public virtual System.Collections.Generic.IEqualityComparer EqualityComparer => itemEqualityComparer; - /// - /// - /// - /// True if this collection is empty - public override bool IsEmpty => size == 0; + /// + /// + /// + /// True if this collection is empty + public override bool IsEmpty => size == 0; - #endregion + #endregion - #region IEnumerable Members - /// - /// Create an enumerator for this collection. - /// - /// The enumerator - public abstract override System.Collections.Generic.IEnumerator GetEnumerator(); - #endregion - } + #region IEnumerable Members + /// + /// Create an enumerator for this collection. + /// + /// The enumerator + public abstract override System.Collections.Generic.IEnumerator GetEnumerator(); + #endregion } \ No newline at end of file diff --git a/C5/BaseClasses/CollectionValueBase.cs b/C5/BaseClasses/CollectionValueBase.cs index 03b84882..0f94a168 100644 --- a/C5/BaseClasses/CollectionValueBase.cs +++ b/C5/BaseClasses/CollectionValueBase.cs @@ -1,631 +1,633 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// Base class for classes implementing ICollectionValue[T] +/// +public abstract class CollectionValueBase : EnumerableBase, ICollectionValue, IShowable { + #region Event handling + private EventBlock? eventBlock; /// - /// Base class for classes implementing ICollectionValue[T] + /// /// - public abstract class CollectionValueBase : EnumerableBase, ICollectionValue, IShowable - { - #region Event handling - private EventBlock? eventBlock; - /// - /// - /// - /// - public virtual EventType ListenableEvents => 0; + /// + public virtual EventType ListenableEvents => 0; - /// - /// A flag bitmap of the events currently subscribed to by this collection. - /// - /// - public virtual EventType ActiveEvents => eventBlock == null ? 0 : eventBlock.events; + /// + /// A flag bitmap of the events currently subscribed to by this collection. + /// + /// + public virtual EventType ActiveEvents => eventBlock == null ? 0 : eventBlock.events; - private void CheckWillListen(EventType eventType) + private void CheckWillListen(EventType eventType) + { + if ((ListenableEvents & eventType) == 0) { - if ((ListenableEvents & eventType) == 0) - { - throw new UnlistenableEventException(); - } + throw new UnlistenableEventException(); } + } - /// - /// The change event. Will be raised for every change operation on the collection. - /// - public virtual event CollectionChangedHandler CollectionChanged + /// + /// The change event. Will be raised for every change operation on the collection. + /// + public virtual event CollectionChangedHandler CollectionChanged + { + add { CheckWillListen(EventType.Changed); (eventBlock ??= new EventBlock()).CollectionChanged += value; } + remove { - add { CheckWillListen(EventType.Changed); (eventBlock ??= new EventBlock()).CollectionChanged += value; } - remove + CheckWillListen(EventType.Changed); + if (eventBlock != null) { - CheckWillListen(EventType.Changed); - if (eventBlock != null) + eventBlock.CollectionChanged -= value; + if (eventBlock.events == 0) { - eventBlock.CollectionChanged -= value; - if (eventBlock.events == 0) - { - eventBlock = null; - } + eventBlock = null; } } } - /// - /// Fire the CollectionChanged event - /// - protected virtual void RaiseCollectionChanged() - { - eventBlock?.RaiseCollectionChanged(this); - } + } + /// + /// Fire the CollectionChanged event + /// + protected virtual void RaiseCollectionChanged() + { + eventBlock?.RaiseCollectionChanged(this); + } - /// - /// The clear event. Will be raised for every Clear operation on the collection. - /// - public virtual event CollectionClearedHandler CollectionCleared + /// + /// The clear event. Will be raised for every Clear operation on the collection. + /// + public virtual event CollectionClearedHandler CollectionCleared + { + add { CheckWillListen(EventType.Cleared); (eventBlock ??= new EventBlock()).CollectionCleared += value; } + remove { - add { CheckWillListen(EventType.Cleared); (eventBlock ??= new EventBlock()).CollectionCleared += value; } - remove + CheckWillListen(EventType.Cleared); + if (eventBlock != null) { - CheckWillListen(EventType.Cleared); - if (eventBlock != null) + eventBlock.CollectionCleared -= value; + if (eventBlock.events == 0) { - eventBlock.CollectionCleared -= value; - if (eventBlock.events == 0) - { - eventBlock = null; - } + eventBlock = null; } } } - /// - /// Fire the CollectionCleared event - /// - protected virtual void RaiseCollectionCleared(bool full, int count) - { - eventBlock?.RaiseCollectionCleared(this, full, count); - } + } + /// + /// Fire the CollectionCleared event + /// + protected virtual void RaiseCollectionCleared(bool full, int count) + { + eventBlock?.RaiseCollectionCleared(this, full, count); + } - /// - /// Fire the CollectionCleared event - /// - protected virtual void RaiseCollectionCleared(bool full, int count, int? offset) - { - eventBlock?.RaiseCollectionCleared(this, full, count, offset); - } + /// + /// Fire the CollectionCleared event + /// + protected virtual void RaiseCollectionCleared(bool full, int count, int? offset) + { + eventBlock?.RaiseCollectionCleared(this, full, count, offset); + } - /// - /// The item added event. Will be raised for every individual addition to the collection. - /// - public virtual event ItemsAddedHandler ItemsAdded + /// + /// The item added event. Will be raised for every individual addition to the collection. + /// + public virtual event ItemsAddedHandler ItemsAdded + { + add { CheckWillListen(EventType.Added); (eventBlock ??= new EventBlock()).ItemsAdded += value; } + remove { - add { CheckWillListen(EventType.Added); (eventBlock ??= new EventBlock()).ItemsAdded += value; } - remove + CheckWillListen(EventType.Added); + if (eventBlock != null) { - CheckWillListen(EventType.Added); - if (eventBlock != null) + eventBlock.ItemsAdded -= value; + if (eventBlock.events == 0) { - eventBlock.ItemsAdded -= value; - if (eventBlock.events == 0) - { - eventBlock = null; - } + eventBlock = null; } } } - /// - /// Fire the ItemsAdded event - /// - /// The item that was added - /// - protected virtual void RaiseItemsAdded(T item, int count) - { - eventBlock?.RaiseItemsAdded(this, item, count); - } + } + /// + /// Fire the ItemsAdded event + /// + /// The item that was added + /// + protected virtual void RaiseItemsAdded(T item, int count) + { + eventBlock?.RaiseItemsAdded(this, item, count); + } - /// - /// The item removed event. Will be raised for every individual removal from the collection. - /// - public virtual event ItemsRemovedHandler ItemsRemoved + /// + /// The item removed event. Will be raised for every individual removal from the collection. + /// + public virtual event ItemsRemovedHandler ItemsRemoved + { + add { CheckWillListen(EventType.Removed); (eventBlock ??= new EventBlock()).ItemsRemoved += value; } + remove { - add { CheckWillListen(EventType.Removed); (eventBlock ??= new EventBlock()).ItemsRemoved += value; } - remove + CheckWillListen(EventType.Removed); + if (eventBlock != null) { - CheckWillListen(EventType.Removed); - if (eventBlock != null) + eventBlock.ItemsRemoved -= value; + if (eventBlock.events == 0) { - eventBlock.ItemsRemoved -= value; - if (eventBlock.events == 0) - { - eventBlock = null; - } + eventBlock = null; } } } + } - /// - /// Fire the ItemsRemoved event - /// - /// The item that was removed - /// - protected virtual void RaiseItemsRemoved(T item, int count) - { - eventBlock?.RaiseItemsRemoved(this, item, count); - } + /// + /// Fire the ItemsRemoved event + /// + /// The item that was removed + /// + protected virtual void RaiseItemsRemoved(T item, int count) + { + eventBlock?.RaiseItemsRemoved(this, item, count); + } - /// - /// The item added event. Will be raised for every individual addition to the collection. - /// - public virtual event ItemInsertedHandler ItemInserted + /// + /// The item added event. Will be raised for every individual addition to the collection. + /// + public virtual event ItemInsertedHandler ItemInserted + { + add { CheckWillListen(EventType.Inserted); (eventBlock ??= new EventBlock()).ItemInserted += value; } + remove { - add { CheckWillListen(EventType.Inserted); (eventBlock ??= new EventBlock()).ItemInserted += value; } - remove + CheckWillListen(EventType.Inserted); + if (eventBlock != null) { - CheckWillListen(EventType.Inserted); - if (eventBlock != null) + eventBlock.ItemInserted -= value; + if (eventBlock.events == 0) { - eventBlock.ItemInserted -= value; - if (eventBlock.events == 0) - { - eventBlock = null; - } + eventBlock = null; } } } - /// - /// Fire the ItemInserted event - /// - /// The item that was added - /// - protected virtual void RaiseItemInserted(T item, int index) - { - eventBlock?.RaiseItemInserted(this, item, index); - } + } + /// + /// Fire the ItemInserted event + /// + /// The item that was added + /// + protected virtual void RaiseItemInserted(T item, int index) + { + eventBlock?.RaiseItemInserted(this, item, index); + } - /// - /// The item removed event. Will be raised for every individual removal from the collection. - /// - public virtual event ItemRemovedAtHandler ItemRemovedAt + /// + /// The item removed event. Will be raised for every individual removal from the collection. + /// + public virtual event ItemRemovedAtHandler ItemRemovedAt + { + add { CheckWillListen(EventType.RemovedAt); (eventBlock ??= new EventBlock()).ItemRemovedAt += value; } + remove { - add { CheckWillListen(EventType.RemovedAt); (eventBlock ??= new EventBlock()).ItemRemovedAt += value; } - remove + CheckWillListen(EventType.RemovedAt); + if (eventBlock != null) { - CheckWillListen(EventType.RemovedAt); - if (eventBlock != null) + eventBlock.ItemRemovedAt -= value; + if (eventBlock.events == 0) { - eventBlock.ItemRemovedAt -= value; - if (eventBlock.events == 0) - { - eventBlock = null; - } + eventBlock = null; } } } - /// - /// Fire the ItemRemovedAt event - /// - /// The item that was removed - /// - protected virtual void RaiseItemRemovedAt(T item, int index) + } + /// + /// Fire the ItemRemovedAt event + /// + /// The item that was removed + /// + protected virtual void RaiseItemRemovedAt(T item, int index) + { + eventBlock?.RaiseItemRemovedAt(this, item, index); + } + + #region Event support for IList + /// + /// + /// + /// + /// + /// + protected virtual void RaiseForSetThis(int index, T value, T item) + { + if (ActiveEvents != 0) + { + RaiseItemsRemoved(item, 1); + RaiseItemRemovedAt(item, index); + RaiseItemsAdded(value, 1); + RaiseItemInserted(value, index); + RaiseCollectionChanged(); + } + } + /// + /// + /// + /// + /// + protected virtual void RaiseForInsert(int i, T item) + { + if (ActiveEvents != 0) { - eventBlock?.RaiseItemRemovedAt(this, item, index); + RaiseItemInserted(item, i); + RaiseItemsAdded(item, 1); + RaiseCollectionChanged(); } + } - #region Event support for IList - /// - /// - /// - /// - /// - /// - protected virtual void RaiseForSetThis(int index, T value, T item) + /// + /// + /// + /// + protected void RaiseForRemove(T item) + { + if (ActiveEvents != 0) { - if (ActiveEvents != 0) - { - RaiseItemsRemoved(item, 1); - RaiseItemRemovedAt(item, index); - RaiseItemsAdded(value, 1); - RaiseItemInserted(value, index); - RaiseCollectionChanged(); - } + RaiseItemsRemoved(item, 1); + RaiseCollectionChanged(); } - /// - /// - /// - /// - /// - protected virtual void RaiseForInsert(int i, T item) + } + + /// + /// + /// + /// + /// + protected void RaiseForRemove(T item, int count) + { + if (ActiveEvents != 0) { - if (ActiveEvents != 0) - { - RaiseItemInserted(item, i); - RaiseItemsAdded(item, 1); - RaiseCollectionChanged(); - } + RaiseItemsRemoved(item, count); + RaiseCollectionChanged(); } + } - /// - /// - /// - /// - protected void RaiseForRemove(T item) + /// + /// + /// + /// + /// + protected void RaiseForRemoveAt(int index, T item) + { + if (ActiveEvents != 0) { - if (ActiveEvents != 0) - { - RaiseItemsRemoved(item, 1); - RaiseCollectionChanged(); - } + RaiseItemRemovedAt(item, index); + RaiseItemsRemoved(item, 1); + RaiseCollectionChanged(); } + } - /// - /// - /// - /// - /// - protected void RaiseForRemove(T item, int count) + #endregion + + #region Event Support for ICollection + /// + /// + /// + /// + /// + protected virtual void RaiseForUpdate(T newitem, T olditem) + { + if (ActiveEvents != 0) + { + RaiseItemsRemoved(olditem, 1); + RaiseItemsAdded(newitem, 1); + RaiseCollectionChanged(); + } + } + /// + /// + /// + /// + /// + /// + protected virtual void RaiseForUpdate(T newitem, T olditem, int count) + { + if (ActiveEvents != 0) + { + RaiseItemsRemoved(olditem, count); + RaiseItemsAdded(newitem, count); + RaiseCollectionChanged(); + } + } + /// + /// + /// + /// + protected virtual void RaiseForAdd(T item) + { + if (ActiveEvents != 0) + { + RaiseItemsAdded(item, 1); + RaiseCollectionChanged(); + } + } + /// + /// + /// + /// + protected virtual void RaiseForRemoveAll(ICollectionValue? wasRemoved) + { + if ((ActiveEvents & EventType.Removed) != 0) { - if (ActiveEvents != 0) + if (wasRemoved != null) { - RaiseItemsRemoved(item, count); - RaiseCollectionChanged(); + foreach (T item in wasRemoved) + { + RaiseItemsRemoved(item, 1); + } } } - /// - /// - /// - /// - /// - protected void RaiseForRemoveAt(int index, T item) + if (wasRemoved != null && wasRemoved.Count > 0) { - if (ActiveEvents != 0) - { - RaiseItemRemovedAt(item, index); - RaiseItemsRemoved(item, 1); - RaiseCollectionChanged(); - } + RaiseCollectionChanged(); } + } - #endregion + /// + /// + /// + protected class RaiseForRemoveAllHandler + { + private readonly CollectionValueBase collection; + private CircularQueue? wasRemoved = null; + private bool wasChanged = false; - #region Event Support for ICollection /// - /// + /// /// - /// - /// - protected virtual void RaiseForUpdate(T newitem, T olditem) + /// + public RaiseForRemoveAllHandler(CollectionValueBase collection) { - if (ActiveEvents != 0) - { - RaiseItemsRemoved(olditem, 1); - RaiseItemsAdded(newitem, 1); - RaiseCollectionChanged(); - } + this.collection = collection; + mustFireRemoved = (collection.ActiveEvents & EventType.Removed) != 0; + MustFire = (collection.ActiveEvents & (EventType.Removed | EventType.Changed)) != 0; } + + private readonly bool mustFireRemoved; + /// - /// + /// /// - /// - /// - /// - protected virtual void RaiseForUpdate(T newitem, T olditem, int count) - { - if (ActiveEvents != 0) - { - RaiseItemsRemoved(olditem, count); - RaiseItemsAdded(newitem, count); - RaiseCollectionChanged(); - } - } + public bool MustFire { get; } + /// - /// + /// /// /// - protected virtual void RaiseForAdd(T item) - { - if (ActiveEvents != 0) - { - RaiseItemsAdded(item, 1); - RaiseCollectionChanged(); - } - } - /// - /// - /// - /// - protected virtual void RaiseForRemoveAll(ICollectionValue? wasRemoved) + public void Remove(T item) { - if ((ActiveEvents & EventType.Removed) != 0) + if (mustFireRemoved) { - if (wasRemoved != null) - { - foreach (T item in wasRemoved) - { - RaiseItemsRemoved(item, 1); - } - } - } + wasRemoved ??= new CircularQueue(); - if (wasRemoved != null && wasRemoved.Count > 0) + wasRemoved.Enqueue(item); + } + if (!wasChanged) { - RaiseCollectionChanged(); + wasChanged = true; } } /// - /// + /// /// - protected class RaiseForRemoveAllHandler + public void Raise() { - private readonly CollectionValueBase collection; - private CircularQueue? wasRemoved = null; - private bool wasChanged = false; - - /// - /// - /// - /// - public RaiseForRemoveAllHandler(CollectionValueBase collection) - { - this.collection = collection; - mustFireRemoved = (collection.ActiveEvents & EventType.Removed) != 0; - MustFire = (collection.ActiveEvents & (EventType.Removed | EventType.Changed)) != 0; - } - - private readonly bool mustFireRemoved; - - /// - /// - /// - public bool MustFire { get; } - - /// - /// - /// - /// - public void Remove(T item) + if (wasRemoved != null) { - if (mustFireRemoved) + foreach (T item in wasRemoved) { - wasRemoved ??= new CircularQueue(); - - wasRemoved.Enqueue(item); - } - if (!wasChanged) - { - wasChanged = true; + collection.RaiseItemsRemoved(item, 1); } } - /// - /// - /// - public void Raise() + if (wasChanged) { - if (wasRemoved != null) - { - foreach (T item in wasRemoved) - { - collection.RaiseItemsRemoved(item, 1); - } - } - - if (wasChanged) - { - collection.RaiseCollectionChanged(); - } + collection.RaiseCollectionChanged(); } } - #endregion + } + #endregion - #endregion + #endregion - /// - /// Check if collection is empty. - /// - /// True if empty - public abstract bool IsEmpty { get; } + /// + /// Check if collection is empty. + /// + /// True if empty + public abstract bool IsEmpty { get; } - /// - /// The number of items in this collection. - /// - /// - public abstract int Count { get; } + /// + /// The number of items in this collection. + /// + /// + public abstract int Count { get; } - /// - /// The value is symbolic indicating the type of asymptotic complexity - /// in terms of the size of this collection (worst-case or amortized as - /// relevant). - /// - /// A characterization of the speed of the - /// Count property in this collection. - public abstract Speed CountSpeed { get; } + /// + /// The value is symbolic indicating the type of asymptotic complexity + /// in terms of the size of this collection (worst-case or amortized as + /// relevant). + /// + /// A characterization of the speed of the + /// Count property in this collection. + public abstract Speed CountSpeed { get; } - /// - /// Copy the items of this collection to part of an array. - /// - /// if index - /// is not a valid index - /// into the array (i.e. negative or greater than the size of the array) - /// or the array does not have room for the items. - /// The array to copy to. - /// The starting index. - public virtual void CopyTo(T[] array, int index) + /// + /// Copy the items of this collection to part of an array. + /// + /// if index + /// is not a valid index + /// into the array (i.e. negative or greater than the size of the array) + /// or the array does not have room for the items. + /// The array to copy to. + /// The starting index. + public virtual void CopyTo(T[] array, int index) + { + if (index < 0 || index + Count > array.Length) { - if (index < 0 || index + Count > array.Length) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - - foreach (T item in this) - { - array[index++] = item; - } + throw new ArgumentOutOfRangeException(nameof(index)); } - /// - /// Create an array with the items of this collection (in the same order as an - /// enumerator would output them). - /// - /// The array - public virtual T[] ToArray() + foreach (T item in this) { - T[] res = new T[Count]; - int i = 0; + array[index++] = item; + } + } - foreach (T item in this) - { - res[i++] = item; - } + /// + /// Create an array with the items of this collection (in the same order as an + /// enumerator would output them). + /// + /// The array + public virtual T[] ToArray() + { + T[] res = new T[Count]; + int i = 0; - return res; + foreach (T item in this) + { + res[i++] = item; } - /// - /// Apply an single argument action, to this enumerable - /// - /// The action delegate - public virtual void Apply(Action action) + return res; + } + + /// + /// Apply an single argument action, to this enumerable + /// + /// The action delegate + public virtual void Apply(Action action) + { + foreach (T item in this) { - foreach (T item in this) - { - action(item); - } + action(item); } + } - /// - /// Check if there exists an item that satisfies a - /// specific predicate in this collection. - /// - /// A delegate - /// ( with R = bool) - /// defining the predicate - /// True if such an item exists - public virtual bool Exists(Func predicate) + /// + /// Check if there exists an item that satisfies a + /// specific predicate in this collection. + /// + /// A delegate + /// ( with R = bool) + /// defining the predicate + /// True if such an item exists + public virtual bool Exists(Func predicate) + { + foreach (T item in this) { - foreach (T item in this) + if (predicate(item)) { - if (predicate(item)) - { - return true; - } + return true; } - - return false; } - /// - /// Check if there exists an item that satisfies a - /// specific predicate in this collection and return the first one in enumeration order. - /// - /// A delegate - /// ( with R == bool) defining the predicate - /// - /// True is such an item exists - public virtual bool Find(Func predicate, out T item) + return false; + } + + /// + /// Check if there exists an item that satisfies a + /// specific predicate in this collection and return the first one in enumeration order. + /// + /// A delegate + /// ( with R == bool) defining the predicate + /// + /// True is such an item exists + public virtual bool Find(Func predicate, out T item) + { + foreach (T jtem in this) { - foreach (T jtem in this) + if (predicate(jtem)) { - if (predicate(jtem)) - { - item = jtem; - return true; - } + item = jtem; + return true; } - - item = default; - return false; } - /// - /// Check if all items in this collection satisfies a specific predicate. - /// - /// A delegate - /// ( with R = bool) - /// defining the predicate - /// True if all items satisfies the predicate - public virtual bool All(Func predicate) + item = default; + return false; + } + + /// + /// Check if all items in this collection satisfies a specific predicate. + /// + /// A delegate + /// ( with R = bool) + /// defining the predicate + /// True if all items satisfies the predicate + public virtual bool All(Func predicate) + { + foreach (T item in this) { - foreach (T item in this) + if (!predicate(item)) { - if (!predicate(item)) - { - return false; - } + return false; } - - return true; } - /// - /// Create an enumerable, enumerating the items of this collection that satisfies - /// a certain condition. - /// - /// A delegate - /// ( with R = bool) - /// defining the predicate - /// The filtered enumerable - public virtual System.Collections.Generic.IEnumerable Filter(Func predicate) + return true; + } + + /// + /// Create an enumerable, enumerating the items of this collection that satisfies + /// a certain condition. + /// + /// A delegate + /// ( with R = bool) + /// defining the predicate + /// The filtered enumerable + public virtual System.Collections.Generic.IEnumerable Filter(Func predicate) + { + foreach (T item in this) { - foreach (T item in this) + if (predicate(item)) { - if (predicate(item)) - { - yield return item; - } + yield return item; } } + } - /// - /// Choose some item of this collection. - /// - /// if collection is empty. - /// - public abstract T Choose(); + /// + /// Choose some item of this collection. + /// + /// if collection is empty. + /// + public abstract T Choose(); - /// - /// Create an enumerator for this collection. - /// - /// The enumerator - public abstract override System.Collections.Generic.IEnumerator GetEnumerator(); + /// + /// Create an enumerator for this collection. + /// + /// The enumerator + public abstract override System.Collections.Generic.IEnumerator GetEnumerator(); - #region IShowable Members + #region IShowable Members - /// - /// - /// - /// - /// - /// - /// - public virtual bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider? formatProvider) - { - return Showing.ShowCollectionValue(this, stringbuilder, ref rest, formatProvider!); - } - #endregion + /// + /// + /// + /// + /// + /// + /// + public virtual bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider? formatProvider) + { + return Showing.ShowCollectionValue(this, stringbuilder, ref rest, formatProvider!); + } + #endregion - #region IFormattable Members + #region IFormattable Members - /// - /// - /// - /// - /// - /// - public virtual string ToString(string? format, IFormatProvider? formatProvider) - { - return Showing.ShowString(this, format, formatProvider); - } + /// + /// + /// + /// + /// + /// + public virtual string ToString(string? format, IFormatProvider? formatProvider) + { + return Showing.ShowString(this, format, formatProvider); + } - #endregion + #endregion - /// - /// - /// - /// - public override string ToString() - { - return ToString(null, null); - } + /// + /// + /// + /// + public override string ToString() + { + return ToString(null, null); } } \ No newline at end of file diff --git a/C5/BaseClasses/ComparerFactory.cs b/C5/BaseClasses/ComparerFactory.cs index b4a953b4..2d7e713b 100644 --- a/C5/BaseClasses/ComparerFactory.cs +++ b/C5/BaseClasses/ComparerFactory.cs @@ -4,33 +4,32 @@ using System; using System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// Factory class to create comparers and equality comparers using Func delegates +/// +/// The type to compare +public static class ComparerFactory { /// - /// Factory class to create comparers and equality comparers using Func delegates + /// Create a new comparer. /// - /// The type to compare - public static class ComparerFactory + /// The compare function. + /// The comparer + public static IComparer CreateComparer(Func comparer) { - /// - /// Create a new comparer. - /// - /// The compare function. - /// The comparer - public static IComparer CreateComparer(Func comparer) - { - return new InternalComparer(comparer); - } + return new InternalComparer(comparer); + } - /// - /// Creates a new equality comparer. - /// - /// The equals function. - /// The getHashCode function. - /// The equality comparer. - public static IEqualityComparer CreateEqualityComparer(Func equals, Func getHashCode) - { - return new InternalEqualityComparer(equals, getHashCode); - } + /// + /// Creates a new equality comparer. + /// + /// The equals function. + /// The getHashCode function. + /// The equality comparer. + public static IEqualityComparer CreateEqualityComparer(Func equals, Func getHashCode) + { + return new InternalEqualityComparer(equals, getHashCode); } } \ No newline at end of file diff --git a/C5/BaseClasses/DictionaryBase.cs b/C5/BaseClasses/DictionaryBase.cs index 757a9d24..ed65b2ff 100644 --- a/C5/BaseClasses/DictionaryBase.cs +++ b/C5/BaseClasses/DictionaryBase.cs @@ -1,515 +1,505 @@ using System; using System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// A base class for implementing a dictionary based on a set collection implementation. +/// See the source code for for an example +/// +/// +/// +/// +/// +/// +public abstract class DictionaryBase(IEqualityComparer keyEqualityComparer) : CollectionValueBase>, IDictionary { /// - /// A base class for implementing a dictionary based on a set collection implementation. - /// See the source code for for an example - /// + /// The set collection of entries underlying this dictionary implementation /// - public abstract class DictionaryBase : CollectionValueBase>, IDictionary + protected ICollection> pairs; + + private readonly IEqualityComparer keyEqualityComparer = keyEqualityComparer ?? throw new NullReferenceException("Key equality comparer cannot be null"); + + #region Events + private ProxyEventBlock>? eventBlock; + + /// + /// The change event. Will be raised for every change operation on the collection. + /// + public override event CollectionChangedHandler> CollectionChanged { - /// - /// The set collection of entries underlying this dictionary implementation - /// - protected ICollection> pairs; - private readonly System.Collections.Generic.IEqualityComparer keyequalityComparer; - - #region Events - private ProxyEventBlock>? eventBlock; - - /// - /// The change event. Will be raised for every change operation on the collection. - /// - public override event CollectionChangedHandler> CollectionChanged + add { (eventBlock ??= new ProxyEventBlock>(this, pairs)).CollectionChanged += value; } + remove { - add { (eventBlock ??= new ProxyEventBlock>(this, pairs)).CollectionChanged += value; } - remove + if (eventBlock != null) { - if (eventBlock != null) - { - eventBlock.CollectionChanged -= value; - } + eventBlock.CollectionChanged -= value; } } + } - /// - /// The change event. Will be raised for every change operation on the collection. - /// - public override event CollectionClearedHandler> CollectionCleared + /// + /// The change event. Will be raised for every change operation on the collection. + /// + public override event CollectionClearedHandler> CollectionCleared + { + add { (eventBlock ??= new ProxyEventBlock>(this, pairs)).CollectionCleared += value; } + remove { - add { (eventBlock ??= new ProxyEventBlock>(this, pairs)).CollectionCleared += value; } - remove + if (eventBlock != null) { - if (eventBlock != null) - { - eventBlock.CollectionCleared -= value; - } + eventBlock.CollectionCleared -= value; } } + } - /// - /// The item added event. Will be raised for every individual addition to the collection. - /// - public override event ItemsAddedHandler> ItemsAdded + /// + /// The item added event. Will be raised for every individual addition to the collection. + /// + public override event ItemsAddedHandler> ItemsAdded + { + add { (eventBlock ??= new ProxyEventBlock>(this, pairs)).ItemsAdded += value; } + remove { - add { (eventBlock ??= new ProxyEventBlock>(this, pairs)).ItemsAdded += value; } - remove + if (eventBlock != null) { - if (eventBlock != null) - { - eventBlock.ItemsAdded -= value; - } + eventBlock.ItemsAdded -= value; } } + } - /// - /// The item added event. Will be raised for every individual removal from the collection. - /// - public override event ItemsRemovedHandler> ItemsRemoved + /// + /// The item added event. Will be raised for every individual removal from the collection. + /// + public override event ItemsRemovedHandler> ItemsRemoved + { + add { (eventBlock ??= new ProxyEventBlock>(this, pairs)).ItemsRemoved += value; } + remove { - add { (eventBlock ??= new ProxyEventBlock>(this, pairs)).ItemsRemoved += value; } - remove + if (eventBlock != null) { - if (eventBlock != null) - { - eventBlock.ItemsRemoved -= value; - } + eventBlock.ItemsRemoved -= value; } } + } - /// - /// - /// - public override EventType ListenableEvents => EventType.Basic; + /// + /// + /// + public override EventType ListenableEvents => EventType.Basic; - /// - /// - /// - public override EventType ActiveEvents => pairs.ActiveEvents; + /// + /// + /// + public override EventType ActiveEvents => pairs.ActiveEvents; - #endregion + #endregion - /// - /// - /// - /// - protected DictionaryBase(System.Collections.Generic.IEqualityComparer keyequalityComparer) - { - this.keyequalityComparer = keyequalityComparer ?? throw new NullReferenceException("Key equality comparer cannot be null"); - } + #region IDictionary Members - #region IDictionary Members + /// + /// + /// + /// + public virtual IEqualityComparer EqualityComparer => keyEqualityComparer; - /// - /// - /// - /// - public virtual System.Collections.Generic.IEqualityComparer EqualityComparer => keyequalityComparer; + /// + /// Add a new (key, value) pair (a mapping) to the dictionary. + /// + /// if there already is an entry with the same key. + /// Key to add + /// Value to add + public virtual void Add(K key, V value) + { + KeyValuePair p = new(key, value); - /// - /// Add a new (key, value) pair (a mapping) to the dictionary. - /// - /// if there already is an entry with the same key. - /// Key to add - /// Value to add - public virtual void Add(K key, V value) + if (!pairs.Add(p)) { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(key, value); - - if (!pairs.Add(p)) - { - throw new DuplicateNotAllowedException("Key being added: '" + key + "'"); - } + throw new DuplicateNotAllowedException("Key being added: '" + key + "'"); } + } - /// - /// Add the entries from a collection of pairs to this dictionary. - /// TODO: add restrictions L:K and W:V when the .Net SDK allows it - /// - /// - /// If the input contains duplicate keys or a key already present in this dictionary. - /// - public virtual void AddAll(System.Collections.Generic.IEnumerable> entries) - where L : K - where W : V + /// + /// Add the entries from a collection of pairs to this dictionary. + /// TODO: add restrictions L:K and W:V when the .Net SDK allows it + /// + /// + /// If the input contains duplicate keys or a key already present in this dictionary. + /// + public virtual void AddAll(IEnumerable> entries) + where L : K + where W : V + { + foreach (KeyValuePair pair in entries) { - foreach (System.Collections.Generic.KeyValuePair pair in entries) + KeyValuePair p = new(pair.Key, pair.Value); + if (!pairs.Add(p)) { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(pair.Key, pair.Value); - if (!pairs.Add(p)) - { - throw new DuplicateNotAllowedException("Key being added: '" + pair.Key + "'"); - } + throw new DuplicateNotAllowedException("Key being added: '" + pair.Key + "'"); } } + } - /// - /// Remove an entry with a given key from the dictionary - /// - /// The key of the entry to remove - /// True if an entry was found (and removed) - public virtual bool Remove(K key) - { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(key, default); + /// + /// Remove an entry with a given key from the dictionary + /// + /// The key of the entry to remove + /// True if an entry was found (and removed) + public virtual bool Remove(K key) + { + KeyValuePair p = new(key, default!); - return pairs.Remove(p); - } + return pairs.Remove(p); + } - /// - /// Remove an entry with a given key from the dictionary and report its value. - /// - /// The key of the entry to remove - /// On exit, the value of the removed entry - /// True if an entry was found (and removed) - public virtual bool Remove(K key, out V value) - { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(key, default); + /// + /// Remove an entry with a given key from the dictionary and report its value. + /// + /// The key of the entry to remove + /// On exit, the value of the removed entry + /// True if an entry was found (and removed) + public virtual bool Remove(K key, out V value) + { + KeyValuePair p = new(key, default!); - if (pairs.Remove(p, out p)) - { - value = p.Value; - return true; - } - else - { - value = default; - return false; - } + if (pairs.Remove(p, out p)) + { + value = p.Value; + return true; } + else + { + value = default; + return false; + } + } - /// - /// Remove all entries from the dictionary - /// - public virtual void Clear() { pairs.Clear(); } + /// + /// Remove all entries from the dictionary + /// + public virtual void Clear() { pairs.Clear(); } - /// - /// - /// - /// - public virtual Speed ContainsSpeed => pairs.ContainsSpeed; + /// + /// + /// + /// + public virtual Speed ContainsSpeed => pairs.ContainsSpeed; - /// - /// Check if there is an entry with a specified key - /// - /// The key to look for - /// True if key was found - public virtual bool Contains(K key) - { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(key, default); + /// + /// Check if there is an entry with a specified key + /// + /// The key to look for + /// True if key was found + public virtual bool Contains(K key) + { + KeyValuePair p = new(key, default!); - return pairs.Contains(p); - } + return pairs.Contains(p); + } - private class LiftedEnumerable : IEnumerable> where H : K + private class LiftedEnumerable : IEnumerable> where H : K + { + private readonly IEnumerable keys; + public LiftedEnumerable(IEnumerable keys) => this.keys = keys; + public IEnumerator> GetEnumerator() { - private readonly System.Collections.Generic.IEnumerable keys; - public LiftedEnumerable(System.Collections.Generic.IEnumerable keys) { this.keys = keys; } - public System.Collections.Generic.IEnumerator> GetEnumerator() - { - foreach (H key in keys) - { - yield return new System.Collections.Generic.KeyValuePair(key, default); - } - } - - #region IEnumerable Members - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + foreach (H key in keys) { - throw new NotImplementedException(); + yield return new KeyValuePair(key, default!); } - - #endregion } - /// - /// - /// - /// - /// - public virtual bool ContainsAll(System.Collections.Generic.IEnumerable keys) where H : K + #region IEnumerable Members + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { - return pairs.ContainsAll(new LiftedEnumerable(keys)); + throw new NotImplementedException(); } - /// - /// Check if there is an entry with a specified key and report the corresponding - /// value if found. This can be seen as a safe form of "val = this[key]". - /// - /// The key to look for - /// On exit, the value of the entry - /// True if key was found - public virtual bool Find(ref K key, out V value) - { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(key, default); + #endregion + } - if (pairs.Find(ref p)) - { - key = p.Key; - value = p.Value; - return true; - } - else - { - value = default; - return false; - } - } + /// + /// + /// + /// + /// + public virtual bool ContainsAll(IEnumerable keys) where H : K + { + return pairs.ContainsAll(new LiftedEnumerable(keys)); + } + /// + /// Check if there is an entry with a specified key and report the corresponding + /// value if found. This can be seen as a safe form of "val = this[key]". + /// + /// The key to look for + /// On exit, the value of the entry + /// True if key was found + public virtual bool Find(ref K key, out V value) + { + KeyValuePair p = new(key, default!); - /// - /// Look for a specific key in the dictionary and if found replace the value with a new one. - /// This can be seen as a non-adding version of "this[key] = val". - /// - /// The key to look for - /// The new value - /// True if key was found - public virtual bool Update(K key, V value) + if (pairs.Find(ref p)) { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(key, value); - - return pairs.Update(p); + key = p.Key; + value = p.Value; + return true; + } + else + { + value = default; + return false; } + } - /// - /// - /// - /// - /// - /// - /// - public virtual bool Update(K key, V value, out V oldvalue) - { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(key, value); + /// + /// Look for a specific key in the dictionary and if found replace the value with a new one. + /// This can be seen as a non-adding version of "this[key] = val". + /// + /// The key to look for + /// The new value + /// True if key was found + public virtual bool Update(K key, V value) + { + KeyValuePair p = new(key, value); - bool retval = pairs.Update(p, out p); - oldvalue = p.Value; - return retval; - } + return pairs.Update(p); + } - /// - /// Look for a specific key in the dictionary. If found, report the corresponding value, - /// else add an entry with the key and the supplied value. - /// - /// On entry the key to look for - /// On entry the value to add if the key is not found. - /// On exit the value found if any. - /// True if key was found - public virtual bool FindOrAdd(K key, ref V value) - { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(key, value); + /// + /// + /// + /// + /// + /// + /// + public virtual bool Update(K key, V value, out V oldvalue) + { + KeyValuePair p = new(key, value); - if (!pairs.FindOrAdd(ref p)) - { - return false; - } - else - { - value = p.Value; - //key = p.key; - return true; - } - } + bool retval = pairs.Update(p, out p); + oldvalue = p.Value; + return retval; + } + /// + /// Look for a specific key in the dictionary. If found, report the corresponding value, + /// else add an entry with the key and the supplied value. + /// + /// On entry the key to look for + /// On entry the value to add if the key is not found. + /// On exit the value found if any. + /// True if key was found + public virtual bool FindOrAdd(K key, ref V value) + { + KeyValuePair p = new(key, value); - /// - /// Update value in dictionary corresponding to key if found, else add new entry. - /// More general than "this[key] = val;" by reporting if key was found. - /// - /// The key to look for - /// The value to add or replace with. - /// True if entry was updated. - public virtual bool UpdateOrAdd(K key, V value) + if (!pairs.FindOrAdd(ref p)) { - return pairs.UpdateOrAdd(new System.Collections.Generic.KeyValuePair(key, value)); + return false; } - - - /// - /// Update value in dictionary corresponding to key if found, else add new entry. - /// More general than "this[key] = val;" by reporting if key was found and the old value if any. - /// - /// - /// - /// - /// - public virtual bool UpdateOrAdd(K key, V value, out V oldvalue) + else { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(key, value); - bool retval = pairs.UpdateOrAdd(p, out p); - oldvalue = p.Value; - return retval; + value = p.Value; + //key = p.key; + return true; } + } - #region Keys,Values support classes - internal class ValuesCollection : CollectionValueBase, ICollectionValue - { - private readonly ICollection> pairs; + /// + /// Update value in dictionary corresponding to key if found, else add new entry. + /// More general than "this[key] = val;" by reporting if key was found. + /// + /// The key to look for + /// The value to add or replace with. + /// True if entry was updated. + public virtual bool UpdateOrAdd(K key, V value) + { + return pairs.UpdateOrAdd(new KeyValuePair(key, value)); + } + + /// + /// Update value in dictionary corresponding to key if found, else add new entry. + /// More general than "this[key] = val;" by reporting if key was found and the old value if any. + /// + /// + /// + /// + /// + public virtual bool UpdateOrAdd(K key, V value, out V oldvalue) + { + KeyValuePair p = new(key, value); + bool retval = pairs.UpdateOrAdd(p, out p); + oldvalue = p.Value; + return retval; + } + + #region Keys,Values support classes + internal class ValuesCollection : CollectionValueBase, ICollectionValue + { + private readonly ICollection> pairs; - internal ValuesCollection(ICollection> pairs) - { this.pairs = pairs; } + internal ValuesCollection(ICollection> pairs) + { this.pairs = pairs; } - public override V Choose() { return pairs.Choose().Value; } - public override System.Collections.Generic.IEnumerator GetEnumerator() + public override V Choose() { return pairs.Choose().Value; } + + public override System.Collections.Generic.IEnumerator GetEnumerator() + { + //Updatecheck is performed by the pairs enumerator + foreach (KeyValuePair p in pairs) { - //Updatecheck is performed by the pairs enumerator - foreach (System.Collections.Generic.KeyValuePair p in pairs) - { - yield return p.Value; - } + yield return p.Value; } + } - public override bool IsEmpty => pairs.IsEmpty; + public override bool IsEmpty => pairs.IsEmpty; - public override int Count => pairs.Count; + public override int Count => pairs.Count; - public override Speed CountSpeed => Speed.Constant; - } + public override Speed CountSpeed => Speed.Constant; + } - internal class KeysCollection : CollectionValueBase, ICollectionValue - { - private readonly ICollection> pairs; + internal class KeysCollection : CollectionValueBase, ICollectionValue + { + private readonly ICollection> pairs; - internal KeysCollection(ICollection> pairs) - { this.pairs = pairs; } + internal KeysCollection(ICollection> pairs) + { this.pairs = pairs; } - public override K Choose() { return pairs.Choose().Key; } + public override K Choose() { return pairs.Choose().Key; } - public override System.Collections.Generic.IEnumerator GetEnumerator() + public override System.Collections.Generic.IEnumerator GetEnumerator() + { + foreach (KeyValuePair p in pairs) { - foreach (System.Collections.Generic.KeyValuePair p in pairs) - { - yield return p.Key; - } + yield return p.Key; } + } - public override bool IsEmpty => pairs.IsEmpty; + public override bool IsEmpty => pairs.IsEmpty; - public override int Count => pairs.Count; + public override int Count => pairs.Count; - public override Speed CountSpeed => pairs.CountSpeed; - } - #endregion + public override Speed CountSpeed => pairs.CountSpeed; + } + #endregion - /// - /// - /// - /// A collection containing all the keys of the dictionary - public virtual ICollectionValue Keys => new KeysCollection(pairs); - - - /// - /// - /// - /// A collection containing all the values of the dictionary - public virtual ICollectionValue Values => new ValuesCollection(pairs); - - /// - /// - /// - public virtual Func Func => delegate (K k) { return this[k]; }; - - /// - /// Indexer by key for dictionary. - /// The get method will throw an exception if no entry is found. - /// The set method behaves like . - /// - /// On get if no entry is found. - /// The value corresponding to the key - public virtual V this[K key] + /// + /// + /// + /// A collection containing all the keys of the dictionary + public virtual ICollectionValue Keys => new KeysCollection(pairs); + + /// + /// + /// + /// A collection containing all the values of the dictionary + public virtual ICollectionValue Values => new ValuesCollection(pairs); + + /// + /// + /// + public virtual Func Func => delegate (K k) { return this[k]; }; + + /// + /// Indexer by key for dictionary. + /// The get method will throw an exception if no entry is found. + /// The set method behaves like . + /// + /// On get if no entry is found. + /// The value corresponding to the key + public virtual V this[K key] + { + get { - get + KeyValuePair p = new(key, default!); + + if (pairs.Find(ref p)) + { + return p.Value; + } + else { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(key, default); - - if (pairs.Find(ref p)) - { - return p.Value; - } - else - { - throw new NoSuchItemException("Key '" + key!.ToString() + "' not present in Dictionary"); - } + throw new NoSuchItemException("Key '" + key!.ToString() + "' not present in Dictionary"); } - set => pairs.UpdateOrAdd(new System.Collections.Generic.KeyValuePair(key, value)); } + set => pairs.UpdateOrAdd(new KeyValuePair(key, value)); + } + /// + /// + /// + /// True if dictionary is read only + public virtual bool IsReadOnly => pairs.IsReadOnly; - /// - /// - /// - /// True if dictionary is read only - public virtual bool IsReadOnly => pairs.IsReadOnly; + /// + /// Check the integrity of the internal data structures of this dictionary. + /// + /// True if check does not fail. + public virtual bool Check() => pairs.Check(); + #endregion - /// - /// Check the integrity of the internal data structures of this dictionary. - /// - /// True if check does not fail. - public virtual bool Check() { return pairs.Check(); } + #region ICollectionValue> Members - #endregion - - #region ICollectionValue> Members + /// + /// + /// + /// True if this collection is empty. + public override bool IsEmpty => pairs.IsEmpty; - /// - /// - /// - /// True if this collection is empty. - public override bool IsEmpty => pairs.IsEmpty; + /// + /// + /// + /// The number of entries in the dictionary + public override int Count => pairs.Count; - /// - /// - /// - /// The number of entries in the dictionary - public override int Count => pairs.Count; + /// + /// + /// + /// The number of entries in the dictionary + public override Speed CountSpeed => pairs.CountSpeed; - /// - /// - /// - /// The number of entries in the dictionary - public override Speed CountSpeed => pairs.CountSpeed; + /// + /// Choose some entry in this Dictionary. + /// + /// if collection is empty. + /// + public override KeyValuePair Choose() { return pairs.Choose(); } - /// - /// Choose some entry in this Dictionary. - /// - /// if collection is empty. - /// - public override System.Collections.Generic.KeyValuePair Choose() { return pairs.Choose(); } - - /// - /// Create an enumerator for the collection of entries of the dictionary - /// - /// The enumerator - public override System.Collections.Generic.IEnumerator> GetEnumerator() - { - return pairs.GetEnumerator(); - } + /// + /// Create an enumerator for the collection of entries of the dictionary + /// + /// The enumerator + public override System.Collections.Generic.IEnumerator> GetEnumerator() + { + return pairs.GetEnumerator(); + } - #endregion + #endregion - /// - /// - /// - /// - /// - /// - /// - public override bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider? formatProvider) - { - return Showing.ShowDictionary(this, stringbuilder, ref rest, formatProvider); - } + /// + /// + /// + /// + /// + /// + /// + public override bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider? formatProvider) + { + return Showing.ShowDictionary(this, stringbuilder, ref rest, formatProvider); } } \ No newline at end of file diff --git a/C5/BaseClasses/DirectedCollectionBase.cs b/C5/BaseClasses/DirectedCollectionBase.cs index 47087631..8544f9f0 100644 --- a/C5/BaseClasses/DirectedCollectionBase.cs +++ b/C5/BaseClasses/DirectedCollectionBase.cs @@ -1,53 +1,55 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// +/// +/// +public abstract class DirectedCollectionBase : CollectionBase, IDirectedCollectionValue { /// - /// + /// /// - /// - public abstract class DirectedCollectionBase : CollectionBase, IDirectedCollectionValue - { - /// - /// - /// - /// - protected DirectedCollectionBase(System.Collections.Generic.IEqualityComparer itemequalityComparer) : base(itemequalityComparer) { } - /// - /// Forwards if same, else Backwards - /// - /// The enumeration direction relative to the original collection. - public virtual Direction Direction => Direction.Forwards; + /// + protected DirectedCollectionBase(System.Collections.Generic.IEqualityComparer itemequalityComparer) : base(itemequalityComparer) { } + /// + /// Forwards if same, else Backwards + /// + /// The enumeration direction relative to the original collection. + public virtual Direction Direction => Direction.Forwards; - /// - /// - /// - /// - public abstract IDirectedCollectionValue Backwards(); + /// + /// + /// + /// + public abstract IDirectedCollectionValue Backwards(); - IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } + IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } - /// - /// Check if there exists an item that satisfies a - /// specific predicate in this collection and return the first one in enumeration order. - /// - /// A delegate - /// ( with R == bool) defining the predicate - /// - /// True is such an item exists - public virtual bool FindLast(Func predicate, out T item) + /// + /// Check if there exists an item that satisfies a + /// specific predicate in this collection and return the first one in enumeration order. + /// + /// A delegate + /// ( with R == bool) defining the predicate + /// + /// True is such an item exists + public virtual bool FindLast(Func predicate, out T item) + { + foreach (T jtem in Backwards()) { - foreach (T jtem in Backwards()) + if (predicate(jtem)) { - if (predicate(jtem)) - { - item = jtem; - return true; - } + item = jtem; + return true; } - - item = default; - return false; } + + item = default; + return false; } } \ No newline at end of file diff --git a/C5/BaseClasses/DirectedCollectionValueBase.cs b/C5/BaseClasses/DirectedCollectionValueBase.cs index 3a2729ce..fac5c35e 100644 --- a/C5/BaseClasses/DirectedCollectionValueBase.cs +++ b/C5/BaseClasses/DirectedCollectionValueBase.cs @@ -1,48 +1,50 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// +/// +/// +public abstract class DirectedCollectionValueBase : CollectionValueBase, IDirectedCollectionValue { /// - /// + /// Forwards if same, else Backwards /// - /// - public abstract class DirectedCollectionValueBase : CollectionValueBase, IDirectedCollectionValue - { - /// - /// Forwards if same, else Backwards - /// - /// The enumeration direction relative to the original collection. - public virtual Direction Direction => Direction.Forwards; + /// The enumeration direction relative to the original collection. + public virtual Direction Direction => Direction.Forwards; - /// - /// - /// - /// - public abstract IDirectedCollectionValue Backwards(); + /// + /// + /// + /// + public abstract IDirectedCollectionValue Backwards(); - IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } + IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } - /// - /// Check if there exists an item that satisfies a - /// specific predicate in this collection and return the first one in enumeration order. - /// - /// A delegate - /// ( with R == bool) defining the predicate - /// - /// True is such an item exists - public virtual bool FindLast(Func predicate, out T item) + /// + /// Check if there exists an item that satisfies a + /// specific predicate in this collection and return the first one in enumeration order. + /// + /// A delegate + /// ( with R == bool) defining the predicate + /// + /// True is such an item exists + public virtual bool FindLast(Func predicate, out T item) + { + foreach (T jtem in Backwards()) { - foreach (T jtem in Backwards()) + if (predicate(jtem)) { - if (predicate(jtem)) - { - item = jtem; - return true; - } + item = jtem; + return true; } - - item = default; - return false; } + + item = default; + return false; } } \ No newline at end of file diff --git a/C5/BaseClasses/EnumerableBase.cs b/C5/BaseClasses/EnumerableBase.cs index 50614c8c..8f27739a 100644 --- a/C5/BaseClasses/EnumerableBase.cs +++ b/C5/BaseClasses/EnumerableBase.cs @@ -1,55 +1,28 @@ // This file is part of the C5 Generic Collection Library for C# and CLI // See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. -using System; +using System.Linq; using SCG = System.Collections.Generic; -namespace C5 + +namespace C5; + +/// +/// A base class for implementing an IEnumerable<T> +/// +public abstract class EnumerableBase : SCG.IEnumerable { /// - /// A base class for implementing an IEnumerable<T> + /// Create an enumerator for this collection. /// - public abstract class EnumerableBase : SCG.IEnumerable - { - /// - /// Create an enumerator for this collection. - /// - /// The enumerator - public abstract SCG.IEnumerator GetEnumerator(); - - /// - /// Count the number of items in an enumerable by enumeration - /// - /// The enumerable to count - /// The size of the enumerable - protected static int CountItems(SCG.IEnumerable items) - { - // ICollectionValue jtems = items as ICollectionValue; - - if (items is ICollectionValue jtems) - { - return jtems.Count; - } - - int count = 0; + /// The enumerator + public abstract SCG.IEnumerator GetEnumerator(); - using (SCG.IEnumerator e = items.GetEnumerator()) - { - while (e.MoveNext()) - { - count++; - } - } - - return count; - } - - #region IEnumerable Members - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + /// + /// Count the number of items in an enumerable by enumeration + /// + /// The enumerable to count + /// The size of the enumerable + protected static int CountItems(SCG.IEnumerable items) => items is ICollectionValue collectionValue ? collectionValue.Count : items.Count(); - #endregion - } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); } diff --git a/C5/BaseClasses/SequencedBase.cs b/C5/BaseClasses/SequencedBase.cs index e88764ce..639ab7c0 100644 --- a/C5/BaseClasses/SequencedBase.cs +++ b/C5/BaseClasses/SequencedBase.cs @@ -1,182 +1,181 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// Base class (abstract) for sequenced collection implementations. +/// +public abstract class SequencedBase : DirectedCollectionBase, IDirectedCollectionValue { - /// - /// Base class (abstract) for sequenced collection implementations. - /// - public abstract class SequencedBase : DirectedCollectionBase, IDirectedCollectionValue - { - #region Fields + #region Fields - private int iSequencedHashCode, iSequencedHashCodeStamp = -1; + private int iSequencedHashCode, iSequencedHashCodeStamp = -1; - #endregion + #endregion - /// - /// - /// - /// - protected SequencedBase(System.Collections.Generic.IEqualityComparer itemequalityComparer) : base(itemequalityComparer) { } + /// + /// + /// + /// + protected SequencedBase(System.Collections.Generic.IEqualityComparer itemEqualityComparer) : base(itemEqualityComparer) { } - #region Util + #region Util - //TODO: make random for release - private const int HASHFACTOR = 31; + //TODO: make random for release + private const int HashFactor = 31; - /// - /// Compute the unsequenced hash code of a collection - /// - /// The collection to compute hash code for - /// The item equalitySCG.Comparer - /// The hash code - public static int ComputeHashCode(ISequenced items, System.Collections.Generic.IEqualityComparer itemequalityComparer) + /// + /// Compute the unsequenced hash code of a collection + /// + /// The collection to compute hash code for + /// The item equalitySCG.Comparer + /// The hash code + public static int ComputeHashCode(ISequenced items, System.Collections.Generic.IEqualityComparer itemEqualityComparer) + { + // NOTE: It must be possible to devise a much stronger combined hash code, + // but unfortunately, it has to be universal. OR we could use a (strong) + // family and initialize its parameter randomly at load time of this class! + // (We would not want to have yet a flag to check for invalidation?!) + // NB: the current hash code has the very bad property that items with hash code 0 + // is ignored. + int iIndexedHashCode = 0; + + foreach (T item in items) { - //NOTE: It must be possible to devise a much stronger combined hashcode, - //but unfortunately, it has to be universal. OR we could use a (strong) - //family and initialise its parameter randomly at load time of this class! - //(We would not want to have yet a flag to check for invalidation?!) - //NBNBNB: the current hashcode has the very bad property that items with hashcode 0 - // is ignored. - int iIndexedHashCode = 0; - - foreach (T item in items) - { - iIndexedHashCode = iIndexedHashCode * HASHFACTOR + itemequalityComparer.GetHashCode(item); - } + iIndexedHashCode = iIndexedHashCode * HashFactor + itemEqualityComparer.GetHashCode(item); + } - return iIndexedHashCode; + return iIndexedHashCode; + } + + /// + /// Examine if tit and tat are equal as sequenced collections + /// using the specified item equalityComparer (assumed compatible with the two collections). + /// + /// The first collection + /// The second collection + /// The item equalityComparer to use for comparison + /// True if equal + public static bool StaticEquals(ISequenced collection1, ISequenced collection2, System.Collections.Generic.IEqualityComparer itemEqualityComparer) + { + if (ReferenceEquals(collection1, collection2)) + { + return true; } + if (collection1.Count != collection2.Count) + { + return false; + } - /// - /// Examine if tit and tat are equal as sequenced collections - /// using the specified item equalityComparer (assumed compatible with the two collections). - /// - /// The first collection - /// The second collection - /// The item equalityComparer to use for comparison - /// True if equal - public static bool StaticEquals(ISequenced collection1, ISequenced collection2, System.Collections.Generic.IEqualityComparer itemequalityComparer) + //This way we might run through both enumerations twice, but + //probably not (if the hash codes are good) + if (collection1.GetSequencedHashCode() != collection2.GetSequencedHashCode()) { - if (object.ReferenceEquals(collection1, collection2)) - { - return true; - } + return false; + } - if (collection1.Count != collection2.Count) - { - return false; - } + using System.Collections.Generic.IEnumerator dat = collection2.GetEnumerator(), dit = collection1.GetEnumerator(); - //This way we might run through both enumerations twice, but - //probably not (if the hash codes are good) - if (collection1.GetSequencedHashCode() != collection2.GetSequencedHashCode()) + while (dit.MoveNext()) + { + dat.MoveNext(); + if (!itemEqualityComparer.Equals(dit.Current, dat.Current)) { return false; } - - using (System.Collections.Generic.IEnumerator dat = collection2.GetEnumerator(), dit = collection1.GetEnumerator()) - { - while (dit.MoveNext()) - { - dat.MoveNext(); - if (!itemequalityComparer.Equals(dit.Current, dat.Current)) - { - return false; - } - } - } - - return true; } + return true; + } - /// - /// Get the sequenced collection hash code of this collection: from the cached - /// value if present and up to date, else (re)compute. - /// - /// The hash code - public virtual int GetSequencedHashCode() + /// + /// Get the sequenced collection hash code of this collection: from the cached + /// value if present and up to date, else (re)compute. + /// + /// The hash code + public virtual int GetSequencedHashCode() + { + if (iSequencedHashCodeStamp == stamp) { - if (iSequencedHashCodeStamp == stamp) - { - return iSequencedHashCode; - } - - iSequencedHashCode = ComputeHashCode((ISequenced)this, itemequalityComparer); - iSequencedHashCodeStamp = stamp; return iSequencedHashCode; } + iSequencedHashCode = ComputeHashCode((ISequenced)this, itemEqualityComparer); + iSequencedHashCodeStamp = stamp; + return iSequencedHashCode; + } - /// - /// Check if the contents of that is equal to the contents of this - /// in the sequenced sense. Using the item equalityComparer of this collection. - /// - /// The collection to compare to. - /// True if equal - public virtual bool SequencedEquals(ISequenced otherCollection) - { - return StaticEquals((ISequenced)this, otherCollection, itemequalityComparer); - } + /// + /// Check if the contents of that is equal to the contents of this + /// in the sequenced sense. Using the item equalityComparer of this collection. + /// + /// The collection to compare to. + /// True if equal + public virtual bool SequencedEquals(ISequenced otherCollection) + { + return StaticEquals((ISequenced)this, otherCollection, itemEqualityComparer); + } - #endregion - /// - /// Create an enumerator for this collection. - /// - /// The enumerator - public abstract override System.Collections.Generic.IEnumerator GetEnumerator(); + #endregion - /// - /// Forwards if same, else Backwards - /// - /// The enumeration direction relative to the original collection. - public override Direction Direction => Direction.Forwards; + /// + /// Create an enumerator for this collection. + /// + /// The enumerator + public abstract override System.Collections.Generic.IEnumerator GetEnumerator(); - /// - /// Check if there exists an item that satisfies a - /// specific predicate in this collection and return the index of the first one. - /// - /// A delegate defining the predicate - /// the index, if found, a negative value else - public int FindIndex(Func predicate) + /// + /// Forwards if same, else Backwards + /// + /// The enumeration direction relative to the original collection. + public override Direction Direction => Direction.Forwards; + + /// + /// Check if there exists an item that satisfies a + /// specific predicate in this collection and return the index of the first one. + /// + /// A delegate defining the predicate + /// the index, if found, a negative value else + public int FindIndex(Func predicate) + { + int index = 0; + foreach (T item in this) { - int index = 0; - foreach (T item in this) + if (predicate(item)) { - if (predicate(item)) - { - return index; - } - - index++; + return index; } - return -1; + + index++; } + return -1; + } - /// - /// Check if there exists an item that satisfies a - /// specific predicate in this collection and return the index of the last one. - /// - /// A delegate defining the predicate - /// the index, if found, a negative value else - public int FindLastIndex(Func predicate) + /// + /// Check if there exists an item that satisfies a + /// specific predicate in this collection and return the index of the last one. + /// + /// A delegate defining the predicate + /// the index, if found, a negative value else + public int FindLastIndex(Func predicate) + { + int index = Count - 1; + foreach (T item in Backwards()) { - int index = Count - 1; - foreach (T item in Backwards()) + if (predicate(item)) { - if (predicate(item)) - { - return index; - } - - index--; + return index; } - return -1; - } + index--; + } + return -1; } + } \ No newline at end of file diff --git a/C5/C5.csproj b/C5/C5.csproj index 609ff422..d678e9b6 100644 --- a/C5/C5.csproj +++ b/C5/C5.csproj @@ -1,9 +1,9 @@  - netstandard2.0;net6.0;net8.0 + netstandard2.0;net8.0 enable latest - 3.0.0 + 3.1.0 Copyright © Niels Kokholm, Peter Sestoft, and Rasmus Lystrøm 2003-2024 Niels Kokholm, Peter Sestoft, and Rasmus Lystrøm The C5 Generic Collection Library for C# and CLI is a comprehensive collection library supporting lists, sets, bags, dictionaries, priority queues, (FIFO) queues, and (LIFO) stacks. C5 runs on everything supporting .NET Standard 2.0: .NET Core 2.0+, .NET 4.6.1+, Mono, Xamarin, Universal Windows Platform, and Unity. @@ -15,15 +15,9 @@ README.md type removed. - - Breaking change: All public readonly fields are now properties. - - Breaking change: EventTypeEnum is now EventType. - - Breaking change: custom KeyValuePair has been replaced by the standard System.Collections.Generic.KeyValue for better compatibility. - - Breaking change: EnumerationDirection is now Direction. - - Breaking change: Serializable attribute removed. + - C5 now targets .NET Standard 2.0 and .NET 8.0. ]]> true @@ -35,7 +29,7 @@ bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml - + diff --git a/C5/C5Random.cs b/C5/C5Random.cs index b5e2a15a..9c6670f8 100644 --- a/C5/C5Random.cs +++ b/C5/C5Random.cs @@ -2,165 +2,165 @@ // See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. using System; -namespace C5 + +namespace C5; + +/// +/// A modern random number generator based on G. Marsaglia: +/// Seeds for Random Number Generators, Communications of the +/// ACM 46, 5 (May 2003) 90-93; and a posting by Marsaglia to +/// comp.lang.c on 2003-04-03. +/// +public class C5Random : Random { - /// - /// A modern random number generator based on G. Marsaglia: - /// Seeds for Random Number Generators, Communications of the - /// ACM 46, 5 (May 2003) 90-93; and a posting by Marsaglia to - /// comp.lang.c on 2003-04-03. - /// - public class C5Random : Random - { - private readonly uint[] Q = new uint[16]; + private readonly uint[] Q = new uint[16]; - private uint c = 362436, i = 15; + private uint c = 362436, i = 15; - private uint Cmwc() + private uint Cmwc() + { + ulong t, a = 487198574UL; + uint x, r = 0xfffffffe; + + i = (i + 1) & 15; + t = a * Q[i] + c; + c = (uint)(t >> 32); + x = (uint)(t + c); + if (x < c) { - ulong t, a = 487198574UL; - uint x, r = 0xfffffffe; - - i = (i + 1) & 15; - t = a * Q[i] + c; - c = (uint)(t >> 32); - x = (uint)(t + c); - if (x < c) - { - x++; - c++; - } - - return Q[i] = r - x; + x++; + c++; } + return Q[i] = r - x; + } + - /// - /// Get a new random System.Double value - /// - /// The random double - public override double NextDouble() - { - return Cmwc() / 4294967296.0; - } + /// + /// Get a new random System.Double value + /// + /// The random double + public override double NextDouble() + { + return Cmwc() / 4294967296.0; + } - /// - /// Get a new random System.Double value - /// - /// The random double - protected override double Sample() + /// + /// Get a new random System.Double value + /// + /// The random double + protected override double Sample() + { + return NextDouble(); + } + + + /// + /// Get a new random System.Int32 value + /// + /// The random int + public override int Next() + { + return (int)Cmwc(); + } + + + /// + /// Get a random non-negative integer less than a given upper bound + /// + /// If max is negative + /// The upper bound (exclusive) + /// + public override int Next(int max) + { + if (max < 0) { - return NextDouble(); + throw new ArgumentException("max must be non-negative"); } + return (int)(Cmwc() / 4294967296.0 * max); + } + - /// - /// Get a new random System.Int32 value - /// - /// The random int - public override int Next() + /// + /// Get a random integer between two given bounds + /// + /// If max is less than min + /// The lower bound (inclusive) + /// The upper bound (exclusive) + /// + public override int Next(int min, int max) + { + if (min > max) { - return (int)Cmwc(); + throw new ArgumentException("min must be less than or equal to max"); } + return min + (int)(Cmwc() / 4294967296.0 * (max - min)); + } - /// - /// Get a random non-negative integer less than a given upper bound - /// - /// If max is negative - /// The upper bound (exclusive) - /// - public override int Next(int max) + /// + /// Fill a array of byte with random bytes + /// + /// The array to fill + public override void NextBytes(byte[] buffer) + { + for (int i = 0, length = buffer.Length; i < length; i++) { - if (max < 0) - { - throw new ArgumentException("max must be non-negative"); - } - - return (int)(Cmwc() / 4294967296.0 * max); + buffer[i] = (byte)Cmwc(); } + } - /// - /// Get a random integer between two given bounds - /// - /// If max is less than min - /// The lower bound (inclusive) - /// The upper bound (exclusive) - /// - public override int Next(int min, int max) - { - if (min > max) - { - throw new ArgumentException("min must be less than or equal to max"); - } + /// + /// Create a random number generator seed by system time. + /// + public C5Random() + : this(DateTime.Now.Ticks) + { + } - return min + (int)(Cmwc() / 4294967296.0 * (max - min)); - } - /// - /// Fill a array of byte with random bytes - /// - /// The array to fill - public override void NextBytes(byte[] buffer) + /// + /// Create a random number generator with a given seed + /// + /// If seed is zero + /// The seed + public C5Random(long seed) + { + if (seed == 0) { - for (int i = 0, length = buffer.Length; i < length; i++) - { - buffer[i] = (byte)Cmwc(); - } + throw new ArgumentException("Seed must be non-zero"); } + uint j = (uint)(seed & 0xFFFFFFFF); - /// - /// Create a random number generator seed by system time. - /// - public C5Random() - : this(DateTime.Now.Ticks) + for (int i = 0; i < 16; i++) { + j ^= j << 13; + j ^= j >> 17; + j ^= j << 5; + Q[i] = j; } + Q[15] = (uint)(seed ^ (seed >> 32)); + } - /// - /// Create a random number generator with a given seed - /// - /// If seed is zero - /// The seed - public C5Random(long seed) + /// + /// Create a random number generator with a specified internal start state. + /// + /// If Q is not of length exactly 16 + /// The start state. Must be a collection of random bits given by an array of exactly 16 uints. + [CLSCompliant(false)] + public C5Random(uint[] Q) + { + if (Q.Length != 16) { - if (seed == 0) - { - throw new ArgumentException("Seed must be non-zero"); - } - - uint j = (uint)(seed & 0xFFFFFFFF); - - for (int i = 0; i < 16; i++) - { - j ^= j << 13; - j ^= j >> 17; - j ^= j << 5; - Q[i] = j; - } - - Q[15] = (uint)(seed ^ (seed >> 32)); + throw new ArgumentException("Q must have length 16, was " + Q.Length); } - /// - /// Create a random number generator with a specified internal start state. - /// - /// If Q is not of length exactly 16 - /// The start state. Must be a collection of random bits given by an array of exactly 16 uints. - [CLSCompliant(false)] - public C5Random(uint[] Q) - { - if (Q.Length != 16) - { - throw new ArgumentException("Q must have length 16, was " + Q.Length); - } - - Array.Copy(Q, this.Q, 16); - } + Array.Copy(Q, this.Q, 16); } } \ No newline at end of file diff --git a/C5/Comparers/ComparerZeroHashCodeEqualityComparer.cs b/C5/Comparers/ComparerZeroHashCodeEqualityComparer.cs index 4e7be8b2..b4d3b5fe 100644 --- a/C5/Comparers/ComparerZeroHashCodeEqualityComparer.cs +++ b/C5/Comparers/ComparerZeroHashCodeEqualityComparer.cs @@ -4,38 +4,42 @@ using System; using SCG = System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// An equalityComparer compatible with a given comparer. All hash codes are 0, +/// meaning that anything based on hash codes will be quite inefficient. +/// Note: this will give a new EqualityComparer each time created! +/// +/// +/// +/// Create a trivial compatible with the +/// comparer +/// +/// +internal class ComparerZeroHashCodeEqualityComparer(SCG.IComparer comparer) : SCG.IEqualityComparer { + private readonly SCG.IComparer comparer = comparer; + + /// + /// A trivial, inefficient hash function. Compatible with any equality relation. + /// + /// + /// 0 + public int GetHashCode(T item) => 0; + /// - /// An equalityComparer compatible with a given comparer. All hash codes are 0, - /// meaning that anything based on hash codes will be quite inefficient. - /// Note: this will give a new EqualityComparer each time created! + /// Equality of two items as defined by the comparer. /// - /// - internal class ComparerZeroHashCodeEqualityComparer : SCG.IEqualityComparer + /// + /// + /// + public bool Equals(T? item1, T? item2) { - private readonly SCG.IComparer comparer; - /// - /// Create a trivial compatible with the - /// comparer - /// - /// - public ComparerZeroHashCodeEqualityComparer(SCG.IComparer comparer) - { - this.comparer = comparer ?? throw new NullReferenceException("Comparer cannot be null"); - } - /// - /// A trivial, inefficient hash function. Compatible with any equality relation. - /// - /// - /// 0 - public int GetHashCode(T item) { return 0; } - /// - /// Equality of two items as defined by the comparer. - /// - /// - /// - /// - public bool Equals(T item1, T item2) { return comparer.Compare(item1, item2) == 0; } + if (item1 is null && item2 is null) return true; + if (item1 is null) return false; + if (item2 is null) return false; + + return comparer.Compare(item1, item2) == 0; } } diff --git a/C5/Comparers/EqualityComparer.cs b/C5/Comparers/EqualityComparer.cs index 26dbd2ed..8cd09712 100644 --- a/C5/Comparers/EqualityComparer.cs +++ b/C5/Comparers/EqualityComparer.cs @@ -6,74 +6,73 @@ using System.Reflection; using SCG = System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// Utility class for building default generic equality comparers. +/// +/// +public static class EqualityComparer { - /// - /// Utility class for building default generic equality comparers. - /// - /// - public static class EqualityComparer - { - private static SCG.IEqualityComparer _default; + private static SCG.IEqualityComparer? _default; - private static readonly Type SequencedCollectionEqualityComparer = typeof(SequencedCollectionEqualityComparer<,>); + private static readonly Type SequencedCollectionEqualityComparer = typeof(SequencedCollectionEqualityComparer<,>); - private static readonly Type UnsequencedCollectionEqualityComparer = typeof(UnsequencedCollectionEqualityComparer<,>); + private static readonly Type UnsequencedCollectionEqualityComparer = typeof(UnsequencedCollectionEqualityComparer<,>); - /// - /// A default generic equality comparer for type T. The procedure is as follows: - /// - /// If the actual generic argument T implements the generic interface - /// for some value W of its generic parameter T, - /// the equality comparer will be - /// If the actual generic argument T implements - /// for some value W of its generic parameter T, - /// the equality comparer will be - /// Otherwise the SCG.EqualityComparer<T>.Default is returned - /// - /// - /// The comparer - public static SCG.IEqualityComparer Default + /// + /// A default generic equality comparer for type T. The procedure is as follows: + /// + /// If the actual generic argument T implements the generic interface + /// for some value W of its generic parameter T, + /// the equality comparer will be + /// If the actual generic argument T implements + /// for some value W of its generic parameter T, + /// the equality comparer will be + /// Otherwise the SCG.EqualityComparer<T>.Default is returned + /// + /// + /// The comparer + public static SCG.IEqualityComparer Default + { + get { - get + if (_default != null) { - if (_default != null) - { - return _default; - } - - var type = typeof(T); - var interfaces = type.GetTypeInfo().GetInterfaces(); + return _default; + } - if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(ISequenced<>))) - { - return CreateAndCache(SequencedCollectionEqualityComparer.MakeGenericType(new[] { type, type.GetTypeInfo().GetGenericArguments()[0] })); - } + var type = typeof(T); + var interfaces = type.GetTypeInfo().GetInterfaces(); - var isequenced = interfaces.FirstOrDefault(i => i.GetTypeInfo().IsGenericType && i.GetGenericTypeDefinition().Equals(typeof(ISequenced<>))); - if (isequenced != null) - { - return CreateAndCache(SequencedCollectionEqualityComparer.MakeGenericType(new[] { type, isequenced.GetTypeInfo().GetGenericArguments()[0] })); - } + if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(ISequenced<>))) + { + return CreateAndCache(SequencedCollectionEqualityComparer.MakeGenericType([type, type.GetTypeInfo().GetGenericArguments()[0]])); + } - if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(ICollection<>))) - { - return CreateAndCache(UnsequencedCollectionEqualityComparer.MakeGenericType(new[] { type, type.GetTypeInfo().GetGenericArguments()[0] })); - } + var isequenced = interfaces.FirstOrDefault(i => i.GetTypeInfo().IsGenericType && i.GetGenericTypeDefinition().Equals(typeof(ISequenced<>))); + if (isequenced != null) + { + return CreateAndCache(SequencedCollectionEqualityComparer.MakeGenericType([type, isequenced.GetTypeInfo().GetGenericArguments()[0]])); + } - var icollection = interfaces.FirstOrDefault(i => i.GetTypeInfo().IsGenericType && i.GetGenericTypeDefinition().Equals(typeof(ICollection<>))); - if (icollection != null) - { - return CreateAndCache(UnsequencedCollectionEqualityComparer.MakeGenericType(new[] { type, icollection.GetTypeInfo().GetGenericArguments()[0] })); - } + if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(ICollection<>))) + { + return CreateAndCache(UnsequencedCollectionEqualityComparer.MakeGenericType([type, type.GetTypeInfo().GetGenericArguments()[0]])); + } - return _default = SCG.EqualityComparer.Default; + var icollection = interfaces.FirstOrDefault(i => i.GetTypeInfo().IsGenericType && i.GetGenericTypeDefinition().Equals(typeof(ICollection<>))); + if (icollection != null) + { + return CreateAndCache(UnsequencedCollectionEqualityComparer.MakeGenericType([type, icollection.GetTypeInfo().GetGenericArguments()[0]])); } - } - private static SCG.IEqualityComparer CreateAndCache(Type equalityComparertype) - { - return _default = (SCG.IEqualityComparer)(equalityComparertype.GetTypeInfo().GetProperty("Default", BindingFlags.Static | BindingFlags.Public).GetValue(null, null)); + return _default = SCG.EqualityComparer.Default; } } + + private static SCG.IEqualityComparer CreateAndCache(Type equalityComparertype) + { + return _default = (SCG.IEqualityComparer)(equalityComparertype.GetTypeInfo().GetProperty("Default", BindingFlags.Static | BindingFlags.Public)!.GetValue(null, null))!; + } } diff --git a/C5/Comparers/InternalComparer.cs b/C5/Comparers/InternalComparer.cs index 14717c0e..ed50b3f4 100644 --- a/C5/Comparers/InternalComparer.cs +++ b/C5/Comparers/InternalComparer.cs @@ -4,35 +4,38 @@ using System; using System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// Defines a method that a type implements to compare two objects. +/// This class is intentionally declared internal - use the ComparerFactory to create an instance. +/// +/// The type of objects to compare. +internal class InternalComparer : IComparer { + private readonly Func _compare; + /// - /// Defines a method that a type implements to compare two objects. - /// This class is intentionally declared internal - use the ComparerFactory to create an instance. + /// Constructs a comparer using one Func delegate. /// - /// The type of objects to compare. - internal class InternalComparer : IComparer + /// The compare function. + public InternalComparer(Func compare) { - private readonly Func _compare; + _compare = compare; + } - /// - /// Constructs a comparer using one Func delegate. - /// - /// The compare function. - public InternalComparer(Func compare) - { - _compare = compare; - } + /// + /// Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other. + /// + /// The first object to compare. + /// The second object to compare. + /// A signed integer that indicates the relative values of x and y, as shown in the following table. Value Condition Less than zero x is less than y. Zero x equals y. Greater than zero x is greater than y. + public int Compare(T? x, T? y) + { + if (x is null && y is null) return 0; + if (x is null) return -1; + if (y is null) return 1; - /// - /// Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other. - /// - /// The first object to compare. - /// The second object to compare. - /// A signed integer that indicates the relative values of x and y, as shown in the following table. Value Condition Less than zero x is less than y. Zero x equals y. Greater than zero x is greater than y. - public int Compare(T x, T y) - { - return _compare(x, y); - } + return _compare(x, y); } } \ No newline at end of file diff --git a/C5/Comparers/InternalEqualityComparer.cs b/C5/Comparers/InternalEqualityComparer.cs index 93034ba7..1be3494e 100644 --- a/C5/Comparers/InternalEqualityComparer.cs +++ b/C5/Comparers/InternalEqualityComparer.cs @@ -4,48 +4,51 @@ using System; using System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// Defines methods to support the comparison of objects for equality. +/// This class is intentionally declared internal - use the ComparerFactory to create an instance. +/// +/// The type of objects to compare. +internal class InternalEqualityComparer : IEqualityComparer { + private readonly Func _equals; + private readonly Func _getHashCode; + /// - /// Defines methods to support the comparison of objects for equality. - /// This class is intentionally declared internal - use the ComparerFactory to create an instance. + /// Constructs and equality comparer using two Func delegates. /// - /// The type of objects to compare. - internal class InternalEqualityComparer : IEqualityComparer + /// The equals function. + /// The get hash code function. + public InternalEqualityComparer(Func equals, Func getHashCode) { - private readonly Func _equals; - private readonly Func _getHashCode; + _equals = equals; + _getHashCode = getHashCode; + } - /// - /// Constructs and equality comparer using two Func delegates. - /// - /// The equals function. - /// The get hash code function. - public InternalEqualityComparer(Func equals, Func getHashCode) - { - _equals = equals; - _getHashCode = getHashCode; - } + /// + /// Determines whether the specified objects are equal. + /// + /// The first object of type T to compare. + /// The second object of type T to compare. + /// true if the specified objects are equal; otherwise, false. + public bool Equals(T? x, T? y) + { + if (x is null && y is null) return true; + if (x is null) return false; + if (y is null) return false; - /// - /// Determines whether the specified objects are equal. - /// - /// The first object of type T to compare. - /// The second object of type T to compare. - /// true if the specified objects are equal; otherwise, false. - public bool Equals(T x, T y) - { - return _equals(x, y); - } + return _equals(x, y); + } - /// - /// Returns a hash code for the specified object. - /// - /// The System.Object for which a hash code is to be returned. - /// A hash code for the specified object. - public int GetHashCode(T obj) - { - return _getHashCode(obj); - } + /// + /// Returns a hash code for the specified object. + /// + /// The System.Object for which a hash code is to be returned. + /// A hash code for the specified object. + public int GetHashCode(T obj) + { + return _getHashCode(obj); } } \ No newline at end of file diff --git a/C5/Comparers/KeyValuePairComparer.cs b/C5/Comparers/KeyValuePairComparer.cs index 37851fd5..d773f0f5 100644 --- a/C5/Comparers/KeyValuePairComparer.cs +++ b/C5/Comparers/KeyValuePairComparer.cs @@ -1,36 +1,35 @@ using System; using System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// Default comparer for dictionary entries in a sorted dictionary. +/// Entry comparisons only look at keys and uses an externally defined comparer for that. +/// +public class KeyValuePairComparer : IComparer> { + private readonly System.Collections.Generic.IComparer comparer; + + /// - /// Default comparer for dictionary entries in a sorted dictionary. - /// Entry comparisons only look at keys and uses an externally defined comparer for that. + /// Create an entry comparer for a item comparer of the keys /// - public class KeyValuePairComparer : IComparer> + /// Comparer of keys + public KeyValuePairComparer(System.Collections.Generic.IComparer comparer) { - private readonly System.Collections.Generic.IComparer comparer; - - - /// - /// Create an entry comparer for a item comparer of the keys - /// - /// Comparer of keys - public KeyValuePairComparer(System.Collections.Generic.IComparer comparer) - { - this.comparer = comparer ?? throw new NullReferenceException(); - } + this.comparer = comparer ?? throw new NullReferenceException(); + } - /// - /// Compare two entries - /// - /// First entry - /// Second entry - /// The result of comparing the keys - public int Compare(System.Collections.Generic.KeyValuePair entry1, System.Collections.Generic.KeyValuePair entry2) - { - return comparer.Compare(entry1.Key, entry2.Key); - } + /// + /// Compare two entries + /// + /// First entry + /// Second entry + /// The result of comparing the keys + public int Compare(System.Collections.Generic.KeyValuePair entry1, System.Collections.Generic.KeyValuePair entry2) + { + return comparer.Compare(entry1.Key, entry2.Key); } } \ No newline at end of file diff --git a/C5/Comparers/KeyValuePairEqualityComparer.cs b/C5/Comparers/KeyValuePairEqualityComparer.cs index d90b1cbe..e262b620 100644 --- a/C5/Comparers/KeyValuePairEqualityComparer.cs +++ b/C5/Comparers/KeyValuePairEqualityComparer.cs @@ -1,50 +1,45 @@ using System; -using System.Collections.Generic; +using SCG = System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// Default equalityComparer for dictionary entries. +/// Operations only look at keys and uses an externally defined equalityComparer for that. +/// +public sealed class KeyValuePairEqualityComparer : SCG.IEqualityComparer> { + private readonly SCG.IEqualityComparer _keyEqualityComparer; + /// - /// Default equalityComparer for dictionary entries. - /// Operations only look at keys and uses an externally defined equalityComparer for that. + /// Create an entry equalityComparer using the default equalityComparer for keys /// - public sealed class KeyValuePairEqualityComparer : IEqualityComparer> - { - private readonly System.Collections.Generic.IEqualityComparer keyequalityComparer; - - - /// - /// Create an entry equalityComparer using the default equalityComparer for keys - /// - public KeyValuePairEqualityComparer() { keyequalityComparer = EqualityComparer.Default; } + public KeyValuePairEqualityComparer() { _keyEqualityComparer = EqualityComparer.Default; } + /// + /// Create an entry equalityComparer from a specified item equalityComparer for the keys + /// + /// The key equalitySCG.Comparer + public KeyValuePairEqualityComparer(SCG.IEqualityComparer keyEqualityComparer) + { + _keyEqualityComparer = keyEqualityComparer ?? throw new NullReferenceException("Key equality comparer cannot be null"); + } - /// - /// Create an entry equalityComparer from a specified item equalityComparer for the keys - /// - /// The key equalitySCG.Comparer - public KeyValuePairEqualityComparer(System.Collections.Generic.IEqualityComparer keyequalityComparer) - { - this.keyequalityComparer = keyequalityComparer ?? throw new NullReferenceException("Key equality comparer cannot be null"); - } - - - /// - /// Get the hash code of the entry - /// - /// The entry - /// The hash code of the key - public int GetHashCode(System.Collections.Generic.KeyValuePair entry) { return keyequalityComparer.GetHashCode(entry.Key); } - + /// + /// Get the hash code of the entry + /// + /// The entry + /// The hash code of the key + public int GetHashCode(SCG.KeyValuePair entry) { return _keyEqualityComparer.GetHashCode(entry.Key); } - /// - /// Test two entries for equality - /// - /// First entry - /// Second entry - /// True if keys are equal - public bool Equals(System.Collections.Generic.KeyValuePair entry1, System.Collections.Generic.KeyValuePair entry2) - { - return keyequalityComparer.Equals(entry1.Key, entry2.Key); - } + /// + /// Test two entries for equality + /// + /// First entry + /// Second entry + /// True if keys are equal + public bool Equals(SCG.KeyValuePair entry1, SCG.KeyValuePair entry2) + { + return _keyEqualityComparer.Equals(entry1.Key, entry2.Key); } } \ No newline at end of file diff --git a/C5/Comparers/SequencedCollectionEqualityComparer.cs b/C5/Comparers/SequencedCollectionEqualityComparer.cs index 304bb2b1..e045905f 100644 --- a/C5/Comparers/SequencedCollectionEqualityComparer.cs +++ b/C5/Comparers/SequencedCollectionEqualityComparer.cs @@ -1,38 +1,46 @@ -using System; -using System.Collections.Generic; +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. -namespace C5 +using SCG = System.Collections.Generic; + +namespace C5; + +/// +/// Prototype for a sequenced equalityComparer for something (T) that implements ISequenced[W]. +/// This will use ISequenced[W] specific implementations of the equality comparer operations. +/// +/// +/// +public class SequencedCollectionEqualityComparer : SCG.IEqualityComparer + where T : ISequenced { + private static SequencedCollectionEqualityComparer? _cached; + + private SequencedCollectionEqualityComparer() { } /// - /// Prototype for a sequenced equalityComparer for something (T) that implements ISequenced[W]. - /// This will use ISequenced[W] specific implementations of the equality comparer operations. + /// /// - /// - /// - public class SequencedCollectionEqualityComparer : IEqualityComparer - where T : ISequenced - { - private static SequencedCollectionEqualityComparer cached; + /// + public static SequencedCollectionEqualityComparer Default => _cached ??= new SequencedCollectionEqualityComparer(); + /// + /// Get the hash code with respect to this sequenced equalityComparer + /// + /// The collection + /// The hash code + public int GetHashCode(T collection) { return collection.GetSequencedHashCode(); } - private SequencedCollectionEqualityComparer() { } - /// - /// - /// - /// - public static SequencedCollectionEqualityComparer Default => cached ??= new SequencedCollectionEqualityComparer(); - /// - /// Get the hash code with respect to this sequenced equalityComparer - /// - /// The collection - /// The hash code - public int GetHashCode(T collection) { return collection.GetSequencedHashCode(); } + /// + /// Check if two items are equal with respect to this sequenced equalityComparer + /// + /// first collection + /// second collection + /// True if equal + public bool Equals(T? collection1, T? collection2) + { + if (collection1 == null && collection2 == null) return true; + if (collection1 == null) return false; + if (collection2 == null) return false; - /// - /// Check if two items are equal with respect to this sequenced equalityComparer - /// - /// first collection - /// second collection - /// True if equal - public bool Equals(T collection1, T collection2) { return collection1 == null ? collection2 == null : collection1.SequencedEquals(collection2); } + return collection1.SequencedEquals(collection2); } } \ No newline at end of file diff --git a/C5/Comparers/UnsequencedCollectionEqualityComparer.cs b/C5/Comparers/UnsequencedCollectionEqualityComparer.cs index 09fe8174..73882d84 100644 --- a/C5/Comparers/UnsequencedCollectionEqualityComparer.cs +++ b/C5/Comparers/UnsequencedCollectionEqualityComparer.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using SCG = System.Collections.Generic; namespace C5 { @@ -9,17 +8,17 @@ namespace C5 /// /// /// - public class UnsequencedCollectionEqualityComparer : IEqualityComparer + public class UnsequencedCollectionEqualityComparer : SCG.IEqualityComparer where T : ICollection { - private static UnsequencedCollectionEqualityComparer cached; + private static UnsequencedCollectionEqualityComparer? _cached; private UnsequencedCollectionEqualityComparer() { } /// /// /// /// - public static UnsequencedCollectionEqualityComparer Default => cached ??= new UnsequencedCollectionEqualityComparer(); + public static UnsequencedCollectionEqualityComparer Default => _cached ??= new UnsequencedCollectionEqualityComparer(); /// /// Get the hash code with respect to this unsequenced equalityComparer /// @@ -34,6 +33,13 @@ private UnsequencedCollectionEqualityComparer() { } /// first collection /// second collection /// True if equal - public bool Equals(T collection1, T collection2) { return collection1 == null ? collection2 == null : collection1.UnsequencedEquals(collection2); } + public bool Equals(T? collection1, T? collection2) + { + if (collection1 == null && collection2 == null) return true; + if (collection1 == null) return false; + if (collection2 == null) return false; + + return collection1.UnsequencedEquals(collection2); + } } } \ No newline at end of file diff --git a/C5/Debug.cs b/C5/Debug.cs index dee402bc..5c7ad94d 100644 --- a/C5/Debug.cs +++ b/C5/Debug.cs @@ -1,18 +1,15 @@ // This file is part of the C5 Generic Collection Library for C# and CLI // See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. -using System; +namespace C5; -namespace C5 +/// +/// Class containing debugging symbols - to eliminate preprocessor directives +/// +internal class Debug { /// - /// Class containing debugging symbols - to eliminate preprocessor directives + /// Flag used to test hashing. Set to true when unit testing hash functions. /// - internal class Debug - { - /// - /// Flag used to test hashing. Set to true when unit testing hash functions. - /// - internal static bool UseDeterministicHashing { get; set; } - } + internal static bool UseDeterministicHashing { get; set; } } diff --git a/C5/Dictionaries/SortedArrayDictionary.cs b/C5/Dictionaries/SortedArrayDictionary.cs index f55dd44e..dcdae524 100644 --- a/C5/Dictionaries/SortedArrayDictionary.cs +++ b/C5/Dictionaries/SortedArrayDictionary.cs @@ -1,41 +1,38 @@ -using System; +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. -namespace C5 -{ - internal class SortedArrayDictionary : SortedDictionaryBase - { - #region Constructors +namespace C5; - public SortedArrayDictionary() : this(System.Collections.Generic.Comparer.Default, EqualityComparer.Default) { } +internal class SortedArrayDictionary : SortedDictionaryBase +{ + public SortedArrayDictionary() : this(System.Collections.Generic.Comparer.Default, EqualityComparer.Default) { } - /// - /// Create a red-black tree dictionary using an external comparer for keys. - /// - /// The external comparer - public SortedArrayDictionary(System.Collections.Generic.IComparer comparer) : this(comparer, new ComparerZeroHashCodeEqualityComparer(comparer)) { } + /// + /// Create a red-black tree dictionary using an external comparer for keys. + /// + /// The external comparer + public SortedArrayDictionary(System.Collections.Generic.IComparer comparer) : this(comparer, new ComparerZeroHashCodeEqualityComparer(comparer)) { } - /// - /// - /// - /// - /// - public SortedArrayDictionary(System.Collections.Generic.IComparer comparer, System.Collections.Generic.IEqualityComparer equalityComparer) - : base(comparer, equalityComparer) - { - pairs = sortedpairs = new SortedArray>(new KeyValuePairComparer(comparer)); - } + /// + /// + /// + /// + /// + public SortedArrayDictionary(System.Collections.Generic.IComparer comparer, System.Collections.Generic.IEqualityComparer equalityComparer) + : base(comparer, equalityComparer) + { + pairs = sortedPairs = new SortedArray>(new KeyValuePairComparer(comparer)); + } - /// - /// - /// - /// - /// - /// - public SortedArrayDictionary(int capacity, System.Collections.Generic.IComparer comparer, System.Collections.Generic.IEqualityComparer equalityComparer) - : base(comparer, equalityComparer) - { - pairs = sortedpairs = new SortedArray>(capacity, new KeyValuePairComparer(comparer)); - } - #endregion + /// + /// + /// + /// + /// + /// + public SortedArrayDictionary(int capacity, System.Collections.Generic.IComparer comparer, System.Collections.Generic.IEqualityComparer equalityComparer) + : base(comparer, equalityComparer) + { + pairs = sortedPairs = new SortedArray>(capacity, new KeyValuePairComparer(comparer)); } } \ No newline at end of file diff --git a/C5/Dictionaries/SortedDictionaryBase.cs b/C5/Dictionaries/SortedDictionaryBase.cs index c38c6891..676dbbe2 100644 --- a/C5/Dictionaries/SortedDictionaryBase.cs +++ b/C5/Dictionaries/SortedDictionaryBase.cs @@ -3,533 +3,526 @@ using System; using SCG = System.Collections.Generic; -namespace C5 + +namespace C5; + +/// +/// A base class for implementing a sorted dictionary based on a sorted set collection implementation. +/// See the source code for for an example +/// +public abstract class SortedDictionaryBase : DictionaryBase, ISortedDictionary { + #region Fields + /// - /// A base class for implementing a sorted dictionary based on a sorted set collection implementation. - /// See the source code for for an example /// /// - public abstract class SortedDictionaryBase : DictionaryBase, ISortedDictionary - { - #region Fields + protected ISorted> sortedPairs; + private readonly SCG.IComparer keyComparer; - /// - /// - /// - protected ISorted> sortedpairs; - private readonly SCG.IComparer keycomparer; + /// + /// + /// + /// + /// + protected SortedDictionaryBase(SCG.IComparer keyComparer, SCG.IEqualityComparer keyequalityComparer) : base(keyequalityComparer) { this.keyComparer = keyComparer; } - /// - /// - /// - /// - /// - protected SortedDictionaryBase(SCG.IComparer keycomparer, SCG.IEqualityComparer keyequalityComparer) : base(keyequalityComparer) { this.keycomparer = keycomparer; } + #endregion - #endregion + #region ISortedDictionary Members - #region ISortedDictionary Members + /// + /// The key comparer used by this dictionary. + /// + /// + public SCG.IComparer Comparer => keyComparer; - /// - /// The key comparer used by this dictionary. - /// - /// - public SCG.IComparer Comparer => keycomparer; + /// + /// + /// + /// + public new ISorted Keys => new SortedKeysCollection(this, sortedPairs, keyComparer, EqualityComparer); - /// - /// - /// - /// - public new ISorted? Keys => new SortedKeysCollection(this, sortedpairs, keycomparer, EqualityComparer); + /// + /// Find the entry in the dictionary whose key is the + /// predecessor of the specified key. + /// + /// The key + /// The predecessor, if any + /// True if key has a predecessor + public bool TryPredecessor(K key, out SCG.KeyValuePair res) + { + return sortedPairs.TryPredecessor(new SCG.KeyValuePair(key, default!), out res); + } - /// - /// Find the entry in the dictionary whose key is the - /// predecessor of the specified key. - /// - /// The key - /// The predecessor, if any - /// True if key has a predecessor - public bool TryPredecessor(K key, out SCG.KeyValuePair res) - { - return sortedpairs.TryPredecessor(new SCG.KeyValuePair(key, default), out res); - } + /// + /// Find the entry in the dictionary whose key is the + /// successor of the specified key. + /// + /// The key + /// The successor, if any + /// True if the key has a successor + public bool TrySuccessor(K key, out SCG.KeyValuePair res) + { + return sortedPairs.TrySuccessor(new SCG.KeyValuePair(key, default!), out res); + } - /// - /// Find the entry in the dictionary whose key is the - /// successor of the specified key. - /// - /// The key - /// The successor, if any - /// True if the key has a successor - public bool TrySuccessor(K key, out SCG.KeyValuePair res) - { - return sortedpairs.TrySuccessor(new SCG.KeyValuePair(key, default), out res); - } + /// + /// Find the entry in the dictionary whose key is the + /// weak predecessor of the specified key. + /// + /// The key + /// The predecessor, if any + /// True if key has a weak predecessor + public bool TryWeakPredecessor(K key, out SCG.KeyValuePair res) + { + return sortedPairs.TryWeakPredecessor(new SCG.KeyValuePair(key, default!), out res); + } - /// - /// Find the entry in the dictionary whose key is the - /// weak predecessor of the specified key. - /// - /// The key - /// The predecessor, if any - /// True if key has a weak predecessor - public bool TryWeakPredecessor(K key, out SCG.KeyValuePair res) - { - return sortedpairs.TryWeakPredecessor(new SCG.KeyValuePair(key, default), out res); - } + /// + /// Find the entry in the dictionary whose key is the + /// weak successor of the specified key. + /// + /// The key + /// The weak successor, if any + /// True if the key has a weak successor + public bool TryWeakSuccessor(K key, out SCG.KeyValuePair res) + { + return sortedPairs.TryWeakSuccessor(new SCG.KeyValuePair(key, default!), out res); + } - /// - /// Find the entry in the dictionary whose key is the - /// weak successor of the specified key. - /// - /// The key - /// The weak successor, if any - /// True if the key has a weak successor - public bool TryWeakSuccessor(K key, out SCG.KeyValuePair res) - { - return sortedpairs.TryWeakSuccessor(new SCG.KeyValuePair(key, default), out res); - } + /// + /// Get the entry in the dictionary whose key is the + /// predecessor of the specified key. + /// + /// + /// The key + /// The entry + public SCG.KeyValuePair Predecessor(K key) + { + return sortedPairs.Predecessor(new SCG.KeyValuePair(key, default!)); + } - /// - /// Get the entry in the dictionary whose key is the - /// predecessor of the specified key. - /// - /// - /// The key - /// The entry - public SCG.KeyValuePair Predecessor(K key) - { - return sortedpairs.Predecessor(new SCG.KeyValuePair(key, default)); - } + /// + /// Get the entry in the dictionary whose key is the + /// successor of the specified key. + /// + /// + /// The key + /// The entry + public SCG.KeyValuePair Successor(K key) + { + return sortedPairs.Successor(new SCG.KeyValuePair(key, default!)); + } - /// - /// Get the entry in the dictionary whose key is the - /// successor of the specified key. - /// - /// - /// The key - /// The entry - public SCG.KeyValuePair Successor(K key) - { - return sortedpairs.Successor(new SCG.KeyValuePair(key, default)); - } + /// + /// Get the entry in the dictionary whose key is the + /// weak predecessor of the specified key. + /// + /// + /// The key + /// The entry + public SCG.KeyValuePair WeakPredecessor(K key) + { + return sortedPairs.WeakPredecessor(new SCG.KeyValuePair(key, default!)); + } - /// - /// Get the entry in the dictionary whose key is the - /// weak predecessor of the specified key. - /// - /// - /// The key - /// The entry - public SCG.KeyValuePair WeakPredecessor(K key) - { - return sortedpairs.WeakPredecessor(new SCG.KeyValuePair(key, default)); - } + /// + /// Get the entry in the dictionary whose key is the + /// weak successor of the specified key. + /// + /// + /// The key + /// The entry + public SCG.KeyValuePair WeakSuccessor(K key) + { + return sortedPairs.WeakSuccessor(new SCG.KeyValuePair(key, default!)); + } - /// - /// Get the entry in the dictionary whose key is the - /// weak successor of the specified key. - /// - /// - /// The key - /// The entry - public SCG.KeyValuePair WeakSuccessor(K key) - { - return sortedpairs.WeakSuccessor(new SCG.KeyValuePair(key, default)); - } + #endregion - #endregion + #region ISortedDictionary Members - #region ISortedDictionary Members + /// + /// + /// + /// + public SCG.KeyValuePair FindMin() + { + return sortedPairs.FindMin(); + } - /// - /// - /// - /// - public SCG.KeyValuePair FindMin() - { - return sortedpairs.FindMin(); - } + /// + /// + /// + /// + public SCG.KeyValuePair DeleteMin() + { + return sortedPairs.DeleteMin(); + } - /// - /// - /// - /// - public SCG.KeyValuePair DeleteMin() - { - return sortedpairs.DeleteMin(); - } + /// + /// + /// + /// + public SCG.KeyValuePair FindMax() + { + return sortedPairs.FindMax(); + } - /// - /// - /// - /// - public SCG.KeyValuePair FindMax() - { - return sortedpairs.FindMax(); - } + /// + /// + /// + /// + public SCG.KeyValuePair DeleteMax() + { + return sortedPairs.DeleteMax(); + } - /// - /// - /// - /// - public SCG.KeyValuePair DeleteMax() - { - return sortedpairs.DeleteMax(); - } + /// + /// + /// + /// + /// + /// + /// + /// + /// + public bool Cut(IComparable cutter, out SCG.KeyValuePair lowEntry, out bool lowIsValid, out SCG.KeyValuePair highEntry, out bool highIsValid) + { + return sortedPairs.Cut(new KeyValuePairComparable(cutter), out lowEntry, out lowIsValid, out highEntry, out highIsValid); + } - /// - /// - /// - /// - /// - /// - /// - /// - /// - public bool Cut(IComparable cutter, out SCG.KeyValuePair lowEntry, out bool lowIsValid, out SCG.KeyValuePair highEntry, out bool highIsValid) - { - return sortedpairs.Cut(new KeyValuePairComparable(cutter), out lowEntry, out lowIsValid, out highEntry, out highIsValid); - } + /// + /// + /// + /// + /// + public IDirectedEnumerable> RangeFrom(K bot) + { + return sortedPairs.RangeFrom(new SCG.KeyValuePair(bot, default)); + } - /// - /// - /// - /// - /// - public IDirectedEnumerable> RangeFrom(K bot) - { - return sortedpairs.RangeFrom(new SCG.KeyValuePair(bot, default)); - } + /// + /// + /// + /// + /// + /// + public IDirectedEnumerable> RangeFromTo(K bot, K top) + { + return sortedPairs.RangeFromTo(new SCG.KeyValuePair(bot, default), new SCG.KeyValuePair(top, default)); + } - /// - /// - /// - /// - /// - /// - public IDirectedEnumerable> RangeFromTo(K bot, K top) - { - return sortedpairs.RangeFromTo(new SCG.KeyValuePair(bot, default), new SCG.KeyValuePair(top, default)); - } + /// + /// + /// + /// + /// + public IDirectedEnumerable> RangeTo(K top) + { + return sortedPairs.RangeTo(new SCG.KeyValuePair(top, default!)); + } - /// - /// - /// - /// - /// - public IDirectedEnumerable> RangeTo(K top) - { - return sortedpairs.RangeTo(new SCG.KeyValuePair(top, default)); - } + /// + /// + /// + /// + public IDirectedCollectionValue> RangeAll() + { + return sortedPairs.RangeAll(); + } - /// - /// - /// - /// - public IDirectedCollectionValue> RangeAll() - { - return sortedpairs.RangeAll(); - } + /// + /// + /// + /// + public void AddSorted(SCG.IEnumerable> items) + { + sortedPairs.AddSorted(items); + } - /// - /// - /// - /// - public void AddSorted(SCG.IEnumerable> items) - { - sortedpairs.AddSorted(items); - } + /// + /// + /// + /// + public void RemoveRangeFrom(K lowKey) + { + sortedPairs.RemoveRangeFrom(new SCG.KeyValuePair(lowKey, default!)); + } - /// - /// - /// - /// - public void RemoveRangeFrom(K lowKey) - { - sortedpairs.RemoveRangeFrom(new SCG.KeyValuePair(lowKey, default)); - } + /// + /// + /// + /// + /// + public void RemoveRangeFromTo(K lowKey, K highKey) + { + sortedPairs.RemoveRangeFromTo(new SCG.KeyValuePair(lowKey, default!), new SCG.KeyValuePair(highKey, default!)); + } - /// - /// - /// - /// - /// - public void RemoveRangeFromTo(K lowKey, K highKey) - { - sortedpairs.RemoveRangeFromTo(new SCG.KeyValuePair(lowKey, default), new SCG.KeyValuePair(highKey, default)); - } + /// + /// + /// + /// + public void RemoveRangeTo(K highKey) + { + sortedPairs.RemoveRangeTo(new SCG.KeyValuePair(highKey, default!)); + } - /// - /// - /// - /// - public void RemoveRangeTo(K highKey) - { - sortedpairs.RemoveRangeTo(new SCG.KeyValuePair(highKey, default)); - } + #endregion + private class KeyValuePairComparable : IComparable> + { + private readonly IComparable cutter; - #endregion - private class KeyValuePairComparable : IComparable> - { - private readonly IComparable cutter; + internal KeyValuePairComparable(IComparable cutter) { this.cutter = cutter; } - internal KeyValuePairComparable(IComparable cutter) { this.cutter = cutter; } + public int CompareTo(SCG.KeyValuePair other) { return cutter.CompareTo(other.Key); } - public int CompareTo(SCG.KeyValuePair other) { return cutter.CompareTo(other.Key); } + public bool Equals(SCG.KeyValuePair other) { return cutter.Equals(other.Key); } + } - public bool Equals(SCG.KeyValuePair other) { return cutter.Equals(other.Key); } - } + private class ProjectedDirectedEnumerable(IDirectedEnumerable> directedpairs) : MappedDirectedEnumerable, K>(directedpairs) + { + public override K Map(SCG.KeyValuePair pair) => pair.Key; + } - private class ProjectedDirectedEnumerable : MappedDirectedEnumerable, K> - { - public ProjectedDirectedEnumerable(IDirectedEnumerable> directedpairs) : base(directedpairs) { } + private class ProjectedDirectedCollectionValue(IDirectedCollectionValue> directedpairs) : MappedDirectedCollectionValue, K>(directedpairs) + { + public override K Map(SCG.KeyValuePair pair) => pair.Key; + } - public override K Map(SCG.KeyValuePair pair) { return pair.Key; } + private class SortedKeysCollection : SequencedBase, ISorted + { + private readonly ISortedDictionary sortedDict; - } + //TODO: eliminate this. Only problem is the Find method because we lack method on dictionary that also + // returns the actual key. + private readonly ISorted> sortedPairs; + private readonly SCG.IComparer comparer; - private class ProjectedDirectedCollectionValue : MappedDirectedCollectionValue, K> + internal SortedKeysCollection(ISortedDictionary sortedDict, ISorted> sortedPairs, SCG.IComparer comparer, SCG.IEqualityComparer itemequalityComparer) + : base(itemequalityComparer) { - public ProjectedDirectedCollectionValue(IDirectedCollectionValue> directedpairs) : base(directedpairs) { } - - public override K Map(SCG.KeyValuePair pair) { return pair.Key; } - + this.sortedDict = sortedDict; + this.sortedPairs = sortedPairs; + this.comparer = comparer; } - private class SortedKeysCollection : SequencedBase, ISorted - { - private readonly ISortedDictionary sorteddict; - - //TODO: eliminate this. Only problem is the Find method because we lack method on dictionary that also - // returns the actual key. - private readonly ISorted> sortedpairs; - private readonly SCG.IComparer comparer; - - internal SortedKeysCollection(ISortedDictionary sorteddict, ISorted> sortedpairs, SCG.IComparer comparer, SCG.IEqualityComparer itemequalityComparer) - : base(itemequalityComparer) - { - this.sorteddict = sorteddict; - this.sortedpairs = sortedpairs; - this.comparer = comparer; - } - - public override K Choose() { return sorteddict.Choose().Key; } + public override K Choose() { return sortedDict.Choose().Key; } - public override SCG.IEnumerator GetEnumerator() + public override SCG.IEnumerator GetEnumerator() + { + foreach (SCG.KeyValuePair p in sortedDict) { - foreach (SCG.KeyValuePair p in sorteddict) - { - yield return p.Key; - } + yield return p.Key; } + } - public override bool IsEmpty => sorteddict.IsEmpty; + public override bool IsEmpty => sortedDict.IsEmpty; - public override int Count => sorteddict.Count; + public override int Count => sortedDict.Count; - public override Speed CountSpeed => sorteddict.CountSpeed; + public override Speed CountSpeed => sortedDict.CountSpeed; - #region ISorted Members + #region ISorted Members - public K FindMin() { return sorteddict.FindMin().Key; } + public K FindMin() { return sortedDict.FindMin().Key; } - public K DeleteMin() { throw new ReadOnlyCollectionException(); } + public K DeleteMin() { throw new ReadOnlyCollectionException(); } - public K FindMax() { return sorteddict.FindMax().Key; } + public K FindMax() { return sortedDict.FindMax().Key; } - public K DeleteMax() { throw new ReadOnlyCollectionException(); } + public K DeleteMax() { throw new ReadOnlyCollectionException(); } - public SCG.IComparer Comparer => comparer; + public SCG.IComparer Comparer => comparer; - public bool TryPredecessor(K item, out K res) - { - bool success = sorteddict.TryPredecessor(item, out SCG.KeyValuePair pRes); - res = pRes.Key; - return success; - } + public bool TryPredecessor(K item, out K res) + { + bool success = sortedDict.TryPredecessor(item, out SCG.KeyValuePair pRes); + res = pRes.Key; + return success; + } - public bool TrySuccessor(K item, out K res) - { - bool success = sorteddict.TrySuccessor(item, out SCG.KeyValuePair pRes); - res = pRes.Key; - return success; - } + public bool TrySuccessor(K item, out K res) + { + bool success = sortedDict.TrySuccessor(item, out SCG.KeyValuePair pRes); + res = pRes.Key; + return success; + } - public bool TryWeakPredecessor(K item, out K res) - { - bool success = sorteddict.TryWeakPredecessor(item, out SCG.KeyValuePair pRes); - res = pRes.Key; - return success; - } + public bool TryWeakPredecessor(K item, out K res) + { + bool success = sortedDict.TryWeakPredecessor(item, out SCG.KeyValuePair pRes); + res = pRes.Key; + return success; + } - public bool TryWeakSuccessor(K item, out K res) - { - bool success = sorteddict.TryWeakSuccessor(item, out SCG.KeyValuePair pRes); - res = pRes.Key; - return success; - } + public bool TryWeakSuccessor(K item, out K res) + { + bool success = sortedDict.TryWeakSuccessor(item, out SCG.KeyValuePair pRes); + res = pRes.Key; + return success; + } - public K Predecessor(K item) { return sorteddict.Predecessor(item).Key; } + public K Predecessor(K item) { return sortedDict.Predecessor(item).Key; } - public K Successor(K item) { return sorteddict.Successor(item).Key; } + public K Successor(K item) { return sortedDict.Successor(item).Key; } - public K WeakPredecessor(K item) { return sorteddict.WeakPredecessor(item).Key; } + public K WeakPredecessor(K item) { return sortedDict.WeakPredecessor(item).Key; } - public K WeakSuccessor(K item) { return sorteddict.WeakSuccessor(item).Key; } + public K WeakSuccessor(K item) { return sortedDict.WeakSuccessor(item).Key; } - public bool Cut(IComparable c, out K low, out bool lowIsValid, out K high, out bool highIsValid) - { - bool retval = sorteddict.Cut(c, out SCG.KeyValuePair lowpair, out lowIsValid, out SCG.KeyValuePair highpair, out highIsValid); - low = lowpair.Key; - high = highpair.Key; - return retval; - } + public bool Cut(IComparable c, out K low, out bool lowIsValid, out K high, out bool highIsValid) + { + bool retval = sortedDict.Cut(c, out SCG.KeyValuePair lowpair, out lowIsValid, out SCG.KeyValuePair highpair, out highIsValid); + low = lowpair.Key; + high = highpair.Key; + return retval; + } - public IDirectedEnumerable RangeFrom(K bot) - { - return new ProjectedDirectedEnumerable(sorteddict.RangeFrom(bot)); - } + public IDirectedEnumerable RangeFrom(K bot) + { + return new ProjectedDirectedEnumerable(sortedDict.RangeFrom(bot)); + } - public IDirectedEnumerable RangeFromTo(K bot, K top) - { - return new ProjectedDirectedEnumerable(sorteddict.RangeFromTo(bot, top)); - } + public IDirectedEnumerable RangeFromTo(K bot, K top) + { + return new ProjectedDirectedEnumerable(sortedDict.RangeFromTo(bot, top)); + } - public IDirectedEnumerable RangeTo(K top) - { - return new ProjectedDirectedEnumerable(sorteddict.RangeTo(top)); - } + public IDirectedEnumerable RangeTo(K top) + { + return new ProjectedDirectedEnumerable(sortedDict.RangeTo(top)); + } - public IDirectedCollectionValue RangeAll() - { - return new ProjectedDirectedCollectionValue(sorteddict.RangeAll()); - } + public IDirectedCollectionValue RangeAll() + { + return new ProjectedDirectedCollectionValue(sortedDict.RangeAll()); + } - public void AddSorted(SCG.IEnumerable items) { throw new ReadOnlyCollectionException(); } + public void AddSorted(SCG.IEnumerable items) { throw new ReadOnlyCollectionException(); } - public void RemoveRangeFrom(K low) { throw new ReadOnlyCollectionException(); } + public void RemoveRangeFrom(K low) { throw new ReadOnlyCollectionException(); } - public void RemoveRangeFromTo(K low, K hi) { throw new ReadOnlyCollectionException(); } + public void RemoveRangeFromTo(K low, K hi) { throw new ReadOnlyCollectionException(); } - public void RemoveRangeTo(K hi) { throw new ReadOnlyCollectionException(); } - #endregion + public void RemoveRangeTo(K hi) { throw new ReadOnlyCollectionException(); } + #endregion - #region ICollection Members - public Speed ContainsSpeed => sorteddict.ContainsSpeed; + #region ICollection Members + public Speed ContainsSpeed => sortedDict.ContainsSpeed; - public bool Contains(K key) { return sorteddict.Contains(key); } + public bool Contains(K key) { return sortedDict.Contains(key); } - public int ContainsCount(K item) { return sorteddict.Contains(item) ? 1 : 0; } + public int ContainsCount(K item) { return sortedDict.Contains(item) ? 1 : 0; } - /// - /// - /// - /// - public virtual ICollectionValue UniqueItems() - { - return this; - } + /// + /// + /// + /// + public virtual ICollectionValue UniqueItems() + { + return this; + } - /// - /// - /// - /// - public virtual ICollectionValue> ItemMultiplicities() - { - return new MultiplicityOne(this); - } + /// + /// + /// + /// + public virtual ICollectionValue> ItemMultiplicities() + { + return new MultiplicityOne(this); + } - public bool ContainsAll(SCG.IEnumerable items) + public bool ContainsAll(SCG.IEnumerable items) + { + //TODO: optimize? + foreach (K item in items) { - //TODO: optimize? - foreach (K item in items) + if (!sortedDict.Contains(item)) { - if (!sorteddict.Contains(item)) - { - return false; - } + return false; } - - return true; } - public bool Find(ref K item) - { - SCG.KeyValuePair p = new SCG.KeyValuePair(item, default); - bool retval = sortedpairs.Find(ref p); - item = p.Key; - return retval; - } + return true; + } - public bool FindOrAdd(ref K item) { throw new ReadOnlyCollectionException(); } + public bool Find(ref K item) + { + SCG.KeyValuePair p = new(item, default); + bool retval = sortedPairs.Find(ref p); + item = p.Key; + return retval; + } - public bool Update(K item) { throw new ReadOnlyCollectionException(); } + public bool FindOrAdd(ref K item) { throw new ReadOnlyCollectionException(); } - public bool Update(K item, out K olditem) { throw new ReadOnlyCollectionException(); } + public bool Update(K item) { throw new ReadOnlyCollectionException(); } - public bool UpdateOrAdd(K item) { throw new ReadOnlyCollectionException(); } + public bool Update(K item, out K olditem) { throw new ReadOnlyCollectionException(); } - public bool UpdateOrAdd(K item, out K olditem) { throw new ReadOnlyCollectionException(); } + public bool UpdateOrAdd(K item) { throw new ReadOnlyCollectionException(); } - public bool Remove(K item) { throw new ReadOnlyCollectionException(); } + public bool UpdateOrAdd(K item, out K olditem) { throw new ReadOnlyCollectionException(); } - public bool Remove(K item, out K removeditem) { throw new ReadOnlyCollectionException(); } + public bool Remove(K item) { throw new ReadOnlyCollectionException(); } - public void RemoveAllCopies(K item) { throw new ReadOnlyCollectionException(); } + public bool Remove(K item, out K removeditem) { throw new ReadOnlyCollectionException(); } - public void RemoveAll(SCG.IEnumerable items) { throw new ReadOnlyCollectionException(); } + public void RemoveAllCopies(K item) { throw new ReadOnlyCollectionException(); } - public void Clear() { throw new ReadOnlyCollectionException(); } + public void RemoveAll(SCG.IEnumerable items) { throw new ReadOnlyCollectionException(); } - public void RetainAll(SCG.IEnumerable items) { throw new ReadOnlyCollectionException(); } + public void Clear() { throw new ReadOnlyCollectionException(); } - #endregion + public void RetainAll(SCG.IEnumerable items) { throw new ReadOnlyCollectionException(); } - #region IExtensible Members - public override bool IsReadOnly => true; + #endregion - public bool AllowsDuplicates => false; + #region IExtensible Members + public override bool IsReadOnly => true; - public bool DuplicatesByCounting => true; + public bool AllowsDuplicates => false; - public bool Add(K item) { throw new ReadOnlyCollectionException(); } + public bool DuplicatesByCounting => true; - void SCG.ICollection.Add(K item) { throw new ReadOnlyCollectionException(); } + public bool Add(K item) { throw new ReadOnlyCollectionException(); } - public void AddAll(SCG.IEnumerable items) { throw new ReadOnlyCollectionException(); } + void SCG.ICollection.Add(K item) { throw new ReadOnlyCollectionException(); } - public bool Check() { return sorteddict.Check(); } + public void AddAll(SCG.IEnumerable items) { throw new ReadOnlyCollectionException(); } - #endregion + public bool Check() { return sortedDict.Check(); } - #region IDirectedCollectionValue Members + #endregion - public override IDirectedCollectionValue Backwards() - { - return RangeAll().Backwards(); - } + #region IDirectedCollectionValue Members - #endregion + public override IDirectedCollectionValue Backwards() + { + return RangeAll().Backwards(); + } - #region IDirectedEnumerable Members + #endregion - IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } - #endregion - } + #region IDirectedEnumerable Members - /// - /// - /// - /// - /// - /// - /// - public override bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider? formatProvider) - { - return Showing.ShowDictionary(this, stringbuilder, ref rest, formatProvider); - } + IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } + #endregion + } + + /// + /// + /// + /// + /// + /// + /// + public override bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider? formatProvider) + { + return Showing.ShowDictionary(this, stringbuilder, ref rest, formatProvider); } } \ No newline at end of file diff --git a/C5/Enumerators/DropMultiplicity.cs b/C5/Enumerators/DropMultiplicity.cs index 803b40fb..b73b70eb 100644 --- a/C5/Enumerators/DropMultiplicity.cs +++ b/C5/Enumerators/DropMultiplicity.cs @@ -1,10 +1,10 @@ -using System; +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. -namespace C5 +namespace C5; + +internal class DropMultiplicity : MappedCollectionValue, K> { - internal class DropMultiplicity : MappedCollectionValue, K> - { - public DropMultiplicity(ICollectionValue> coll) : base(coll) { } - public override K Map(System.Collections.Generic.KeyValuePair kvp) { return kvp.Key; } - } + public DropMultiplicity(ICollectionValue> coll) : base(coll) { } + public override K Map(System.Collections.Generic.KeyValuePair kvp) { return kvp.Key; } } \ No newline at end of file diff --git a/C5/Enumerators/MappedCollectionValue.cs b/C5/Enumerators/MappedCollectionValue.cs index f542e95d..2701e5d8 100644 --- a/C5/Enumerators/MappedCollectionValue.cs +++ b/C5/Enumerators/MappedCollectionValue.cs @@ -1,32 +1,32 @@ -using System; +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. -namespace C5 +namespace C5; + +internal abstract class MappedCollectionValue : CollectionValueBase { - internal abstract class MappedCollectionValue : CollectionValueBase - { - private readonly ICollectionValue collectionValue; + private readonly ICollectionValue _collectionValue; - public abstract V Map(T item); + public abstract V Map(T item); - protected MappedCollectionValue(ICollectionValue collectionValue) - { - this.collectionValue = collectionValue; - } + protected MappedCollectionValue(ICollectionValue collectionValue) + { + _collectionValue = collectionValue; + } - public override V Choose() { return Map(collectionValue.Choose()); } + public override V Choose() => Map(_collectionValue.Choose()); - public override bool IsEmpty => collectionValue.IsEmpty; + public override bool IsEmpty => _collectionValue.IsEmpty; - public override int Count => collectionValue.Count; + public override int Count => _collectionValue.Count; - public override Speed CountSpeed => collectionValue.CountSpeed; + public override Speed CountSpeed => _collectionValue.CountSpeed; - public override System.Collections.Generic.IEnumerator GetEnumerator() + public override System.Collections.Generic.IEnumerator GetEnumerator() + { + foreach (var item in _collectionValue) { - foreach (var item in collectionValue) - { - yield return Map(item); - } + yield return Map(item); } } } \ No newline at end of file diff --git a/C5/Enumerators/MappedDirectedCollectionValue.cs b/C5/Enumerators/MappedDirectedCollectionValue.cs index e28ed769..17085040 100644 --- a/C5/Enumerators/MappedDirectedCollectionValue.cs +++ b/C5/Enumerators/MappedDirectedCollectionValue.cs @@ -1,52 +1,50 @@ // This file is part of the C5 Generic Collection Library for C# and CLI // See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. -using System; using SCG = System.Collections.Generic; -namespace C5 +namespace C5; + +internal abstract class MappedDirectedCollectionValue : DirectedCollectionValueBase, IDirectedCollectionValue { - internal abstract class MappedDirectedCollectionValue : DirectedCollectionValueBase, IDirectedCollectionValue - { - private IDirectedCollectionValue directedCollectionValue; + private IDirectedCollectionValue _directedCollectionValue; - public abstract V Map(T item); + public abstract V Map(T item); - protected MappedDirectedCollectionValue(IDirectedCollectionValue directedCollectionValue) - { - this.directedCollectionValue = directedCollectionValue; - } + protected MappedDirectedCollectionValue(IDirectedCollectionValue directedCollectionValue) + { + _directedCollectionValue = directedCollectionValue; + } - public override V Choose() { return Map(directedCollectionValue.Choose()); } + public override V Choose() => Map(_directedCollectionValue.Choose()); - public override bool IsEmpty => directedCollectionValue.IsEmpty; + public override bool IsEmpty => _directedCollectionValue.IsEmpty; - public override int Count => directedCollectionValue.Count; + public override int Count => _directedCollectionValue.Count; - public override Speed CountSpeed => directedCollectionValue.CountSpeed; + public override Speed CountSpeed => _directedCollectionValue.CountSpeed; - public override IDirectedCollectionValue Backwards() - { - var ret = (MappedDirectedCollectionValue)MemberwiseClone(); - ret.directedCollectionValue = directedCollectionValue.Backwards(); - return ret; - //If we made this classs non-abstract we could do - //return new MappedDirectedCollectionValue(directedCollectionValue.Backwards());; - } + public override IDirectedCollectionValue Backwards() + { + var ret = (MappedDirectedCollectionValue)MemberwiseClone(); + ret._directedCollectionValue = _directedCollectionValue.Backwards(); + return ret; + //If we made this class non-abstract we could do + //return new MappedDirectedCollectionValue(directedCollectionValue.Backwards());; + } - public override SCG.IEnumerator GetEnumerator() + public override SCG.IEnumerator GetEnumerator() + { + foreach (var item in _directedCollectionValue) { - foreach (var item in directedCollectionValue) - { - yield return Map(item); - } + yield return Map(item); } + } - public override Direction Direction => directedCollectionValue.Direction; + public override Direction Direction => _directedCollectionValue.Direction; - IDirectedEnumerable IDirectedEnumerable.Backwards() - { - return Backwards(); - } + IDirectedEnumerable IDirectedEnumerable.Backwards() + { + return Backwards(); } } \ No newline at end of file diff --git a/C5/Enumerators/MappedDirectedEnumerable.cs b/C5/Enumerators/MappedDirectedEnumerable.cs index a40261c0..b7ffc0fa 100644 --- a/C5/Enumerators/MappedDirectedEnumerable.cs +++ b/C5/Enumerators/MappedDirectedEnumerable.cs @@ -1,36 +1,33 @@ -using System; +namespace C5; -namespace C5 +internal abstract class MappedDirectedEnumerable : EnumerableBase, IDirectedEnumerable { - internal abstract class MappedDirectedEnumerable : EnumerableBase, IDirectedEnumerable - { - private IDirectedEnumerable directedenumerable; + private IDirectedEnumerable _directedEnumerable; - public abstract V Map(T item); + public abstract V Map(T item); - public MappedDirectedEnumerable(IDirectedEnumerable directedenumerable) - { - this.directedenumerable = directedenumerable; - } + public MappedDirectedEnumerable(IDirectedEnumerable directedEnumerable) + { + _directedEnumerable = directedEnumerable; + } - public IDirectedEnumerable Backwards() - { - MappedDirectedEnumerable retval = (MappedDirectedEnumerable)MemberwiseClone(); - retval.directedenumerable = directedenumerable.Backwards(); - return retval; - //If we made this classs non-abstract we could do - //return new MappedDirectedCollectionValue(directedcollectionvalue.Backwards());; - } + public IDirectedEnumerable Backwards() + { + MappedDirectedEnumerable retval = (MappedDirectedEnumerable)MemberwiseClone(); + retval._directedEnumerable = _directedEnumerable.Backwards(); + return retval; + //If we made this classs non-abstract we could do + //return new MappedDirectedCollectionValue(directedcollectionvalue.Backwards());; + } - public override System.Collections.Generic.IEnumerator GetEnumerator() + public override System.Collections.Generic.IEnumerator GetEnumerator() + { + foreach (T item in _directedEnumerable) { - foreach (T item in directedenumerable) - { - yield return Map(item); - } + yield return Map(item); } - - public Direction Direction => directedenumerable.Direction; } + + public Direction Direction => _directedEnumerable.Direction; } \ No newline at end of file diff --git a/C5/Enumerators/MultiplicityOne.cs b/C5/Enumerators/MultiplicityOne.cs index 28ff39d1..4f34906a 100644 --- a/C5/Enumerators/MultiplicityOne.cs +++ b/C5/Enumerators/MultiplicityOne.cs @@ -1,10 +1,10 @@ -using System; +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. -namespace C5 +namespace C5; + +internal class MultiplicityOne : MappedCollectionValue> { - internal class MultiplicityOne : MappedCollectionValue> - { - public MultiplicityOne(ICollectionValue coll) : base(coll) { } - public override System.Collections.Generic.KeyValuePair Map(K k) { return new System.Collections.Generic.KeyValuePair(k, 1); } - } + public MultiplicityOne(ICollectionValue coll) : base(coll) { } + public override System.Collections.Generic.KeyValuePair Map(K k) { return new System.Collections.Generic.KeyValuePair(k, 1); } } \ No newline at end of file diff --git a/C5/Enums/Direction.cs b/C5/Enums/Direction.cs new file mode 100644 index 00000000..0ed1a8d7 --- /dev/null +++ b/C5/Enums/Direction.cs @@ -0,0 +1,19 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +namespace C5; + +/// +/// Direction of enumeration order relative to original collection. +/// +public enum Direction +{ + /// + /// Same direction + /// + Forwards, + /// + /// Opposite direction + /// + Backwards +} \ No newline at end of file diff --git a/C5/Enums/EnumerationDirection.cs b/C5/Enums/EnumerationDirection.cs deleted file mode 100644 index e0a2f7dc..00000000 --- a/C5/Enums/EnumerationDirection.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace C5 -{ - /// - /// Direction of enumeration order relative to original collection. - /// - public enum Direction - { - /// - /// Same direction - /// - Forwards, - /// - /// Opposite direction - /// - Backwards - } -} \ No newline at end of file diff --git a/C5/Enums/EventType.cs b/C5/Enums/EventType.cs index 3ce37051..55b6e3bb 100644 --- a/C5/Enums/EventType.cs +++ b/C5/Enums/EventType.cs @@ -1,48 +1,50 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// +/// +[Flags] +public enum EventType { /// /// /// - [Flags] - public enum EventType - { - /// - /// - /// - None = 0x00000000, - /// - /// - /// - Changed = 0x00000001, - /// - /// - /// - Cleared = 0x00000002, - /// - /// - /// - Added = 0x00000004, - /// - /// - /// - Removed = 0x00000008, - /// - /// - /// - Basic = 0x0000000f, - /// - /// - /// - Inserted = 0x00000010, - /// - /// - /// - RemovedAt = 0x00000020, - /// - /// - /// - All = 0x0000003f - } + None = 0x00000000, + /// + /// + /// + Changed = 0x00000001, + /// + /// + /// + Cleared = 0x00000002, + /// + /// + /// + Added = 0x00000004, + /// + /// + /// + Removed = 0x00000008, + /// + /// + /// + Basic = 0x0000000f, + /// + /// + /// + Inserted = 0x00000010, + /// + /// + /// + RemovedAt = 0x00000020, + /// + /// + /// + All = 0x0000003f } \ No newline at end of file diff --git a/C5/Enums/MutualViewPosition.cs b/C5/Enums/MutualViewPosition.cs index 5de1e23d..d8022baa 100644 --- a/C5/Enums/MutualViewPosition.cs +++ b/C5/Enums/MutualViewPosition.cs @@ -1,25 +1,27 @@ -namespace C5 +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +namespace C5; + +/// +/// Characterize the mutual position of some view B (other) relative to view A (this) +/// +internal enum MutualViewPosition { /// - /// Characterize the mutual position of some view B (other) relative to view A (this) + /// B contains A(this) /// - internal enum MutualViewPosition - { - /// - /// B contains A(this) - /// - Contains, - /// - /// B is containd in A(this), but not vice versa - /// - ContainedIn, - /// - /// A and B does not overlap - /// - NonOverlapping, - /// - /// A and B overlap, but neither is contained in the other - /// - Overlapping - } + Contains, + /// + /// B is contained in A(this), but not vice versa + /// + ContainedIn, + /// + /// A and B does not overlap + /// + NonOverlapping, + /// + /// A and B overlap, but neither is contained in the other + /// + Overlapping } \ No newline at end of file diff --git a/C5/Enums/Speed.cs b/C5/Enums/Speed.cs index 55c3e89a..9a68523c 100644 --- a/C5/Enums/Speed.cs +++ b/C5/Enums/Speed.cs @@ -1,40 +1,39 @@ // This file is part of the C5 Generic Collection Library for C# and CLI // See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. -namespace C5 +namespace C5; + +/// +/// The symbolic characterization of the speed of lookups for a collection. +/// The values may refer to worst-case, amortized and/or expected asymptotic +/// complexity wrt. the collection size. +/// +public enum Speed : short { /// - /// The symbolic characterization of the speed of lookups for a collection. - /// The values may refer to worst-case, amortized and/or expected asymtotic - /// complexity wrt. the collection size. + /// Counting the collection with the Count property may not return + /// (for a synthetic and potentially infinite collection). /// - public enum Speed : short - { - /// - /// Counting the collection with the Count property may not return - /// (for a synthetic and potentially infinite collection). - /// - PotentiallyInfinite = 1, + PotentiallyInfinite = 1, - /// - /// Lookup operations like Contains(T item) or the Count - /// property may take time O(n), - /// where n is the size of the collection. - /// - Linear = 2, + /// + /// Lookup operations like Contains(T item) or the Count + /// property may take time O(n), + /// where n is the size of the collection. + /// + Linear = 2, - /// - /// Lookup operations like Contains(T item) or the Count - /// property takes time O(log n), - /// where n is the size of the collection. - /// - Log = 3, + /// + /// Lookup operations like Contains(T item) or the Count + /// property takes time O(log n), + /// where n is the size of the collection. + /// + Log = 3, - /// - /// Lookup operations like Contains(T item) or the Count - /// property takes time O(1), - /// where n is the size of the collection. - /// - Constant = 4 - } + /// + /// Lookup operations like Contains(T item) or the Count + /// property takes time O(1), + /// where n is the size of the collection. + /// + Constant = 4 } \ No newline at end of file diff --git a/C5/Events/ClearedEventArgs.cs b/C5/Events/ClearedEventArgs.cs index 56ac9552..5a0c4766 100644 --- a/C5/Events/ClearedEventArgs.cs +++ b/C5/Events/ClearedEventArgs.cs @@ -1,36 +1,38 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// +/// +public class ClearedEventArgs : EventArgs { /// /// /// - public class ClearedEventArgs : EventArgs - { - /// - /// - /// - public bool Full { get; } + public bool Full { get; } - /// - /// - /// - public int Count { get; } + /// + /// + /// + public int Count { get; } - /// - /// - /// - /// - /// True if the operation cleared all of the collection - /// The number of items removed by the clear. - public ClearedEventArgs(bool full, int count) { Full = full; Count = count; } - /// - /// - /// - /// - public override string ToString() - { - return string.Format("(ClearedEventArgs {0} {1})", Count, Full); - } + /// + /// + /// + /// + /// True if the operation cleared all of the collection + /// The number of items removed by the clear. + public ClearedEventArgs(bool full, int count) { Full = full; Count = count; } + /// + /// + /// + /// + public override string ToString() + { + return string.Format("(ClearedEventArgs {0} {1})", Count, Full); } } \ No newline at end of file diff --git a/C5/Events/ClearedRangeEventArgs.cs b/C5/Events/ClearedRangeEventArgs.cs index 4b74a6bc..de1ad83f 100644 --- a/C5/Events/ClearedRangeEventArgs.cs +++ b/C5/Events/ClearedRangeEventArgs.cs @@ -1,32 +1,32 @@ -using System; +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. -namespace C5 +namespace C5; + +/// +/// +/// +public class ClearedRangeEventArgs : ClearedEventArgs { /// /// /// - public class ClearedRangeEventArgs : ClearedEventArgs - { - /// - /// - /// - public int? Start { get; } + public int? Start { get; } - /// - /// - /// - /// - /// - /// - public ClearedRangeEventArgs(bool full, int count, int? start) : base(full, count) { Start = start; } + /// + /// + /// + /// + /// + /// + public ClearedRangeEventArgs(bool full, int count, int? start) : base(full, count) { Start = start; } - /// - /// - /// - /// - public override string ToString() - { - return string.Format("(ClearedRangeEventArgs {0} {1} {2})", Count, Full, Start); - } + /// + /// + /// + /// + public override string ToString() + { + return string.Format("(ClearedRangeEventArgs {0} {1} {2})", Count, Full, Start); } } \ No newline at end of file diff --git a/C5/Events/CollectionChangedHandler.cs b/C5/Events/CollectionChangedHandler.cs index 8cbc5e5a..5c789a0f 100644 --- a/C5/Events/CollectionChangedHandler.cs +++ b/C5/Events/CollectionChangedHandler.cs @@ -1,11 +1,13 @@ -namespace C5 -{ - /// - /// The type of event raised after an operation on a collection has changed its contents. - /// Normally, a multioperation like AddAll, - /// - /// will only fire one CollectionChanged event. Any operation that changes the collection - /// must fire CollectionChanged as its last event. - /// - public delegate void CollectionChangedHandler(object sender); -} \ No newline at end of file +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +namespace C5; + +/// +/// The type of event raised after an operation on a collection has changed its contents. +/// Normally, a multioperation like AddAll, +/// +/// will only fire one CollectionChanged event. Any operation that changes the collection +/// must fire CollectionChanged as its last event. +/// +public delegate void CollectionChangedHandler(object sender); \ No newline at end of file diff --git a/C5/Events/CollectionClearedHandler.cs b/C5/Events/CollectionClearedHandler.cs index b3eb8b63..b8c59618 100644 --- a/C5/Events/CollectionClearedHandler.cs +++ b/C5/Events/CollectionClearedHandler.cs @@ -1,11 +1,13 @@ -namespace C5 -{ - /// - /// The type of event raised after the Clear() operation on a collection. - /// - /// Note: The Clear() operation will not fire ItemsRemoved events. - /// - /// - /// - public delegate void CollectionClearedHandler(object sender, ClearedEventArgs eventArgs); -} \ No newline at end of file +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +namespace C5; + +/// +/// The type of event raised after the Clear() operation on a collection. +/// +/// Note: The Clear() operation will not fire ItemsRemoved events. +/// +/// +/// +public delegate void CollectionClearedHandler(object sender, ClearedEventArgs eventArgs); \ No newline at end of file diff --git a/C5/Events/EventBlock.cs b/C5/Events/EventBlock.cs index a79338f1..869739c6 100644 --- a/C5/Events/EventBlock.cs +++ b/C5/Events/EventBlock.cs @@ -1,157 +1,154 @@ // This file is part of the C5 Generic Collection Library for C# and CLI // See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. -using System; +namespace C5; -namespace C5 +/// +/// Holds the real events for a collection +/// +/// +internal sealed class EventBlock { - /// - /// Holds the real events for a collection - /// - /// - internal sealed class EventBlock - { - internal EventType events; + internal EventType events; - private event CollectionChangedHandler CollectionChangedInner; - internal event CollectionChangedHandler CollectionChanged + private event CollectionChangedHandler CollectionChangedInner; + internal event CollectionChangedHandler CollectionChanged + { + add { - add - { - CollectionChangedInner += value; - events |= EventType.Changed; - } - remove + CollectionChangedInner += value; + events |= EventType.Changed; + } + remove + { + CollectionChangedInner -= value; + if (CollectionChangedInner == null) { - CollectionChangedInner -= value; - if (CollectionChangedInner == null) - { - events &= ~EventType.Changed; - } + events &= ~EventType.Changed; } } - internal void RaiseCollectionChanged(object sender) + } + internal void RaiseCollectionChanged(object sender) + { + CollectionChangedInner?.Invoke(sender); + } + + private event CollectionClearedHandler CollectionClearedInner; + internal event CollectionClearedHandler CollectionCleared + { + add { - CollectionChangedInner?.Invoke(sender); + CollectionClearedInner += value; + events |= EventType.Cleared; } - - private event CollectionClearedHandler CollectionClearedInner; - internal event CollectionClearedHandler CollectionCleared + remove { - add - { - CollectionClearedInner += value; - events |= EventType.Cleared; - } - remove + CollectionClearedInner -= value; + if (CollectionClearedInner == null) { - CollectionClearedInner -= value; - if (CollectionClearedInner == null) - { - events &= ~EventType.Cleared; - } + events &= ~EventType.Cleared; } } + } - internal void RaiseCollectionCleared(object sender, bool full, int count) - { - CollectionClearedInner?.Invoke(sender, new ClearedEventArgs(full, count)); - } + internal void RaiseCollectionCleared(object sender, bool full, int count) + { + CollectionClearedInner?.Invoke(sender, new ClearedEventArgs(full, count)); + } - internal void RaiseCollectionCleared(object sender, bool full, int count, int? start) + internal void RaiseCollectionCleared(object sender, bool full, int count, int? start) + { + CollectionClearedInner?.Invoke(sender, new ClearedRangeEventArgs(full, count, start)); + } + + private event ItemsAddedHandler ItemsAddedInner; + internal event ItemsAddedHandler ItemsAdded + { + add { - CollectionClearedInner?.Invoke(sender, new ClearedRangeEventArgs(full, count, start)); + ItemsAddedInner += value; + events |= EventType.Added; } - - private event ItemsAddedHandler ItemsAddedInner; - internal event ItemsAddedHandler ItemsAdded + remove { - add + ItemsAddedInner -= value; + if (ItemsAddedInner == null) { - ItemsAddedInner += value; - events |= EventType.Added; - } - remove - { - ItemsAddedInner -= value; - if (ItemsAddedInner == null) - { - events &= ~EventType.Added; - } + events &= ~EventType.Added; } } - internal void RaiseItemsAdded(object sender, T item, int count) + } + internal void RaiseItemsAdded(object sender, T item, int count) + { + ItemsAddedInner?.Invoke(sender, new ItemCountEventArgs(item, count)); + } + + private event ItemsRemovedHandler ItemsRemovedInner; + internal event ItemsRemovedHandler ItemsRemoved + { + add { - ItemsAddedInner?.Invoke(sender, new ItemCountEventArgs(item, count)); + ItemsRemovedInner += value; + events |= EventType.Removed; } - - private event ItemsRemovedHandler ItemsRemovedInner; - internal event ItemsRemovedHandler ItemsRemoved + remove { - add - { - ItemsRemovedInner += value; - events |= EventType.Removed; - } - remove + ItemsRemovedInner -= value; + if (ItemsRemovedInner == null) { - ItemsRemovedInner -= value; - if (ItemsRemovedInner == null) - { - events &= ~EventType.Removed; - } + events &= ~EventType.Removed; } } + } + + internal void RaiseItemsRemoved(object sender, T item, int count) + { + ItemsRemovedInner?.Invoke(sender, new ItemCountEventArgs(item, count)); + } - internal void RaiseItemsRemoved(object sender, T item, int count) + private event ItemInsertedHandler ItemInsertedInner; + internal event ItemInsertedHandler ItemInserted + { + add { - ItemsRemovedInner?.Invoke(sender, new ItemCountEventArgs(item, count)); + ItemInsertedInner += value; + events |= EventType.Inserted; } - - private event ItemInsertedHandler ItemInsertedInner; - internal event ItemInsertedHandler ItemInserted + remove { - add + ItemInsertedInner -= value; + if (ItemInsertedInner == null) { - ItemInsertedInner += value; - events |= EventType.Inserted; - } - remove - { - ItemInsertedInner -= value; - if (ItemInsertedInner == null) - { - events &= ~EventType.Inserted; - } + events &= ~EventType.Inserted; } } + } - internal void RaiseItemInserted(object sender, T item, int index) + internal void RaiseItemInserted(object sender, T item, int index) + { + ItemInsertedInner?.Invoke(sender, new ItemAtEventArgs(item, index)); + } + + private event ItemRemovedAtHandler ItemRemovedAtInner; + internal event ItemRemovedAtHandler ItemRemovedAt + { + add { - ItemInsertedInner?.Invoke(sender, new ItemAtEventArgs(item, index)); + ItemRemovedAtInner += value; + events |= EventType.RemovedAt; } - - private event ItemRemovedAtHandler ItemRemovedAtInner; - internal event ItemRemovedAtHandler ItemRemovedAt + remove { - add + ItemRemovedAtInner -= value; + if (ItemRemovedAtInner == null) { - ItemRemovedAtInner += value; - events |= EventType.RemovedAt; - } - remove - { - ItemRemovedAtInner -= value; - if (ItemRemovedAtInner == null) - { - events &= ~EventType.RemovedAt; - } + events &= ~EventType.RemovedAt; } } + } - internal void RaiseItemRemovedAt(object sender, T item, int index) - { - ItemRemovedAtInner?.Invoke(sender, new ItemAtEventArgs(item, index)); - } + internal void RaiseItemRemovedAt(object sender, T item, int index) + { + ItemRemovedAtInner?.Invoke(sender, new ItemAtEventArgs(item, index)); } } \ No newline at end of file diff --git a/C5/Events/ItemAtEventArgs.cs b/C5/Events/ItemAtEventArgs.cs index edac410f..ddd832e9 100644 --- a/C5/Events/ItemAtEventArgs.cs +++ b/C5/Events/ItemAtEventArgs.cs @@ -1,37 +1,39 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// +/// +/// +public class ItemAtEventArgs : EventArgs { /// /// /// - /// - public class ItemAtEventArgs : EventArgs - { - /// - /// - /// - public T Item { get; } + public T Item { get; } - /// - /// - /// - public int Index { get; } + /// + /// + /// + public int Index { get; } - /// - /// - /// - /// - /// - public ItemAtEventArgs(T item, int index) { Item = item; Index = index; } + /// + /// + /// + /// + /// + public ItemAtEventArgs(T item, int index) { Item = item; Index = index; } - /// - /// - /// - /// - public override string ToString() - { - return string.Format("(ItemAtEventArgs {0} '{1}')", Index, Item); - } + /// + /// + /// + /// + public override string ToString() + { + return string.Format("(ItemAtEventArgs {0} '{1}')", Index, Item); } } \ No newline at end of file diff --git a/C5/Events/ItemCountEventArgs.cs b/C5/Events/ItemCountEventArgs.cs index c6c69b1e..55acee15 100644 --- a/C5/Events/ItemCountEventArgs.cs +++ b/C5/Events/ItemCountEventArgs.cs @@ -1,36 +1,38 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// +/// +/// +public class ItemCountEventArgs : EventArgs { /// /// /// - /// - public class ItemCountEventArgs : EventArgs - { - /// - /// - /// - public T Item { get; } + public T Item { get; } - /// - /// - /// - public int Count { get; } + /// + /// + /// + public int Count { get; } - /// - /// - /// - /// - /// - public ItemCountEventArgs(T item, int count) { Item = item; Count = count; } - /// - /// - /// - /// - public override string ToString() - { - return string.Format("(ItemCountEventArgs {0} '{1}')", Count, Item); - } + /// + /// + /// + /// + /// + public ItemCountEventArgs(T item, int count) { Item = item; Count = count; } + /// + /// + /// + /// + public override string ToString() + { + return string.Format("(ItemCountEventArgs {0} '{1}')", Count, Item); } } \ No newline at end of file diff --git a/C5/Events/ItemInsertedHandler.cs b/C5/Events/ItemInsertedHandler.cs index 44011773..1260f8ac 100644 --- a/C5/Events/ItemInsertedHandler.cs +++ b/C5/Events/ItemInsertedHandler.cs @@ -1,15 +1,17 @@ -namespace C5 -{ - /// - /// The type of event raised after an item has been inserted into a list by an Insert, - /// InsertFirst or InsertLast operation. - /// The event will be raised at a point of time, where the collection object is - /// in an internally consistent state and before the corresponding CollectionChanged - /// event is raised. - /// - /// Note: an ItemsAdded event will also be fired. - /// - /// - /// - public delegate void ItemInsertedHandler(object sender, ItemAtEventArgs eventArgs); -} \ No newline at end of file +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +namespace C5; + +/// +/// The type of event raised after an item has been inserted into a list by an Insert, +/// InsertFirst or InsertLast operation. +/// The event will be raised at a point of time, where the collection object is +/// in an internally consistent state and before the corresponding CollectionChanged +/// event is raised. +/// +/// Note: an ItemsAdded event will also be fired. +/// +/// +/// +public delegate void ItemInsertedHandler(object sender, ItemAtEventArgs eventArgs); \ No newline at end of file diff --git a/C5/Events/ItemRemovedAtHandler.cs b/C5/Events/ItemRemovedAtHandler.cs index a2b37a13..de90b0b1 100644 --- a/C5/Events/ItemRemovedAtHandler.cs +++ b/C5/Events/ItemRemovedAtHandler.cs @@ -1,15 +1,17 @@ -namespace C5 -{ - /// - /// The type of event raised after an item has been removed from a list by a RemoveAt(int i) - /// operation (or RemoveFirst(), RemoveLast(), Remove() operation). - /// The event will be raised at a point of time, where the collection object is - /// in an internally consistent state and before the corresponding CollectionChanged - /// event is raised. - /// - /// Note: an ItemRemoved event will also be fired. - /// - /// - /// - public delegate void ItemRemovedAtHandler(object sender, ItemAtEventArgs eventArgs); -} \ No newline at end of file +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +namespace C5; + +/// +/// The type of event raised after an item has been removed from a list by a RemoveAt(int i) +/// operation (or RemoveFirst(), RemoveLast(), Remove() operation). +/// The event will be raised at a point of time, where the collection object is +/// in an internally consistent state and before the corresponding CollectionChanged +/// event is raised. +/// +/// Note: an ItemRemoved event will also be fired. +/// +/// +/// +public delegate void ItemRemovedAtHandler(object sender, ItemAtEventArgs eventArgs); \ No newline at end of file diff --git a/C5/Events/ItemsAddedHandler.cs b/C5/Events/ItemsAddedHandler.cs index c207a400..b7e4aeb0 100644 --- a/C5/Events/ItemsAddedHandler.cs +++ b/C5/Events/ItemsAddedHandler.cs @@ -1,17 +1,19 @@ -namespace C5 -{ - /// - /// The type of event raised after an item has been added to a collection. - /// The event will be raised at a point of time, where the collection object is - /// in an internally consistent state and before the corresponding CollectionChanged - /// event is raised. - /// - /// Note: an Update operation will fire an ItemsRemoved and an ItemsAdded event. - /// - /// Note: When an item is inserted into a list (), both - /// ItemInserted and ItemsAdded events will be fired. - /// - /// - /// An object with the item that was added - public delegate void ItemsAddedHandler(object sender, ItemCountEventArgs eventArgs); -} \ No newline at end of file +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +namespace C5; + +/// +/// The type of event raised after an item has been added to a collection. +/// The event will be raised at a point of time, where the collection object is +/// in an internally consistent state and before the corresponding CollectionChanged +/// event is raised. +/// +/// Note: an Update operation will fire an ItemsRemoved and an ItemsAdded event. +/// +/// Note: When an item is inserted into a list (), both +/// ItemInserted and ItemsAdded events will be fired. +/// +/// +/// An object with the item that was added +public delegate void ItemsAddedHandler(object sender, ItemCountEventArgs eventArgs); \ No newline at end of file diff --git a/C5/Events/ItemsRemovedHandler.cs b/C5/Events/ItemsRemovedHandler.cs index 78853bf2..98037eb5 100644 --- a/C5/Events/ItemsRemovedHandler.cs +++ b/C5/Events/ItemsRemovedHandler.cs @@ -1,19 +1,21 @@ -namespace C5 -{ - /// - /// The type of event raised after an item has been removed from a collection. - /// The event will be raised at a point of time, where the collection object is - /// in an internally consistent state and before the corresponding CollectionChanged - /// event is raised. - /// - /// Note: The Clear() operation will not fire ItemsRemoved events. - /// - /// Note: an Update operation will fire an ItemsRemoved and an ItemsAdded event. - /// - /// Note: When an item is removed from a list by the RemoveAt operation, both an - /// ItemsRemoved and an ItemRemovedAt event will be fired. - /// - /// - /// An object with the item that was removed - public delegate void ItemsRemovedHandler(object sender, ItemCountEventArgs eventArgs); -} \ No newline at end of file +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +namespace C5; + +/// +/// The type of event raised after an item has been removed from a collection. +/// The event will be raised at a point of time, where the collection object is +/// in an internally consistent state and before the corresponding CollectionChanged +/// event is raised. +/// +/// Note: The Clear() operation will not fire ItemsRemoved events. +/// +/// Note: an Update operation will fire an ItemsRemoved and an ItemsAdded event. +/// +/// Note: When an item is removed from a list by the RemoveAt operation, both an +/// ItemsRemoved and an ItemRemovedAt event will be fired. +/// +/// +/// An object with the item that was removed +public delegate void ItemsRemovedHandler(object sender, ItemCountEventArgs eventArgs); \ No newline at end of file diff --git a/C5/Events/ProxyEventBlock.cs b/C5/Events/ProxyEventBlock.cs index 26b93a3e..4143567b 100644 --- a/C5/Events/ProxyEventBlock.cs +++ b/C5/Events/ProxyEventBlock.cs @@ -1,166 +1,166 @@ -using System; +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. -namespace C5 +namespace C5; + +/// +/// Tentative, to conserve memory in GuardedCollectionValueBase +/// This should really be nested in Guarded collection value, only have a guardereal field +/// +/// +internal sealed class ProxyEventBlock { - /// - /// Tentative, to conserve memory in GuardedCollectionValueBase - /// This should really be nested in Guarded collection value, only have a guardereal field - /// - /// - internal sealed class ProxyEventBlock - { - private readonly ICollectionValue proxy, real; + private readonly ICollectionValue proxy, real; - internal ProxyEventBlock(ICollectionValue proxy, ICollectionValue real) - { this.proxy = proxy; this.real = real; } + internal ProxyEventBlock(ICollectionValue proxy, ICollectionValue real) + { this.proxy = proxy; this.real = real; } - private event CollectionChangedHandler CollectionChangedInner; + private event CollectionChangedHandler CollectionChangedInner; - private CollectionChangedHandler? collectionChangedProxy = null; - internal event CollectionChangedHandler CollectionChanged + private CollectionChangedHandler? collectionChangedProxy = null; + internal event CollectionChangedHandler CollectionChanged + { + add { - add + if (CollectionChangedInner == null) { - if (CollectionChangedInner == null) - { - collectionChangedProxy ??= delegate (object sender) { CollectionChangedInner(proxy); }; + collectionChangedProxy ??= delegate (object sender) { CollectionChangedInner(proxy); }; - real.CollectionChanged += collectionChangedProxy; - } - CollectionChangedInner += value; + real.CollectionChanged += collectionChangedProxy; } - remove + CollectionChangedInner += value; + } + remove + { + CollectionChangedInner -= value; + if (CollectionChangedInner == null) { - CollectionChangedInner -= value; - if (CollectionChangedInner == null) - { - real.CollectionChanged -= collectionChangedProxy; - } + real.CollectionChanged -= collectionChangedProxy; } } + } - private event CollectionClearedHandler CollectionClearedInner; + private event CollectionClearedHandler CollectionClearedInner; - private CollectionClearedHandler? collectionClearedProxy = null; - internal event CollectionClearedHandler CollectionCleared + private CollectionClearedHandler? collectionClearedProxy = null; + internal event CollectionClearedHandler CollectionCleared + { + add { - add + if (CollectionClearedInner == null) { - if (CollectionClearedInner == null) - { - collectionClearedProxy ??= delegate (object sender, ClearedEventArgs e) { CollectionClearedInner(proxy, e); }; + collectionClearedProxy ??= delegate (object sender, ClearedEventArgs e) { CollectionClearedInner(proxy, e); }; - real.CollectionCleared += collectionClearedProxy; - } - CollectionClearedInner += value; + real.CollectionCleared += collectionClearedProxy; } - remove + CollectionClearedInner += value; + } + remove + { + CollectionClearedInner -= value; + if (CollectionClearedInner == null) { - CollectionClearedInner -= value; - if (CollectionClearedInner == null) - { - real.CollectionCleared -= collectionClearedProxy; - } + real.CollectionCleared -= collectionClearedProxy; } } + } - private event ItemsAddedHandler ItemsAddedInner; + private event ItemsAddedHandler ItemsAddedInner; - private ItemsAddedHandler? itemsAddedProxy = null; - internal event ItemsAddedHandler ItemsAdded + private ItemsAddedHandler? itemsAddedProxy = null; + internal event ItemsAddedHandler ItemsAdded + { + add { - add + if (ItemsAddedInner == null) { - if (ItemsAddedInner == null) - { - itemsAddedProxy ??= delegate (object sender, ItemCountEventArgs e) { ItemsAddedInner(proxy, e); }; + itemsAddedProxy ??= delegate (object sender, ItemCountEventArgs e) { ItemsAddedInner(proxy, e); }; - real.ItemsAdded += itemsAddedProxy; - } - ItemsAddedInner += value; + real.ItemsAdded += itemsAddedProxy; } - remove + ItemsAddedInner += value; + } + remove + { + ItemsAddedInner -= value; + if (ItemsAddedInner == null) { - ItemsAddedInner -= value; - if (ItemsAddedInner == null) - { - real.ItemsAdded -= itemsAddedProxy; - } + real.ItemsAdded -= itemsAddedProxy; } } + } - private event ItemInsertedHandler ItemInsertedInner; + private event ItemInsertedHandler ItemInsertedInner; - private ItemInsertedHandler? itemInsertedProxy = null; - internal event ItemInsertedHandler ItemInserted + private ItemInsertedHandler? itemInsertedProxy = null; + internal event ItemInsertedHandler ItemInserted + { + add { - add + if (ItemInsertedInner == null) { - if (ItemInsertedInner == null) - { - itemInsertedProxy ??= delegate (object sender, ItemAtEventArgs e) { ItemInsertedInner(proxy, e); }; + itemInsertedProxy ??= delegate (object sender, ItemAtEventArgs e) { ItemInsertedInner(proxy, e); }; - real.ItemInserted += itemInsertedProxy; - } - ItemInsertedInner += value; + real.ItemInserted += itemInsertedProxy; } - remove + ItemInsertedInner += value; + } + remove + { + ItemInsertedInner -= value; + if (ItemInsertedInner == null) { - ItemInsertedInner -= value; - if (ItemInsertedInner == null) - { - real.ItemInserted -= itemInsertedProxy; - } + real.ItemInserted -= itemInsertedProxy; } } + } - private event ItemsRemovedHandler? ItemsRemovedInner = null; + private event ItemsRemovedHandler? ItemsRemovedInner = null; - private ItemsRemovedHandler? itemsRemovedProxy = null; - internal event ItemsRemovedHandler ItemsRemoved + private ItemsRemovedHandler? itemsRemovedProxy = null; + internal event ItemsRemovedHandler ItemsRemoved + { + add { - add + if (ItemsRemovedInner == null) { - if (ItemsRemovedInner == null) - { - itemsRemovedProxy ??= delegate (object sender, ItemCountEventArgs e) { ItemsRemovedInner?.Invoke(proxy, e); }; + itemsRemovedProxy ??= delegate (object sender, ItemCountEventArgs e) { ItemsRemovedInner?.Invoke(proxy, e); }; - real.ItemsRemoved += itemsRemovedProxy; - } - ItemsRemovedInner += value; + real.ItemsRemoved += itemsRemovedProxy; } - remove + ItemsRemovedInner += value; + } + remove + { + ItemsRemovedInner -= value; + if (ItemsRemovedInner == null) { - ItemsRemovedInner -= value; - if (ItemsRemovedInner == null) - { - real.ItemsRemoved -= itemsRemovedProxy; - } + real.ItemsRemoved -= itemsRemovedProxy; } } + } - private event ItemRemovedAtHandler ItemRemovedAtInner; + private event ItemRemovedAtHandler ItemRemovedAtInner; - private ItemRemovedAtHandler? itemRemovedAtProxy = null; - internal event ItemRemovedAtHandler ItemRemovedAt + private ItemRemovedAtHandler? itemRemovedAtProxy = null; + internal event ItemRemovedAtHandler ItemRemovedAt + { + add { - add + if (ItemRemovedAtInner == null) { - if (ItemRemovedAtInner == null) - { - itemRemovedAtProxy ??= delegate (object sender, ItemAtEventArgs e) { ItemRemovedAtInner(proxy, e); }; + itemRemovedAtProxy ??= delegate (object sender, ItemAtEventArgs e) { ItemRemovedAtInner(proxy, e); }; - real.ItemRemovedAt += itemRemovedAtProxy; - } - ItemRemovedAtInner += value; + real.ItemRemovedAt += itemRemovedAtProxy; } - remove + ItemRemovedAtInner += value; + } + remove + { + ItemRemovedAtInner -= value; + if (ItemRemovedAtInner == null) { - ItemRemovedAtInner -= value; - if (ItemRemovedAtInner == null) - { - real.ItemRemovedAt -= itemRemovedAtProxy; - } + real.ItemRemovedAt -= itemRemovedAtProxy; } } } diff --git a/C5/Exceptions/CollectionModifiedException.cs b/C5/Exceptions/CollectionModifiedException.cs index f4430d61..b1f97d1c 100644 --- a/C5/Exceptions/CollectionModifiedException.cs +++ b/C5/Exceptions/CollectionModifiedException.cs @@ -1,22 +1,24 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// An exception thrown by enumerators, range views etc. when accessed after +/// the underlying collection has been modified. +/// +public class CollectionModifiedException : Exception { /// - /// An exception thrown by enumerators, range views etc. when accessed after - /// the underlying collection has been modified. + /// Create a simple exception with no further explanation. /// - public class CollectionModifiedException : Exception - { - /// - /// Create a simple exception with no further explanation. - /// - public CollectionModifiedException() : base() { } + public CollectionModifiedException() : base() { } - /// - /// Create the exception with an explanation of the reason. - /// - /// - public CollectionModifiedException(string message) : base(message) { } - } + /// + /// Create the exception with an explanation of the reason. + /// + /// + public CollectionModifiedException(string message) : base(message) { } } \ No newline at end of file diff --git a/C5/Exceptions/DuplicateNotAllowedException.cs b/C5/Exceptions/DuplicateNotAllowedException.cs index a7d67ac2..c4f8c2b0 100644 --- a/C5/Exceptions/DuplicateNotAllowedException.cs +++ b/C5/Exceptions/DuplicateNotAllowedException.cs @@ -1,25 +1,27 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// An exception thrown when an operation attempts to create a duplicate in a collection with set semantics +/// ( is false) or attempts to create a duplicate key in a dictionary. +/// With collections this can only happen with Insert operations on lists, since the Add operations will +/// not try to create duplicates and either ignore the failure or report it in a bool return value. +/// +/// With dictionaries this can happen with the method. +/// +public class DuplicateNotAllowedException : Exception { /// - /// An exception thrown when an operation attempts to create a duplicate in a collection with set semantics - /// ( is false) or attempts to create a duplicate key in a dictionary. - /// With collections this can only happen with Insert operations on lists, since the Add operations will - /// not try to create duplictes and either ignore the failure or report it in a bool return value. - /// - /// With dictionaries this can happen with the metod. + /// Create a simple exception with no further explanation. + /// + public DuplicateNotAllowedException() : base() { } + /// + /// Create the exception with an explanation of the reason. /// - public class DuplicateNotAllowedException : Exception - { - /// - /// Create a simple exception with no further explanation. - /// - public DuplicateNotAllowedException() : base() { } - /// - /// Create the exception with an explanation of the reason. - /// - /// - public DuplicateNotAllowedException(string message) : base(message) { } - } + /// + public DuplicateNotAllowedException(string message) : base(message) { } } \ No newline at end of file diff --git a/C5/Exceptions/FixedSizeCollectionException.cs b/C5/Exceptions/FixedSizeCollectionException.cs index 09c2ee29..797cb26d 100644 --- a/C5/Exceptions/FixedSizeCollectionException.cs +++ b/C5/Exceptions/FixedSizeCollectionException.cs @@ -1,20 +1,22 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// +/// +public class FixedSizeCollectionException : Exception { /// - /// + /// Create a simple exception with no further explanation. + /// + public FixedSizeCollectionException() : base() { } + /// + /// Create the exception with an explanation of the reason. /// - public class FixedSizeCollectionException : Exception - { - /// - /// Create a simple exception with no further explanation. - /// - public FixedSizeCollectionException() : base() { } - /// - /// Create the exception with an explanation of the reason. - /// - /// - public FixedSizeCollectionException(string message) : base(message) { } - } + /// + public FixedSizeCollectionException(string message) : base(message) { } } \ No newline at end of file diff --git a/C5/Exceptions/IncompatibleViewException.cs b/C5/Exceptions/IncompatibleViewException.cs index c1b4ef5a..bd7dab7d 100644 --- a/C5/Exceptions/IncompatibleViewException.cs +++ b/C5/Exceptions/IncompatibleViewException.cs @@ -1,21 +1,23 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// An exception thrown by operations on a list that expects an argument +/// that is a view on the same underlying list. +/// +public class IncompatibleViewException : Exception { /// - /// An exception thrown by operations on a list that expects an argument - /// that is a view on the same underlying list. + /// Create a simple exception with no further explanation. + /// + public IncompatibleViewException() : base() { } + /// + /// Create the exception with an explanation of the reason. /// - public class IncompatibleViewException : Exception - { - /// - /// Create a simple exception with no further explanation. - /// - public IncompatibleViewException() : base() { } - /// - /// Create the exception with an explanation of the reason. - /// - /// - public IncompatibleViewException(string message) : base(message) { } - } + /// + public IncompatibleViewException(string message) : base(message) { } } \ No newline at end of file diff --git a/C5/Exceptions/InternalException.cs b/C5/Exceptions/InternalException.cs index 5ab94aae..c4394cf6 100644 --- a/C5/Exceptions/InternalException.cs +++ b/C5/Exceptions/InternalException.cs @@ -3,13 +3,12 @@ using System; -namespace C5 +namespace C5; + +/// +/// An exception to throw from library code when an internal inconsistency is encountered. +/// +public class InternalException : Exception { - /// - /// An exception to throw from library code when an internal inconsistency is encountered. - /// - public class InternalException : Exception - { - internal InternalException(string message) : base(message) { } - } + internal InternalException(string message) : base(message) { } } \ No newline at end of file diff --git a/C5/Exceptions/InvalidPriorityQueueHandleException.cs b/C5/Exceptions/InvalidPriorityQueueHandleException.cs index 9abae8a6..bb6f69b5 100644 --- a/C5/Exceptions/InvalidPriorityQueueHandleException.cs +++ b/C5/Exceptions/InvalidPriorityQueueHandleException.cs @@ -1,20 +1,22 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// +/// +public class InvalidPriorityQueueHandleException : Exception { /// - /// + /// Create a simple exception with no further explanation. + /// + public InvalidPriorityQueueHandleException() : base() { } + /// + /// Create the exception with an explanation of the reason. /// - public class InvalidPriorityQueueHandleException : Exception - { - /// - /// Create a simple exception with no further explanation. - /// - public InvalidPriorityQueueHandleException() : base() { } - /// - /// Create the exception with an explanation of the reason. - /// - /// - public InvalidPriorityQueueHandleException(string message) : base(message) { } - } + /// + public InvalidPriorityQueueHandleException(string message) : base(message) { } } \ No newline at end of file diff --git a/C5/Exceptions/NoSuchItemException.cs b/C5/Exceptions/NoSuchItemException.cs index 55edb12b..3fca3a8c 100644 --- a/C5/Exceptions/NoSuchItemException.cs +++ b/C5/Exceptions/NoSuchItemException.cs @@ -1,23 +1,25 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// An exception thrown by a lookup or lookup with update operation that does not +/// find the lookup item and has no other means to communicate failure. +/// The typical scenario is a lookup by key in a dictionary with an indexer, +/// see e.g. +/// +public class NoSuchItemException : Exception { /// - /// An exception thrown by a lookup or lookup with update operation that does not - /// find the lookup item and has no other means to communicate failure. - /// The typical scenario is a lookup by key in a dictionary with an indexer, - /// see e.g. + /// Create a simple exception with no further explanation. + /// + public NoSuchItemException() : base() { } + /// + /// Create the exception with an explanation of the reason. /// - public class NoSuchItemException : Exception - { - /// - /// Create a simple exception with no further explanation. - /// - public NoSuchItemException() : base() { } - /// - /// Create the exception with an explanation of the reason. - /// - /// - public NoSuchItemException(string message) : base(message) { } - } + /// + public NoSuchItemException(string message) : base(message) { } } \ No newline at end of file diff --git a/C5/Exceptions/NotAViewException.cs b/C5/Exceptions/NotAViewException.cs index 5ad8c010..244ffeec 100644 --- a/C5/Exceptions/NotAViewException.cs +++ b/C5/Exceptions/NotAViewException.cs @@ -1,21 +1,23 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// An exception thrown by an operation on a list () +/// that only makes sense for a view, not for an underlying list. +/// +public class NotAViewException : Exception { /// - /// An exception thrown by an operation on a list () - /// that only makes sense for a view, not for an underlying list. + /// Create a simple exception with no further explanation. + /// + public NotAViewException() : base() { } + /// + /// Create the exception with an explanation of the reason. /// - public class NotAViewException : Exception - { - /// - /// Create a simple exception with no further explanation. - /// - public NotAViewException() : base() { } - /// - /// Create the exception with an explanation of the reason. - /// - /// - public NotAViewException(string message) : base(message) { } - } + /// + public NotAViewException(string message) : base(message) { } } \ No newline at end of file diff --git a/C5/Exceptions/NotComparableException.cs b/C5/Exceptions/NotComparableException.cs index 7e53b83c..8afa6bf9 100644 --- a/C5/Exceptions/NotComparableException.cs +++ b/C5/Exceptions/NotComparableException.cs @@ -1,21 +1,23 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// An exception thrown by an operation that need to construct a natural +/// comparer for a type. +/// +public class NotComparableException : Exception { /// - /// An exception thrown by an operation that need to construct a natural - /// comparer for a type. + /// Create a simple exception with no further explanation. + /// + public NotComparableException() : base() { } + /// + /// Create the exception with an explanation of the reason. /// - public class NotComparableException : Exception - { - /// - /// Create a simple exception with no further explanation. - /// - public NotComparableException() : base() { } - /// - /// Create the exception with an explanation of the reason. - /// - /// - public NotComparableException(string message) : base(message) { } - } + /// + public NotComparableException(string message) : base(message) { } } \ No newline at end of file diff --git a/C5/Exceptions/ReadOnlyCollectionException.cs b/C5/Exceptions/ReadOnlyCollectionException.cs index 486d5169..86afcbb4 100644 --- a/C5/Exceptions/ReadOnlyCollectionException.cs +++ b/C5/Exceptions/ReadOnlyCollectionException.cs @@ -1,23 +1,25 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// An exception thrown by an update operation on a Read-Only collection or dictionary. +/// This exception will be thrown unconditionally when an update operation +/// (method or set property) is called. No check is made to see if the update operation, +/// if allowed, would actually change the collection. +/// +public class ReadOnlyCollectionException : Exception { /// - /// An exception thrown by an update operation on a Read-Only collection or dictionary. - /// This exception will be thrown unconditionally when an update operation - /// (method or set property) is called. No check is made to see if the update operation, - /// if allowed, would actually change the collection. + /// Create a simple exception with no further explanation. + /// + public ReadOnlyCollectionException() : base() { } + /// + /// Create the exception with an explanation of the reason. /// - public class ReadOnlyCollectionException : Exception - { - /// - /// Create a simple exception with no further explanation. - /// - public ReadOnlyCollectionException() : base() { } - /// - /// Create the exception with an explanation of the reason. - /// - /// - public ReadOnlyCollectionException(string message) : base(message) { } - } + /// + public ReadOnlyCollectionException(string message) : base(message) { } } \ No newline at end of file diff --git a/C5/Exceptions/UnlistenableEventException.cs b/C5/Exceptions/UnlistenableEventException.cs index 3eb30e68..97a25dd1 100644 --- a/C5/Exceptions/UnlistenableEventException.cs +++ b/C5/Exceptions/UnlistenableEventException.cs @@ -1,20 +1,22 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// +/// +public class UnlistenableEventException : Exception { /// - /// + /// Create a simple exception with no further explanation. + /// + public UnlistenableEventException() : base() { } + /// + /// Create the exception with an explanation of the reason. /// - public class UnlistenableEventException : Exception - { - /// - /// Create a simple exception with no further explanation. - /// - public UnlistenableEventException() : base() { } - /// - /// Create the exception with an explanation of the reason. - /// - /// - public UnlistenableEventException(string message) : base(message) { } - } + /// + public UnlistenableEventException(string message) : base(message) { } } \ No newline at end of file diff --git a/C5/Exceptions/ViewDisposedException.cs b/C5/Exceptions/ViewDisposedException.cs index a17317de..ae21c3ef 100644 --- a/C5/Exceptions/ViewDisposedException.cs +++ b/C5/Exceptions/ViewDisposedException.cs @@ -1,26 +1,28 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// An exception thrown when trying to access a view (a list view on a or +/// a snapshot on a ) +/// that has been invalidated by some earlier operation. +/// +/// The typical scenario is a view on a list that hash been invalidated by a call to +/// Sort, Reverse or Shuffle on some other, overlapping view or the whole list. +/// +/// +public class ViewDisposedException : Exception { /// - /// An exception thrown when trying to access a view (a list view on a or - /// a snapshot on a ) - /// that has been invalidated by some earlier operation. - /// - /// The typical scenario is a view on a list that hash been invalidated by a call to - /// Sort, Reverse or Shuffle on some other, overlapping view or the whole list. - /// + /// Create a simple exception with no further explanation. + /// + public ViewDisposedException() : base() { } + /// + /// Create the exception with an explanation of the reason. /// - public class ViewDisposedException : Exception - { - /// - /// Create a simple exception with no further explanation. - /// - public ViewDisposedException() : base() { } - /// - /// Create the exception with an explanation of the reason. - /// - /// - public ViewDisposedException(string message) : base(message) { } - } + /// + public ViewDisposedException(string message) : base(message) { } } \ No newline at end of file diff --git a/C5/Hashing/HashBag.cs b/C5/Hashing/HashBag.cs index eff94695..6b3f8984 100644 --- a/C5/Hashing/HashBag.cs +++ b/C5/Hashing/HashBag.cs @@ -4,260 +4,297 @@ using System; using SCG = System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// A bag collection based on a hash table of (item,count) pairs. +/// +public class HashBag : CollectionBase, ICollection { + #region Fields + private HashSet> dict; + #endregion + + #region Events + /// - /// A bag collection based on a hash table of (item,count) pairs. + /// /// - public class HashBag : CollectionBase, ICollection + /// + public override EventType ListenableEvents => EventType.Basic; + + #endregion + + #region Constructors + /// + /// Create a hash bag with the default item equalityComparer. + /// + public HashBag() : this(EqualityComparer.Default) { } + + /// + /// Create a hash bag with an external item equalityComparer. + /// + /// The external item equalityComparer. + public HashBag(SCG.IEqualityComparer itemequalityComparer) + : base(itemequalityComparer) { - #region Fields - private HashSet> dict; - #endregion + dict = new HashSet>(new KeyValuePairEqualityComparer(itemequalityComparer)); + } - #region Events + /// + /// Create a hash bag with external item equalityComparer, prescribed initial table size and default fill threshold (66%) + /// + /// Initial table size (rounded to power of 2, at least 16) + /// The external item equalitySCG.Comparer + public HashBag(int capacity, SCG.IEqualityComparer itemequalityComparer) + : base(itemequalityComparer) + { + dict = new HashSet>(capacity, new KeyValuePairEqualityComparer(itemequalityComparer)); + } - /// - /// - /// - /// - public override EventType ListenableEvents => EventType.Basic; - #endregion + /// + /// Create a hash bag with external item equalityComparer, prescribed initial table size and fill threshold. + /// + /// Initial table size (rounded to power of 2, at least 16) + /// Fill threshold (valid range 10% to 90%) + /// The external item equalitySCG.Comparer + public HashBag(int capacity, double fill, SCG.IEqualityComparer itemequalityComparer) + : base(itemequalityComparer) + { + dict = new HashSet>(capacity, fill, new KeyValuePairEqualityComparer(itemequalityComparer)); + } - #region Constructors - /// - /// Create a hash bag with the default item equalityComparer. - /// - public HashBag() : this(EqualityComparer.Default) { } + #endregion - /// - /// Create a hash bag with an external item equalityComparer. - /// - /// The external item equalityComparer. - public HashBag(SCG.IEqualityComparer itemequalityComparer) - : base(itemequalityComparer) - { - dict = new HashSet>(new KeyValuePairEqualityComparer(itemequalityComparer)); - } + #region IEditableCollection Members - /// - /// Create a hash bag with external item equalityComparer, prescribed initial table size and default fill threshold (66%) - /// - /// Initial table size (rounded to power of 2, at least 16) - /// The external item equalitySCG.Comparer - public HashBag(int capacity, SCG.IEqualityComparer itemequalityComparer) - : base(itemequalityComparer) - { - dict = new HashSet>(capacity, new KeyValuePairEqualityComparer(itemequalityComparer)); - } + /// + /// The complexity of the Contains operation + /// + /// Always returns Speed.Constant + public virtual Speed ContainsSpeed => Speed.Constant; + /// + /// Check if an item is in the bag + /// + /// The item to look for + /// True if bag contains item + public virtual bool Contains(T item) + { + return dict.Contains(new System.Collections.Generic.KeyValuePair(item, 0)); + } + + + /// + /// Check if an item (collection equal to a given one) is in the bag and + /// if so report the actual item object found. + /// + /// On entry, the item to look for. + /// On exit the item found, if any + /// True if bag contains item + public virtual bool Find(ref T item) + { + System.Collections.Generic.KeyValuePair p = new(item, 0); - /// - /// Create a hash bag with external item equalityComparer, prescribed initial table size and fill threshold. - /// - /// Initial table size (rounded to power of 2, at least 16) - /// Fill threshold (valid range 10% to 90%) - /// The external item equalitySCG.Comparer - public HashBag(int capacity, double fill, SCG.IEqualityComparer itemequalityComparer) - : base(itemequalityComparer) + if (dict.Find(ref p)) { - dict = new HashSet>(capacity, fill, new KeyValuePairEqualityComparer(itemequalityComparer)); + item = p.Key; + return true; } - #endregion + return false; + } - #region IEditableCollection Members - /// - /// The complexity of the Contains operation - /// - /// Always returns Speed.Constant - public virtual Speed ContainsSpeed => Speed.Constant; + /// + /// Check if an item (collection equal to a given one) is in the bag and + /// if so replace the item object in the bag with the supplied one. + /// + /// The item object to update with + /// True if item was found (and updated) + public virtual bool Update(T item) + { + return Update(item, out _); + } - /// - /// Check if an item is in the bag - /// - /// The item to look for - /// True if bag contains item - public virtual bool Contains(T item) - { - return dict.Contains(new System.Collections.Generic.KeyValuePair(item, 0)); - } + /// + /// + /// + /// + /// + /// + public virtual bool Update(T item, out T olditem) + { + SCG.KeyValuePair p = new(item, 0); - /// - /// Check if an item (collection equal to a given one) is in the bag and - /// if so report the actual item object found. - /// - /// On entry, the item to look for. - /// On exit the item found, if any - /// True if bag contains item - public virtual bool Find(ref T item) - { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(item, 0); + UpdateCheck(); - if (dict.Find(ref p)) + //Note: we cannot just do dict.Update: we have to lookup the count before we + //know what to update with. There is of course a way around if we use the + //implementation of hashset -which we do not want to do. + //The hashbag is moreover mainly a proof of concept + if (dict.Find(ref p)) + { + olditem = p.Key; + p = new SCG.KeyValuePair(item, p.Value); + dict.Update(p); + if (ActiveEvents != 0) { - item = p.Key; - return true; + RaiseForUpdate(item, olditem, p.Value); } - return false; + return true; } + olditem = default; + return false; + } + - /// - /// Check if an item (collection equal to a given one) is in the bag and - /// if so replace the item object in the bag with the supplied one. - /// - /// The item object to update with - /// True if item was found (and updated) - public virtual bool Update(T item) + /// + /// Check if an item (collection equal to a given one) is in the bag. + /// If found, report the actual item object in the bag, + /// else add the supplied one. + /// + /// On entry, the item to look for or add. + /// On exit the actual object found, if any. + /// True if item was found + public virtual bool FindOrAdd(ref T item) + { + UpdateCheck(); + if (Find(ref item)) { - return Update(item, out _); + return true; } + Add(item); + return false; + } - /// - /// - /// - /// - /// - /// - public virtual bool Update(T item, out T olditem) - { - SCG.KeyValuePair p = new SCG.KeyValuePair(item, 0); - - UpdateCheck(); - //Note: we cannot just do dict.Update: we have to lookup the count before we - //know what to update with. There is of course a way around if we use the - //implementation of hashset -which we do not want to do. - //The hashbag is moreover mainly a proof of concept - if (dict.Find(ref p)) - { - olditem = p.Key; - p = new SCG.KeyValuePair(item, p.Value); - dict.Update(p); - if (ActiveEvents != 0) - { - RaiseForUpdate(item, olditem, p.Value); - } + /// + /// Check if an item (collection equal to a supplied one) is in the bag and + /// if so replace the item object in the set with the supplied one; else + /// add the supplied one. + /// + /// The item to look for and update or add + /// True if item was updated + public virtual bool UpdateOrAdd(T item) + { + UpdateCheck(); + if (Update(item)) + { + return true; + } - return true; - } + Add(item); + return false; + } - olditem = default; - return false; + /// + /// + /// + /// + /// + /// + public virtual bool UpdateOrAdd(T item, out T olditem) + { + UpdateCheck(); + if (Update(item, out olditem)) + { + return true; } + Add(item); + return false; + } + + /// + /// Remove one copy of an item from the bag + /// + /// The item to remove + /// True if item was (found and) removed + public virtual bool Remove(T item) + { + var p = new SCG.KeyValuePair(item, 0); - /// - /// Check if an item (collection equal to a given one) is in the bag. - /// If found, report the actual item object in the bag, - /// else add the supplied one. - /// - /// On entry, the item to look for or add. - /// On exit the actual object found, if any. - /// True if item was found - public virtual bool FindOrAdd(ref T item) + UpdateCheck(); + if (dict.Find(ref p)) { - UpdateCheck(); - if (Find(ref item)) + size--; + if (p.Value == 1) { - return true; + dict.Remove(p); + } + else + { + p = new SCG.KeyValuePair(p.Key, p.Value - 1); + dict.Update(p); + } + if (ActiveEvents != 0) + { + RaiseForRemove(p.Key); } - Add(item); - return false; + return true; } + return false; + } + - /// - /// Check if an item (collection equal to a supplied one) is in the bag and - /// if so replace the item object in the set with the supplied one; else - /// add the supplied one. - /// - /// The item to look for and update or add - /// True if item was updated - public virtual bool UpdateOrAdd(T item) + /// + /// Remove one copy of an item from the bag, reporting the actual matching item object. + /// + /// The value to remove. + /// The removed value. + /// True if item was found. + public virtual bool Remove(T item, out T removeditem) + { + UpdateCheck(); + SCG.KeyValuePair p = new(item, 0); + if (dict.Find(ref p)) { - UpdateCheck(); - if (Update(item)) + removeditem = p.Key; + size--; + if (p.Value == 1) { - return true; + dict.Remove(p); } - - Add(item); - return false; - } - - /// - /// - /// - /// - /// - /// - public virtual bool UpdateOrAdd(T item, out T olditem) - { - UpdateCheck(); - if (Update(item, out olditem)) + else { - return true; + p = new SCG.KeyValuePair(p.Key, p.Value - 1); + dict.Update(p); } - - Add(item); - return false; - } - - /// - /// Remove one copy of an item from the bag - /// - /// The item to remove - /// True if item was (found and) removed - public virtual bool Remove(T item) - { - var p = new SCG.KeyValuePair(item, 0); - - UpdateCheck(); - if (dict.Find(ref p)) + if (ActiveEvents != 0) { - size--; - if (p.Value == 1) - { - dict.Remove(p); - } - else - { - p = new SCG.KeyValuePair(p.Key, p.Value - 1); - dict.Update(p); - } - if (ActiveEvents != 0) - { - RaiseForRemove(p.Key); - } - - return true; + RaiseForRemove(removeditem); } - return false; + return true; } + removeditem = default; + return false; + } - /// - /// Remove one copy of an item from the bag, reporting the actual matching item object. - /// - /// The value to remove. - /// The removed value. - /// True if item was found. - public virtual bool Remove(T item, out T removeditem) + /// + /// Remove all items in a supplied collection from this bag, counting multiplicities. + /// + /// The items to remove. + public virtual void RemoveAll(SCG.IEnumerable items) + { +#warning Improve if items is a counting bag + UpdateCheck(); + bool mustRaise = (ActiveEvents & (EventType.Changed | EventType.Removed)) != 0; + RaiseForRemoveAllHandler? raiseHandler = mustRaise ? new RaiseForRemoveAllHandler(this) : null; + foreach (T item in items) { - UpdateCheck(); - SCG.KeyValuePair p = new SCG.KeyValuePair(item, 0); + SCG.KeyValuePair p = new(item, 0); if (dict.Find(ref p)) { - removeditem = p.Key; size--; if (p.Value == 1) { @@ -268,452 +305,414 @@ public virtual bool Remove(T item, out T removeditem) p = new SCG.KeyValuePair(p.Key, p.Value - 1); dict.Update(p); } - if (ActiveEvents != 0) + if (mustRaise) { - RaiseForRemove(removeditem); + raiseHandler?.Remove(p.Key); } - - return true; } - - removeditem = default; - return false; } - - /// - /// Remove all items in a supplied collection from this bag, counting multiplicities. - /// - /// The items to remove. - public virtual void RemoveAll(SCG.IEnumerable items) + if (mustRaise) { -#warning Improve if items is a counting bag - UpdateCheck(); - bool mustRaise = (ActiveEvents & (EventType.Changed | EventType.Removed)) != 0; - RaiseForRemoveAllHandler? raiseHandler = mustRaise ? new RaiseForRemoveAllHandler(this) : null; - foreach (T item in items) - { - SCG.KeyValuePair p = new SCG.KeyValuePair(item, 0); - if (dict.Find(ref p)) - { - size--; - if (p.Value == 1) - { - dict.Remove(p); - } - else - { - p = new SCG.KeyValuePair(p.Key, p.Value - 1); - dict.Update(p); - } - if (mustRaise) - { - raiseHandler?.Remove(p.Key); - } - } - } - if (mustRaise) - { - raiseHandler?.Raise(); - } + raiseHandler?.Raise(); } + } - /// - /// Remove all items from the bag, resetting internal table to initial size. - /// - public virtual void Clear() + /// + /// Remove all items from the bag, resetting internal table to initial size. + /// + public virtual void Clear() + { + UpdateCheck(); + if (size == 0) { - UpdateCheck(); - if (size == 0) - { - return; - } + return; + } - dict.Clear(); - int oldsize = size; - size = 0; - if ((ActiveEvents & EventType.Cleared) != 0) - { - RaiseCollectionCleared(true, oldsize); - } + dict.Clear(); + int oldsize = size; + size = 0; + if ((ActiveEvents & EventType.Cleared) != 0) + { + RaiseCollectionCleared(true, oldsize); + } - if ((ActiveEvents & EventType.Changed) != 0) - { - RaiseCollectionChanged(); - } + if ((ActiveEvents & EventType.Changed) != 0) + { + RaiseCollectionChanged(); } + } - /// - /// Remove all items *not* in a supplied collection from this bag, - /// counting multiplicities. - /// - /// The items to retain - public virtual void RetainAll(SCG.IEnumerable items) - { - UpdateCheck(); + /// + /// Remove all items *not* in a supplied collection from this bag, + /// counting multiplicities. + /// + /// The items to retain + public virtual void RetainAll(SCG.IEnumerable items) + { + UpdateCheck(); - HashBag res = new HashBag(itemequalityComparer); + HashBag res = new(itemEqualityComparer); - foreach (T item in items) + foreach (T item in items) + { + SCG.KeyValuePair p = new(item, default); + if (dict.Find(ref p)) { - SCG.KeyValuePair p = new SCG.KeyValuePair(item, default); - if (dict.Find(ref p)) + SCG.KeyValuePair q = p; + if (res.dict.Find(ref q)) { - SCG.KeyValuePair q = p; - if (res.dict.Find(ref q)) + if (q.Value < p.Value) { - if (q.Value < p.Value) - { - q = new SCG.KeyValuePair(q.Key, q.Value + 1); - res.dict.Update(q); - res.size++; - } - } - else - { - q = new SCG.KeyValuePair(q.Key, 1); - res.dict.Add(q); + q = new SCG.KeyValuePair(q.Key, q.Value + 1); + res.dict.Update(q); res.size++; } } + else + { + q = new SCG.KeyValuePair(q.Key, 1); + res.dict.Add(q); + res.size++; + } } + } - if (size == res.size) - { - return; - } + if (size == res.size) + { + return; + } - CircularQueue? wasRemoved = null; - if ((ActiveEvents & EventType.Removed) != 0) + CircularQueue? wasRemoved = null; + if ((ActiveEvents & EventType.Removed) != 0) + { + wasRemoved = new CircularQueue(); + foreach (SCG.KeyValuePair p in dict) { - wasRemoved = new CircularQueue(); - foreach (SCG.KeyValuePair p in dict) + int removed = p.Value - res.ContainsCount(p.Key); + if (removed > 0) { - int removed = p.Value - res.ContainsCount(p.Key); - if (removed > 0) - { #warning We could send bag events here easily using a CircularQueue of (should?) - for (int i = 0; i < removed; i++) - { - wasRemoved.Enqueue(p.Key); - } + for (int i = 0; i < removed; i++) + { + wasRemoved.Enqueue(p.Key); } } } - dict = res.dict; - size = res.size; + } + dict = res.dict; + size = res.size; - if ((ActiveEvents & EventType.Removed) != 0) + if ((ActiveEvents & EventType.Removed) != 0) + { + RaiseForRemoveAll(wasRemoved); + } + else if ((ActiveEvents & EventType.Changed) != 0) + { + RaiseCollectionChanged(); + } + } + + /// + /// Check if all items in a supplied collection is in this bag + /// (counting multiplicities). + /// + /// The items to look for. + /// True if all items are found. + public virtual bool ContainsAll(SCG.IEnumerable items) + { + HashBag res = new(itemEqualityComparer); + + foreach (T item in items) + { + if (res.ContainsCount(item) < ContainsCount(item)) { - RaiseForRemoveAll(wasRemoved); + res.Add(item); } - else if ((ActiveEvents & EventType.Changed) != 0) + else { - RaiseCollectionChanged(); + return false; } } - /// - /// Check if all items in a supplied collection is in this bag - /// (counting multiplicities). - /// - /// The items to look for. - /// True if all items are found. - public virtual bool ContainsAll(SCG.IEnumerable items) - { - HashBag res = new HashBag(itemequalityComparer); - - foreach (T item in items) - { - if (res.ContainsCount(item) < ContainsCount(item)) - { - res.Add(item); - } - else - { - return false; - } - } + return true; + } - return true; - } + /// + /// Create an array containing all items in this bag (in enumeration order). + /// + /// The array + public override T[] ToArray() + { + T[] res = new T[size]; + int ind = 0; - /// - /// Create an array containing all items in this bag (in enumeration order). - /// - /// The array - public override T[] ToArray() + foreach (System.Collections.Generic.KeyValuePair p in dict) { - T[] res = new T[size]; - int ind = 0; - - foreach (System.Collections.Generic.KeyValuePair p in dict) + for (int i = 0; i < p.Value; i++) { - for (int i = 0; i < p.Value; i++) - { - res[ind++] = p.Key; - } + res[ind++] = p.Key; } - - return res; } + return res; + } - /// - /// Count the number of times an item is in this set. - /// - /// The item to look for. - /// The count - public virtual int ContainsCount(T item) - { - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(item, 0); - if (dict.Find(ref p)) - { - return p.Value; - } + /// + /// Count the number of times an item is in this set. + /// + /// The item to look for. + /// The count + public virtual int ContainsCount(T item) + { + System.Collections.Generic.KeyValuePair p = new(item, 0); - return 0; + if (dict.Find(ref p)) + { + return p.Value; } - /// - /// - /// - /// - public virtual ICollectionValue UniqueItems() { return new DropMultiplicity(dict); } + return 0; + } - /// - /// - /// - /// - public virtual ICollectionValue> ItemMultiplicities() - { - return new GuardedCollectionValue>(dict); - } + /// + /// + /// + /// + public virtual ICollectionValue UniqueItems() { return new DropMultiplicity(dict); } - /// - /// Remove all copies of item from this set. - /// - /// The item to remove - public virtual void RemoveAllCopies(T item) - { - UpdateCheck(); + /// + /// + /// + /// + public virtual ICollectionValue> ItemMultiplicities() + { + return new GuardedCollectionValue>(dict); + } - System.Collections.Generic.KeyValuePair p = new System.Collections.Generic.KeyValuePair(item, 0); + /// + /// Remove all copies of item from this set. + /// + /// The item to remove + public virtual void RemoveAllCopies(T item) + { + UpdateCheck(); - if (dict.Find(ref p)) + System.Collections.Generic.KeyValuePair p = new(item, 0); + + if (dict.Find(ref p)) + { + size -= p.Value; + dict.Remove(p); + if ((ActiveEvents & EventType.Removed) != 0) { - size -= p.Value; - dict.Remove(p); - if ((ActiveEvents & EventType.Removed) != 0) - { - RaiseItemsRemoved(p.Key, p.Value); - } + RaiseItemsRemoved(p.Key, p.Value); + } - if ((ActiveEvents & EventType.Changed) != 0) - { - RaiseCollectionChanged(); - } + if ((ActiveEvents & EventType.Changed) != 0) + { + RaiseCollectionChanged(); } } + } - #endregion + #endregion - #region ICollection Members + #region ICollection Members - /// - /// Copy the items of this bag to part of an array. - /// if i is negative. - /// if the array does not have room for the items. - /// - /// The array to copy to - /// The starting index. - public override void CopyTo(T[] array, int index) + /// + /// Copy the items of this bag to part of an array. + /// if i is negative. + /// if the array does not have room for the items. + /// + /// The array to copy to + /// The starting index. + public override void CopyTo(T[] array, int index) + { + if (index < 0 || index + Count > array.Length) { - if (index < 0 || index + Count > array.Length) - { - throw new ArgumentOutOfRangeException(); - } + throw new ArgumentOutOfRangeException(nameof(index)); + } - foreach (System.Collections.Generic.KeyValuePair p in dict) + foreach (System.Collections.Generic.KeyValuePair p in dict) + { + for (int j = 0; j < p.Value; j++) { - for (int j = 0; j < p.Value; j++) - { - array[index++] = p.Key; - } + array[index++] = p.Key; } } + } - #endregion + #endregion - #region IExtensible Members + #region IExtensible Members - /// - /// Report if this is a set collection. - /// - /// Always true - public virtual bool AllowsDuplicates => true; + /// + /// Report if this is a set collection. + /// + /// Always true + public virtual bool AllowsDuplicates => true; - /// - /// By convention this is true for any collection with set semantics. - /// - /// True if only one representative of a group of equal items - /// is kept in the collection together with the total count. - public virtual bool DuplicatesByCounting => true; + /// + /// By convention this is true for any collection with set semantics. + /// + /// True if only one representative of a group of equal items + /// is kept in the collection together with the total count. + public virtual bool DuplicatesByCounting => true; - /// - /// Add an item to this bag. - /// - /// The item to add. - /// Always true - public virtual bool Add(T item) + /// + /// Add an item to this bag. + /// + /// The item to add. + /// Always true + public virtual bool Add(T item) + { + UpdateCheck(); + Add(ref item); + if (ActiveEvents != 0) { - UpdateCheck(); - Add(ref item); - if (ActiveEvents != 0) - { - RaiseForAdd(item); - } - - return true; + RaiseForAdd(item); } - /// - /// Add an item to this bag. - /// - /// The item to add. - void SCG.ICollection.Add(T item) + return true; + } + + /// + /// Add an item to this bag. + /// + /// The item to add. + void SCG.ICollection.Add(T item) + { + Add(item); + } + + private void Add(ref T item) + { + var p = new SCG.KeyValuePair(item, 1); + if (dict.Find(ref p)) { - Add(item); + p = new SCG.KeyValuePair(item, p.Value + 1); + dict.Update(p); + item = p.Key; } - - private void Add(ref T item) + else { - var p = new SCG.KeyValuePair(item, 1); - if (dict.Find(ref p)) - { - p = new SCG.KeyValuePair(item, p.Value + 1); - dict.Update(p); - item = p.Key; - } - else - { - dict.Add(p); - } - - size++; + dict.Add(p); } - /// - /// Add the elements from another collection with a more specialized item type - /// to this collection. - /// - /// The items to add - public virtual void AddAll(SCG.IEnumerable items) - { - UpdateCheck(); + size++; + } + + /// + /// Add the elements from another collection with a more specialized item type + /// to this collection. + /// + /// The items to add + public virtual void AddAll(SCG.IEnumerable items) + { + UpdateCheck(); #warning We could easily raise bag events - bool mustRaiseAdded = (ActiveEvents & EventType.Added) != 0; - CircularQueue? wasAdded = mustRaiseAdded ? new CircularQueue() : null; - bool wasChanged = false; - foreach (T item in items) - { - T jtem = item; - Add(ref jtem); - wasChanged = true; - if (mustRaiseAdded) - { - wasAdded?.Enqueue(jtem); - } - } - if (!wasChanged) + bool mustRaiseAdded = (ActiveEvents & EventType.Added) != 0; + CircularQueue? wasAdded = mustRaiseAdded ? new CircularQueue() : null; + bool wasChanged = false; + foreach (T item in items) + { + T jtem = item; + Add(ref jtem); + wasChanged = true; + if (mustRaiseAdded) { - return; + wasAdded?.Enqueue(jtem); } + } + if (!wasChanged) + { + return; + } - if (mustRaiseAdded) + if (mustRaiseAdded) + { + if (wasAdded != null) { - if (wasAdded != null) + foreach (T item in wasAdded) { - foreach (T item in wasAdded) - { - RaiseItemsAdded(item, 1); - } + RaiseItemsAdded(item, 1); } } + } - if ((ActiveEvents & EventType.Changed) != 0) - { - RaiseCollectionChanged(); - } + if ((ActiveEvents & EventType.Changed) != 0) + { + RaiseCollectionChanged(); } + } - #endregion + #endregion - #region IEnumerable Members + #region IEnumerable Members - /// - /// Choose some item of this collection. - /// - /// if collection is empty. - /// - public override T Choose() - { - return dict.Choose().Key; - } + /// + /// Choose some item of this collection. + /// + /// if collection is empty. + /// + public override T Choose() + { + return dict.Choose().Key; + } - /// - /// Create an enumerator for this bag. - /// - /// The enumerator - public override SCG.IEnumerator GetEnumerator() - { - int left; - int mystamp = stamp; + /// + /// Create an enumerator for this bag. + /// + /// The enumerator + public override SCG.IEnumerator GetEnumerator() + { + int left; + int mystamp = stamp; - foreach (System.Collections.Generic.KeyValuePair p in dict) + foreach (System.Collections.Generic.KeyValuePair p in dict) + { + left = p.Value; + while (left > 0) { - left = p.Value; - while (left > 0) + if (mystamp != stamp) { - if (mystamp != stamp) - { - throw new CollectionModifiedException(); - } - - left--; - yield return p.Key; + throw new CollectionModifiedException(); } + + left--; + yield return p.Key; } } - #endregion - - #region Diagnostics - /// - /// Test internal structure of data (invariants) - /// - /// True if pass - public virtual bool Check() - { - bool retval = dict.Check(); - int count = 0; + } + #endregion - foreach (System.Collections.Generic.KeyValuePair p in dict) - { - count += p.Value; - } + #region Diagnostics + /// + /// Test internal structure of data (invariants) + /// + /// True if pass + public virtual bool Check() + { + bool retval = dict.Check(); + int count = 0; - if (count != size) - { - Logger.Log(string.Format("count({0}) != size({1})", count, size)); - retval = false; - } + foreach (System.Collections.Generic.KeyValuePair p in dict) + { + count += p.Value; + } - return retval; + if (count != size) + { + Logger.Log(string.Format("count({0}) != size({1})", count, size)); + retval = false; } - #endregion + + return retval; } + #endregion } diff --git a/C5/Hashing/HashDictionary.cs b/C5/Hashing/HashDictionary.cs index 822d9c70..95578bbb 100644 --- a/C5/Hashing/HashDictionary.cs +++ b/C5/Hashing/HashDictionary.cs @@ -1,47 +1,45 @@ // This file is part of the C5 Generic Collection Library for C# and CLI // See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. -using System; using SCG = System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// A generic dictionary class based on a hash set class . +/// +public class HashDictionary : DictionaryBase, IDictionary { /// - /// A generic dictionary class based on a hash set class . + /// Create a hash dictionary using a default equalityComparer for the keys. + /// Initial capacity of internal table will be 16 entries and threshold for + /// expansion is 66% fill. /// - public class HashDictionary : DictionaryBase, IDictionary - { - /// - /// Create a hash dictionary using a default equalityComparer for the keys. - /// Initial capacity of internal table will be 16 entries and threshold for - /// expansion is 66% fill. - /// - public HashDictionary() : this(EqualityComparer.Default) { } + public HashDictionary() : this(EqualityComparer.Default) { } - /// - /// Create a hash dictionary using a custom equalityComparer for the keys. - /// Initial capacity of internal table will be 16 entries and threshold for - /// expansion is 66% fill. - /// - /// The external key equalitySCG.Comparer - public HashDictionary(SCG.IEqualityComparer keyequalityComparer) - : base(keyequalityComparer) - { - pairs = new HashSet>(new KeyValuePairEqualityComparer(keyequalityComparer)); - } + /// + /// Create a hash dictionary using a custom equalityComparer for the keys. + /// Initial capacity of internal table will be 16 entries and threshold for + /// expansion is 66% fill. + /// + /// The external key equalitySCG.Comparer + public HashDictionary(SCG.IEqualityComparer keyEqualityComparer) + : base(keyEqualityComparer) + { + pairs = new HashSet>(new KeyValuePairEqualityComparer(keyEqualityComparer)); + } - /// - /// Create a hash dictionary using a custom equalityComparer and prescribing the - /// initial size of the dictionary and a non-default threshold for internal table expansion. - /// - /// The initial capacity. Will be rounded upwards to nearest - /// power of 2, at least 16. - /// The expansion threshold. Must be between 10% and 90%. - /// The external key equalitySCG.Comparer - public HashDictionary(int capacity, double fill, SCG.IEqualityComparer keyequalityComparer) - : base(keyequalityComparer) - { - pairs = new HashSet>(capacity, fill, new KeyValuePairEqualityComparer(keyequalityComparer)); - } + /// + /// Create a hash dictionary using a custom equalityComparer and prescribing the + /// initial size of the dictionary and a non-default threshold for internal table expansion. + /// + /// The initial capacity. Will be rounded upwards to nearest + /// power of 2, at least 16. + /// The expansion threshold. Must be between 10% and 90%. + /// The external key equalitySCG.Comparer + public HashDictionary(int capacity, double fill, SCG.IEqualityComparer keyEqualityComparer) + : base(keyEqualityComparer) + { + pairs = new HashSet>(capacity, fill, new KeyValuePairEqualityComparer(keyEqualityComparer)); } } \ No newline at end of file diff --git a/C5/Hashing/HashSet.cs b/C5/Hashing/HashSet.cs index 676d532e..2ef165b2 100644 --- a/C5/Hashing/HashSet.cs +++ b/C5/Hashing/HashSet.cs @@ -4,895 +4,894 @@ using System; using SCG = System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// A set collection class based on linear hashing +/// +public class HashSet : CollectionBase, ICollection { + #region Feature /// - /// A set collection class based on linear hashing + /// Enum class to assist printing of compilation alternatives. /// - public class HashSet : CollectionBase, ICollection + [Flags] + public enum Feature : short { - #region Feature /// - /// Enum class to assist printing of compilation alternatives. + /// Nothing /// - [Flags] - public enum Feature : short - { - /// - /// Nothing - /// - Dummy = 0, - /// - /// Buckets are of reference type - /// - RefTypeBucket = 1, - /// - /// Primary buckets are of value type - /// - ValueTypeBucket = 2, - /// - /// Using linear probing to resolve index clashes - /// - LinearProbing = 4, - /// - /// Shrink table when very sparsely filled - /// - ShrinkTable = 8, - /// - /// Use chaining to resolve index clashes - /// - Chaining = 16, - /// - /// Use hash function on item hash code - /// - InterHashing = 32, - /// - /// Use a universal family of hash functions on item hash code - /// - RandomInterHashing = 64 - } - - - private static readonly Feature features = Feature.Dummy - | Feature.RefTypeBucket - | Feature.Chaining - | Feature.RandomInterHashing; - - + Dummy = 0, /// - /// Show which implementation features was chosen at compilation time + /// Buckets are of reference type /// - public static Feature Features => features; - - #endregion - #region Fields - private int indexmask; - private int bits; - private int bitsc; - private readonly int origbits; - private int lastchosen; - private Bucket?[] table; - private readonly double fillfactor = 0.66; - private int resizethreshhold; + RefTypeBucket = 1, + /// + /// Primary buckets are of value type + /// + ValueTypeBucket = 2, + /// + /// Using linear probing to resolve index clashes + /// + LinearProbing = 4, + /// + /// Shrink table when very sparsely filled + /// + ShrinkTable = 8, + /// + /// Use chaining to resolve index clashes + /// + Chaining = 16, + /// + /// Use hash function on item hash code + /// + InterHashing = 32, + /// + /// Use a universal family of hash functions on item hash code + /// + RandomInterHashing = 64 + } - private static readonly Random Random = new Random(); - private uint _randomhashfactor; - #endregion + private static readonly Feature features = Feature.Dummy + | Feature.RefTypeBucket + | Feature.Chaining + | Feature.RandomInterHashing; - #region Events - /// - /// - /// - /// - public override EventType ListenableEvents => EventType.Basic; + /// + /// Show which implementation features was chosen at compilation time + /// + public static Feature Features => features; - #endregion + #endregion + #region Fields + private int indexmask; + private int bits; + private int bitsc; + private readonly int origbits; + private int lastchosen; + private Bucket?[] table; + private readonly double fillfactor = 0.66; + private int resizethreshhold; - #region Bucket nested class(es) - private class Bucket - { - internal T item; + private static readonly Random Random = new(); + private uint _randomhashfactor; - internal int hashval; //Cache! + #endregion - internal Bucket? overflow; + #region Events - internal Bucket(T item, int hashval, Bucket? overflow) - { - this.item = item; - this.hashval = hashval; - this.overflow = overflow; - } - } + /// + /// + /// + /// + public override EventType ListenableEvents => EventType.Basic; - #endregion + #endregion - #region Basic Util + #region Bucket nested class(es) + private class Bucket + { + internal T item; - private bool Equals(T i1, T i2) { return itemequalityComparer.Equals(i1, i2); } + internal int hashval; //Cache! - private int GetHashCode(T item) { return itemequalityComparer.GetHashCode(item); } + internal Bucket? overflow; - private int Hv2i(int hashval) + internal Bucket(T item, int hashval, Bucket? overflow) { - return (int)(((uint)hashval * _randomhashfactor) >> bitsc); + this.item = item; + this.hashval = hashval; + this.overflow = overflow; } + } - private void Expand() - { - Logger.Log(string.Format(string.Format("Expand to {0} bits", bits + 1))); - Resize(bits + 1); - } + #endregion - /* - void shrink() - { - if (bits > 3) - { - Logger.Log(string.Format(string.Format("Shrink to {0} bits", bits - 1))); - resize(bits - 1); - } - } */ + #region Basic Util + + private bool Equals(T i1, T i2) { return itemEqualityComparer.Equals(i1, i2); } + private int GetHashCode(T item) { return itemEqualityComparer.GetHashCode(item); } - private void Resize(int bits) + private int Hv2i(int hashval) + { + return (int)(((uint)hashval * _randomhashfactor) >> bitsc); + } + + private void Expand() + { + Logger.Log(string.Format(string.Format("Expand to {0} bits", bits + 1))); + Resize(bits + 1); + } + + /* + void shrink() + { + if (bits > 3) { - Logger.Log(string.Format(string.Format("Resize to {0} bits", bits))); - this.bits = bits; - bitsc = 32 - bits; - indexmask = (1 << bits) - 1; + Logger.Log(string.Format(string.Format("Shrink to {0} bits", bits - 1))); + resize(bits - 1); + } + } */ - Bucket[] newtable = new Bucket[indexmask + 1]; - for (int i = 0, s = table.Length; i < s; i++) - { - Bucket? b = table[i]; + private void Resize(int bits) + { + Logger.Log(string.Format(string.Format("Resize to {0} bits", bits))); + this.bits = bits; + bitsc = 32 - bits; + indexmask = (1 << bits) - 1; - while (b != null) - { - int j = Hv2i(b.hashval); + Bucket[] newtable = new Bucket[indexmask + 1]; - newtable[j] = new Bucket(b.item, b.hashval, newtable[j]); - b = b.overflow; - } + for (int i = 0, s = table.Length; i < s; i++) + { + Bucket? b = table[i]; + while (b != null) + { + int j = Hv2i(b.hashval); + + newtable[j] = new Bucket(b.item, b.hashval, newtable[j]); + b = b.overflow; } - table = newtable; - resizethreshhold = (int)(table.Length * fillfactor); - Logger.Log(string.Format(string.Format("Resize to {0} bits done", bits))); } - /// - /// Search for an item equal (according to itemequalityComparer) to the supplied item. - /// - /// - /// If true, add item to table if not found. - /// If true, update table entry if item found. - /// If true raise events - /// True if found - private bool SearchOrAdd(ref T item, bool add, bool update, bool raise) - { + table = newtable; + resizethreshhold = (int)(table.Length * fillfactor); + Logger.Log(string.Format(string.Format("Resize to {0} bits done", bits))); + } - int hashval = GetHashCode(item); - int i = Hv2i(hashval); - Bucket? b = table[i]; - Bucket? bold = null; + /// + /// Search for an item equal (according to itemequalityComparer) to the supplied item. + /// + /// + /// If true, add item to table if not found. + /// If true, update table entry if item found. + /// If true raise events + /// True if found + private bool SearchOrAdd(ref T item, bool add, bool update, bool raise) + { - if (b != null) + int hashval = GetHashCode(item); + int i = Hv2i(hashval); + Bucket? b = table[i]; + Bucket? bold = null; + + if (b != null) + { + while (b != null) { - while (b != null) + T olditem = b.item; + if (Equals(olditem, item)) { - T olditem = b.item; - if (Equals(olditem, item)) + if (update) { - if (update) - { - b.item = item; - } - if (raise && update) - { - RaiseForUpdate(item, olditem); - } - // bug20071112: - item = olditem; - return true; + b.item = item; } - - bold = b; - b = b.overflow; - } - - if (!add) - { - goto notfound; + if (raise && update) + { + RaiseForUpdate(item, olditem); + } + // bug20071112: + item = olditem; + return true; } - bold!.overflow = new Bucket(item, hashval, null); + bold = b; + b = b.overflow; } - else - { - if (!add) - { - goto notfound; - } - table[i] = new Bucket(item, hashval, null); - } - size++; - if (size > resizethreshhold) + if (!add) { - Expand(); + goto notfound; } - notfound: - if (raise && add) + bold!.overflow = new Bucket(item, hashval, null); + } + else + { + if (!add) { - RaiseForAdd(item); + goto notfound; } - if (update) - { - item = default; - } + table[i] = new Bucket(item, hashval, null); + } + size++; + if (size > resizethreshhold) + { + Expand(); + } + notfound: + if (raise && add) + { + RaiseForAdd(item); + } + + if (update) + { + item = default; + } + + return false; + } + + + private bool Remove(ref T item) + { + + if (size == 0) + { return false; } + int hashval = GetHashCode(item); + int index = Hv2i(hashval); + Bucket? b = table[index], bold; - private bool Remove(ref T item) + if (b == null) { + return false; + } - if (size == 0) + if (Equals(item, b.item)) + { + //ref + item = b.item; + table[index] = b.overflow; + } + else + { + bold = b; + b = b.overflow; + while (b != null && !Equals(item, b.item)) { - return false; + bold = b; + b = b.overflow; } - int hashval = GetHashCode(item); - int index = Hv2i(hashval); - Bucket? b = table[index], bold; - if (b == null) { return false; } - if (Equals(item, b.item)) - { - //ref - item = b.item; - table[index] = b.overflow; - } - else - { - bold = b; - b = b.overflow; - while (b != null && !Equals(item, b.item)) - { - bold = b; - b = b.overflow; - } - - if (b == null) - { - return false; - } - - //ref - item = b.item; - bold.overflow = b.overflow; - } - size--; - - return true; + //ref + item = b.item; + bold.overflow = b.overflow; } + size--; + return true; + } - private void ClearInner() - { - bits = origbits; - bitsc = 32 - bits; - indexmask = (1 << bits) - 1; - size = 0; - table = new Bucket[indexmask + 1]; - resizethreshhold = (int)(table.Length * fillfactor); - } - #endregion + private void ClearInner() + { + bits = origbits; + bitsc = 32 - bits; + indexmask = (1 << bits) - 1; + size = 0; + table = new Bucket[indexmask + 1]; + resizethreshhold = (int)(table.Length * fillfactor); + } - #region Constructors - /// - /// Create a hash set with natural item equalityComparer and default fill threshold (66%) - /// and initial table size (16). - /// - public HashSet() - : this(EqualityComparer.Default) { } + #endregion + #region Constructors + /// + /// Create a hash set with natural item equalityComparer and default fill threshold (66%) + /// and initial table size (16). + /// + public HashSet() + : this(EqualityComparer.Default) { } - /// - /// Create a hash set with external item equalityComparer and default fill threshold (66%) - /// and initial table size (16). - /// - /// The external item equalitySCG.Comparer - public HashSet(SCG.IEqualityComparer itemequalityComparer) - : this(16, itemequalityComparer) { } + /// + /// Create a hash set with external item equalityComparer and default fill threshold (66%) + /// and initial table size (16). + /// + /// The external item equalitySCG.Comparer + public HashSet(SCG.IEqualityComparer itemequalityComparer) + : this(16, itemequalityComparer) { } - /// - /// Create a hash set with external item equalityComparer and default fill threshold (66%) - /// - /// Initial table size (rounded to power of 2, at least 16) - /// The external item equalitySCG.Comparer - public HashSet(int capacity, SCG.IEqualityComparer itemequalityComparer) - : this(capacity, 0.66, itemequalityComparer) { } + /// + /// Create a hash set with external item equalityComparer and default fill threshold (66%) + /// + /// Initial table size (rounded to power of 2, at least 16) + /// The external item equalitySCG.Comparer + public HashSet(int capacity, SCG.IEqualityComparer itemequalityComparer) + : this(capacity, 0.66, itemequalityComparer) { } - /// - /// Create a hash set with external item equalityComparer. - /// - /// Initial table size (rounded to power of 2, at least 16) - /// Fill threshold (in range 10% to 90%) - /// The external item equalitySCG.Comparer - public HashSet(int capacity, double fill, SCG.IEqualityComparer itemequalityComparer) - : base(itemequalityComparer) - { - _randomhashfactor = (Debug.UseDeterministicHashing) ? 1529784659 : (2 * (uint)Random.Next() + 1) * 1529784659; - if (fill < 0.1 || fill > 0.9) - { - throw new ArgumentException("Fill outside valid range [0.1, 0.9]"); - } + /// + /// Create a hash set with external item equalityComparer. + /// + /// Initial table size (rounded to power of 2, at least 16) + /// Fill threshold (in range 10% to 90%) + /// The external item equalitySCG.Comparer + public HashSet(int capacity, double fill, SCG.IEqualityComparer itemequalityComparer) + : base(itemequalityComparer) + { + _randomhashfactor = (Debug.UseDeterministicHashing) ? 1529784659 : (2 * (uint)Random.Next() + 1) * 1529784659; - if (capacity <= 0) - { - throw new ArgumentException("Capacity must be non-negative"); - } - //this.itemequalityComparer = itemequalityComparer; - origbits = 4; - while (capacity - 1 >> origbits > 0) - { - origbits++; - } + if (fill < 0.1 || fill > 0.9) + { + throw new ArgumentException("Fill outside valid range [0.1, 0.9]"); + } - ClearInner(); + if (capacity <= 0) + { + throw new ArgumentException("Capacity must be non-negative"); + } + //this.itemequalityComparer = itemequalityComparer; + origbits = 4; + while (capacity - 1 >> origbits > 0) + { + origbits++; } + ClearInner(); + } - #endregion - #region IEditableCollection Members + #endregion - /// - /// The complexity of the Contains operation - /// - /// Always returns Speed.Constant - public virtual Speed ContainsSpeed => Speed.Constant; + #region IEditableCollection Members - /// - /// Check if an item is in the set - /// - /// The item to look for - /// True if set contains item - public virtual bool Contains(T item) { return SearchOrAdd(ref item, false, false, false); } + /// + /// The complexity of the Contains operation + /// + /// Always returns Speed.Constant + public virtual Speed ContainsSpeed => Speed.Constant; + /// + /// Check if an item is in the set + /// + /// The item to look for + /// True if set contains item + public virtual bool Contains(T item) { return SearchOrAdd(ref item, false, false, false); } - /// - /// Check if an item (collection equal to a given one) is in the set and - /// if so report the actual item object found. - /// - /// On entry, the item to look for. - /// On exit the item found, if any - /// True if set contains item - public virtual bool Find(ref T item) { return SearchOrAdd(ref item, false, false, false); } + /// + /// Check if an item (collection equal to a given one) is in the set and + /// if so report the actual item object found. + /// + /// On entry, the item to look for. + /// On exit the item found, if any + /// True if set contains item + public virtual bool Find(ref T item) { return SearchOrAdd(ref item, false, false, false); } - /// - /// Check if an item (collection equal to a given one) is in the set and - /// if so replace the item object in the set with the supplied one. - /// - /// The item object to update with - /// True if item was found (and updated) - public virtual bool Update(T item) - { UpdateCheck(); return SearchOrAdd(ref item, false, true, true); } - /// - /// Check if an item (collection equal to a given one) is in the set and - /// if so replace the item object in the set with the supplied one. - /// - /// The item object to update with - /// - /// True if item was found (and updated) - public virtual bool Update(T item, out T olditem) - { UpdateCheck(); olditem = item; return SearchOrAdd(ref olditem, false, true, true); } + /// + /// Check if an item (collection equal to a given one) is in the set and + /// if so replace the item object in the set with the supplied one. + /// + /// The item object to update with + /// True if item was found (and updated) + public virtual bool Update(T item) + { UpdateCheck(); return SearchOrAdd(ref item, false, true, true); } + /// + /// Check if an item (collection equal to a given one) is in the set and + /// if so replace the item object in the set with the supplied one. + /// + /// The item object to update with + /// + /// True if item was found (and updated) + public virtual bool Update(T item, out T olditem) + { UpdateCheck(); olditem = item; return SearchOrAdd(ref olditem, false, true, true); } - /// - /// Check if an item (collection equal to a given one) is in the set. - /// If found, report the actual item object in the set, - /// else add the supplied one. - /// - /// On entry, the item to look for or add. - /// On exit the actual object found, if any. - /// True if item was found - public virtual bool FindOrAdd(ref T item) - { UpdateCheck(); return SearchOrAdd(ref item, true, false, true); } + /// + /// Check if an item (collection equal to a given one) is in the set. + /// If found, report the actual item object in the set, + /// else add the supplied one. + /// + /// On entry, the item to look for or add. + /// On exit the actual object found, if any. + /// True if item was found + public virtual bool FindOrAdd(ref T item) + { UpdateCheck(); return SearchOrAdd(ref item, true, false, true); } - /// - /// Check if an item (collection equal to a supplied one) is in the set and - /// if so replace the item object in the set with the supplied one; else - /// add the supplied one. - /// - /// The item to look for and update or add - /// True if item was updated - public virtual bool UpdateOrAdd(T item) - { UpdateCheck(); return SearchOrAdd(ref item, true, true, true); } + + /// + /// Check if an item (collection equal to a supplied one) is in the set and + /// if so replace the item object in the set with the supplied one; else + /// add the supplied one. + /// + /// The item to look for and update or add + /// True if item was updated + public virtual bool UpdateOrAdd(T item) + { UpdateCheck(); return SearchOrAdd(ref item, true, true, true); } - /// - /// Check if an item (collection equal to a supplied one) is in the set and - /// if so replace the item object in the set with the supplied one; else - /// add the supplied one. - /// - /// The item to look for and update or add - /// - /// True if item was updated - public virtual bool UpdateOrAdd(T item, out T olditem) - { UpdateCheck(); olditem = item; return SearchOrAdd(ref olditem, true, true, true); } + /// + /// Check if an item (collection equal to a supplied one) is in the set and + /// if so replace the item object in the set with the supplied one; else + /// add the supplied one. + /// + /// The item to look for and update or add + /// + /// True if item was updated + public virtual bool UpdateOrAdd(T item, out T olditem) + { UpdateCheck(); olditem = item; return SearchOrAdd(ref olditem, true, true, true); } - /// - /// Remove an item from the set - /// - /// The item to remove - /// True if item was (found and) removed - public virtual bool Remove(T item) + /// + /// Remove an item from the set + /// + /// The item to remove + /// True if item was (found and) removed + public virtual bool Remove(T item) + { + UpdateCheck(); + if (Remove(ref item)) { - UpdateCheck(); - if (Remove(ref item)) - { - RaiseForRemove(item); - return true; - } - else - { - return false; - } + RaiseForRemove(item); + return true; } + else + { + return false; + } + } - /// - /// Remove an item from the set, reporting the actual matching item object. - /// - /// The value to remove. - /// The removed value. - /// True if item was found. - public virtual bool Remove(T item, out T removeditem) - { - UpdateCheck(); - removeditem = item; - if (Remove(ref removeditem)) - { - RaiseForRemove(removeditem); - return true; - } - else - { - return false; - } + /// + /// Remove an item from the set, reporting the actual matching item object. + /// + /// The value to remove. + /// The removed value. + /// True if item was found. + public virtual bool Remove(T item, out T removeditem) + { + UpdateCheck(); + removeditem = item; + if (Remove(ref removeditem)) + { + RaiseForRemove(removeditem); + return true; } + else + { + return false; + } + } - /// - /// Remove all items in a supplied collection from this set. - /// - /// The items to remove. - public virtual void RemoveAll(SCG.IEnumerable items) - { - UpdateCheck(); - RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(this); - bool raise = raiseHandler.MustFire; - T jtem; - foreach (var item in items) + /// + /// Remove all items in a supplied collection from this set. + /// + /// The items to remove. + public virtual void RemoveAll(SCG.IEnumerable items) + { + UpdateCheck(); + RaiseForRemoveAllHandler raiseHandler = new(this); + bool raise = raiseHandler.MustFire; + T jtem; + foreach (var item in items) + { + jtem = item; if (Remove(ref jtem) && raise) { - jtem = item; if (Remove(ref jtem) && raise) - { - raiseHandler.Remove(jtem); - } + raiseHandler.Remove(jtem); } + } - if (raise) - { - raiseHandler.Raise(); - } + if (raise) + { + raiseHandler.Raise(); } + } - /// - /// Remove all items from the set, resetting internal table to initial size. - /// - public virtual void Clear() + /// + /// Remove all items from the set, resetting internal table to initial size. + /// + public virtual void Clear() + { + UpdateCheck(); + int oldsize = size; + ClearInner(); + if (ActiveEvents != 0 && oldsize > 0) { - UpdateCheck(); - int oldsize = size; - ClearInner(); - if (ActiveEvents != 0 && oldsize > 0) - { - RaiseCollectionCleared(true, oldsize); - RaiseCollectionChanged(); - } + RaiseCollectionCleared(true, oldsize); + RaiseCollectionChanged(); } + } - /// - /// Remove all items *not* in a supplied collection from this set. - /// - /// The items to retain - public virtual void RetainAll(SCG.IEnumerable items) - { - UpdateCheck(); + /// + /// Remove all items *not* in a supplied collection from this set. + /// + /// The items to retain + public virtual void RetainAll(SCG.IEnumerable items) + { + UpdateCheck(); - HashSet aux = new HashSet(EqualityComparer); + HashSet aux = new(EqualityComparer); - //This only works for sets: - foreach (var item in items) + //This only works for sets: + foreach (var item in items) + { + if (Contains(item)) { - if (Contains(item)) - { - T jtem = item; + T jtem = item; - aux.SearchOrAdd(ref jtem, true, false, false); - } + aux.SearchOrAdd(ref jtem, true, false, false); } + } - if (size == aux.size) - { - return; - } + if (size == aux.size) + { + return; + } - CircularQueue? wasRemoved = null; - if ((ActiveEvents & EventType.Removed) != 0) + CircularQueue? wasRemoved = null; + if ((ActiveEvents & EventType.Removed) != 0) + { + wasRemoved = new CircularQueue(); + foreach (T item in this) { - wasRemoved = new CircularQueue(); - foreach (T item in this) + if (!aux.Contains(item)) { - if (!aux.Contains(item)) - { - wasRemoved.Enqueue(item); - } + wasRemoved.Enqueue(item); } } + } - table = aux.table; - size = aux.size; + table = aux.table; + size = aux.size; - indexmask = aux.indexmask; - resizethreshhold = aux.resizethreshhold; - bits = aux.bits; - bitsc = aux.bitsc; + indexmask = aux.indexmask; + resizethreshhold = aux.resizethreshhold; + bits = aux.bits; + bitsc = aux.bitsc; - _randomhashfactor = aux._randomhashfactor; + _randomhashfactor = aux._randomhashfactor; - if ((ActiveEvents & EventType.Removed) != 0) - { - RaiseForRemoveAll(wasRemoved); - } - else if ((ActiveEvents & EventType.Changed) != 0) - { - RaiseCollectionChanged(); - } + if ((ActiveEvents & EventType.Removed) != 0) + { + RaiseForRemoveAll(wasRemoved); } + else if ((ActiveEvents & EventType.Changed) != 0) + { + RaiseCollectionChanged(); + } + } - /// - /// Check if all items in a supplied collection is in this set - /// (ignoring multiplicities). - /// - /// The items to look for. - /// True if all items are found. - public virtual bool ContainsAll(SCG.IEnumerable items) + /// + /// Check if all items in a supplied collection is in this set + /// (ignoring multiplicities). + /// + /// The items to look for. + /// True if all items are found. + public virtual bool ContainsAll(SCG.IEnumerable items) + { + foreach (var item in items) { - foreach (var item in items) + if (!Contains(item)) { - if (!Contains(item)) - { - return false; - } + return false; } - - return true; } + return true; + } - /// - /// Create an array containing all items in this set (in enumeration order). - /// - /// The array - public override T[] ToArray() - { - T[] res = new T[size]; - int index = 0; - for (int i = 0; i < table.Length; i++) + /// + /// Create an array containing all items in this set (in enumeration order). + /// + /// The array + public override T[] ToArray() + { + T[] res = new T[size]; + int index = 0; + + for (int i = 0; i < table.Length; i++) + { + Bucket? b = table[i]; + while (b != null) { - Bucket? b = table[i]; - while (b != null) - { - res[index++] = b.item; - b = b.overflow; - } + res[index++] = b.item; + b = b.overflow; } - - System.Diagnostics.Debug.Assert(size == index); - return res; } + System.Diagnostics.Debug.Assert(size == index); + return res; + } - /// - /// Count the number of times an item is in this set (either 0 or 1). - /// - /// The item to look for. - /// 1 if item is in set, 0 else - public virtual int ContainsCount(T item) { return Contains(item) ? 1 : 0; } - /// - /// - /// - /// - public virtual ICollectionValue UniqueItems() { return this; } + /// + /// Count the number of times an item is in this set (either 0 or 1). + /// + /// The item to look for. + /// 1 if item is in set, 0 else + public virtual int ContainsCount(T item) { return Contains(item) ? 1 : 0; } - /// - /// - /// - /// - public virtual ICollectionValue> ItemMultiplicities() - { - return new MultiplicityOne(this); - } + /// + /// + /// + /// + public virtual ICollectionValue UniqueItems() { return this; } - /// - /// Remove all (at most 1) copies of item from this set. - /// - /// The item to remove - public virtual void RemoveAllCopies(T item) { Remove(item); } + /// + /// + /// + /// + public virtual ICollectionValue> ItemMultiplicities() + { + return new MultiplicityOne(this); + } - #endregion + /// + /// Remove all (at most 1) copies of item from this set. + /// + /// The item to remove + public virtual void RemoveAllCopies(T item) { Remove(item); } - #region IEnumerable Members + #endregion + #region IEnumerable Members - /// - /// Choose some item of this collection. - /// - /// if collection is empty. - /// - public override T Choose() + + /// + /// Choose some item of this collection. + /// + /// if collection is empty. + /// + public override T Choose() + { + int len = table.Length; + if (size == 0) { - int len = table.Length; - if (size == 0) - { - throw new NoSuchItemException(); - } + throw new NoSuchItemException(); + } - do { if (++lastchosen >= len) { lastchosen = 0; } } while (table[lastchosen] == null); + do { if (++lastchosen >= len) { lastchosen = 0; } } while (table[lastchosen] == null); - return (table[lastchosen])!.item; - } + return (table[lastchosen])!.item; + } - /// - /// Create an enumerator for this set. - /// - /// The enumerator - public override SCG.IEnumerator GetEnumerator() - { - int index = -1; - int mystamp = stamp; - int len = table.Length; + /// + /// Create an enumerator for this set. + /// + /// The enumerator + public override SCG.IEnumerator GetEnumerator() + { + int index = -1; + int mystamp = stamp; + int len = table.Length; - Bucket? b = null; + Bucket? b = null; - while (true) + while (true) + { + if (mystamp != stamp) { - if (mystamp != stamp) - { - throw new CollectionModifiedException(); - } + throw new CollectionModifiedException(); + } - if (b == null || b.overflow == null) + if (b == null || b.overflow == null) + { + do { - do + if (++index >= len) { - if (++index >= len) - { - yield break; - } - } while (table[index] == null); - - b = table[index]; - yield return b!.item; - } - else - { - b = b.overflow; - yield return b.item; - } + yield break; + } + } while (table[index] == null); + + b = table[index]; + yield return b!.item; + } + else + { + b = b.overflow; + yield return b.item; } } + } - #endregion + #endregion - #region ISink Members - /// - /// Report if this is a set collection. - /// - /// Always false - public virtual bool AllowsDuplicates => false; + #region ISink Members + /// + /// Report if this is a set collection. + /// + /// Always false + public virtual bool AllowsDuplicates => false; - /// - /// By convention this is true for any collection with set semantics. - /// - /// True if only one representative of a group of equal items - /// is kept in the collection together with the total count. - public virtual bool DuplicatesByCounting => true; + /// + /// By convention this is true for any collection with set semantics. + /// + /// True if only one representative of a group of equal items + /// is kept in the collection together with the total count. + public virtual bool DuplicatesByCounting => true; - /// - /// Add an item to this set. - /// - /// The item to add. - /// True if item was added (i.e. not found) - public virtual bool Add(T item) - { - UpdateCheck(); - return !SearchOrAdd(ref item, true, false, true); - } + /// + /// Add an item to this set. + /// + /// The item to add. + /// True if item was added (i.e. not found) + public virtual bool Add(T item) + { + UpdateCheck(); + return !SearchOrAdd(ref item, true, false, true); + } - /// - /// Add an item to this set. - /// - /// The item to add. - void SCG.ICollection.Add(T item) + /// + /// Add an item to this set. + /// + /// The item to add. + void SCG.ICollection.Add(T item) + { + Add(item); + } + + /// + /// Add the elements from another collection with a more specialized item type + /// to this collection. Since this + /// collection has set semantics, only items not already in the collection + /// will be added. + /// + /// The items to add + public virtual void AddAll(SCG.IEnumerable items) + { + UpdateCheck(); + bool wasChanged = false; + bool raiseAdded = (ActiveEvents & EventType.Added) != 0; + CircularQueue? wasAdded = raiseAdded ? new CircularQueue() : null; + foreach (T item in items) { - Add(item); - } + T jtem = item; - /// - /// Add the elements from another collection with a more specialized item type - /// to this collection. Since this - /// collection has set semantics, only items not already in the collection - /// will be added. - /// - /// The items to add - public virtual void AddAll(SCG.IEnumerable items) - { - UpdateCheck(); - bool wasChanged = false; - bool raiseAdded = (ActiveEvents & EventType.Added) != 0; - CircularQueue? wasAdded = raiseAdded ? new CircularQueue() : null; - foreach (T item in items) + if (!SearchOrAdd(ref jtem, true, false, false)) { - T jtem = item; - - if (!SearchOrAdd(ref jtem, true, false, false)) + wasChanged = true; + if (raiseAdded) { - wasChanged = true; - if (raiseAdded) - { - wasAdded?.Enqueue(item); - } + wasAdded?.Enqueue(item); } } - //TODO: implement a RaiseForAddAll() method - if (raiseAdded & wasChanged) + } + //TODO: implement a RaiseForAddAll() method + if (raiseAdded & wasChanged) + { + if (wasAdded != null) { - if (wasAdded != null) + foreach (T item in wasAdded) { - foreach (T item in wasAdded) - { - RaiseItemsAdded(item, 1); - } + RaiseItemsAdded(item, 1); } } + } - if (((ActiveEvents & EventType.Changed) != 0 && wasChanged)) - { - RaiseCollectionChanged(); - } + if (((ActiveEvents & EventType.Changed) != 0 && wasChanged)) + { + RaiseCollectionChanged(); } + } - #endregion + #endregion - #region Diagnostics + #region Diagnostics - /// - /// Test internal structure of data (invariants) - /// - /// True if pass - public virtual bool Check() - { - int count = 0; - bool retval = true; + /// + /// Test internal structure of data (invariants) + /// + /// True if pass + public virtual bool Check() + { + int count = 0; + bool retval = true; - if (bitsc != 32 - bits) - { - Logger.Log(string.Format("bitsc != 32 - bits ({0}, {1})", bitsc, bits)); - retval = false; - } - if (indexmask != (1 << bits) - 1) - { - Logger.Log(string.Format("indexmask != (1 << bits) - 1 ({0}, {1})", indexmask, bits)); - retval = false; - } - if (table.Length != indexmask + 1) - { - Logger.Log(string.Format("table.Length != indexmask + 1 ({0}, {1})", table.Length, indexmask)); - retval = false; - } - if (bitsc != 32 - bits) - { - Logger.Log(string.Format("resizethreshhold != (int)(table.Length * fillfactor) ({0}, {1}, {2})", resizethreshhold, table.Length, fillfactor)); - retval = false; - } + if (bitsc != 32 - bits) + { + Logger.Log(string.Format("bitsc != 32 - bits ({0}, {1})", bitsc, bits)); + retval = false; + } + if (indexmask != (1 << bits) - 1) + { + Logger.Log(string.Format("indexmask != (1 << bits) - 1 ({0}, {1})", indexmask, bits)); + retval = false; + } + if (table.Length != indexmask + 1) + { + Logger.Log(string.Format("table.Length != indexmask + 1 ({0}, {1})", table.Length, indexmask)); + retval = false; + } + if (bitsc != 32 - bits) + { + Logger.Log(string.Format("resizethreshhold != (int)(table.Length * fillfactor) ({0}, {1}, {2})", resizethreshhold, table.Length, fillfactor)); + retval = false; + } - for (int i = 0, s = table.Length; i < s; i++) + for (int i = 0, s = table.Length; i < s; i++) + { + int level = 0; + Bucket? b = table[i]; + while (b != null) { - int level = 0; - Bucket? b = table[i]; - while (b != null) + if (i != Hv2i(b.hashval)) { - if (i != Hv2i(b.hashval)) - { - Logger.Log(string.Format("Bad cell item={0}, hashval={1}, index={2}, level={3}", b.item, b.hashval, i, level)); - retval = false; - } - - count++; - level++; - b = b.overflow; + Logger.Log(string.Format("Bad cell item={0}, hashval={1}, index={2}, level={3}", b.item, b.hashval, i, level)); + retval = false; } - } - if (count != size) - { - Logger.Log(string.Format("size({0}) != count({1})", size, count)); - retval = false; + count++; + level++; + b = b.overflow; } + } - return retval; + if (count != size) + { + Logger.Log(string.Format("size({0}) != count({1})", size, count)); + retval = false; } + return retval; + } - /// - /// Produce statistics on distribution of bucket sizes. Current implementation is incomplete. - /// - /// Histogram data. - public ISortedDictionary BucketCostDistribution() + + /// + /// Produce statistics on distribution of bucket sizes. Current implementation is incomplete. + /// + /// Histogram data. + public ISortedDictionary BucketCostDistribution() + { + TreeDictionary res = new(); + for (int i = 0, s = table.Length; i < s; i++) { - TreeDictionary res = new TreeDictionary(); - for (int i = 0, s = table.Length; i < s; i++) - { - int count = 0; - Bucket? b = table[i]; + int count = 0; + Bucket? b = table[i]; - while (b != null) - { - count++; - b = b.overflow; - } - if (res.Contains(count)) - { - res[count]++; - } - else - { - res[count] = 1; - } + while (b != null) + { + count++; + b = b.overflow; + } + if (res.Contains(count)) + { + res[count]++; + } + else + { + res[count] = 1; } - - return res; } - #endregion + return res; } + + #endregion } diff --git a/C5/Heaps/IntervalHeap.cs b/C5/Heaps/IntervalHeap.cs index 2a3e1f8c..c96fbea9 100644 --- a/C5/Heaps/IntervalHeap.cs +++ b/C5/Heaps/IntervalHeap.cs @@ -4,1104 +4,1103 @@ using System; using SCG = System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// A priority queue class based on an interval heap data structure. +/// +/// The item type +public class IntervalHeap : CollectionValueBase, IPriorityQueue { + #region Events + /// - /// A priority queue class based on an interval heap data structure. + /// /// - /// The item type - public class IntervalHeap : CollectionValueBase, IPriorityQueue + /// + public override EventType ListenableEvents => EventType.Basic; + + #endregion + + #region Fields + private struct Interval { - #region Events + internal T first, last; internal Handle? firsthandle, lasthandle; - /// - /// - /// - /// - public override EventType ListenableEvents => EventType.Basic; - #endregion + public override string ToString() { return string.Format("[{0}; {1}]", first, last); } + } - #region Fields - private struct Interval - { - internal T first, last; internal Handle? firsthandle, lasthandle; + private int stamp; + private readonly SCG.IComparer comparer; + private readonly SCG.IEqualityComparer itemequalityComparer; + private Interval[] heap; + private int size; + #endregion + #region Util + // heapifyMin and heapifyMax and their auxiliaries - public override string ToString() { return string.Format("[{0}; {1}]", first, last); } - } + private void SwapFirstWithLast(int cell1, int cell2) + { + T first = heap[cell1].first; + Handle firsthandle = heap[cell1].firsthandle!; + UpdateFirst(cell1, heap[cell2].last, heap[cell2].lasthandle); + UpdateLast(cell2, first, firsthandle); + } + + private void SwapLastWithLast(int cell1, int cell2) + { + T last = heap[cell2].last; + Handle lasthandle = heap[cell2].lasthandle!; + UpdateLast(cell2, heap[cell1].last, heap[cell1].lasthandle!); + UpdateLast(cell1, last, lasthandle); + } - private int stamp; - private readonly SCG.IComparer comparer; - private readonly SCG.IEqualityComparer itemequalityComparer; - private Interval[] heap; - private int size; - #endregion + private void SwapFirstWithFirst(int cell1, int cell2) + { + T first = heap[cell2].first; + Handle firsthandle = heap[cell2].firsthandle!; + UpdateFirst(cell2, heap[cell1].first, heap[cell1].firsthandle); + UpdateFirst(cell1, first, firsthandle); + } - #region Util - // heapifyMin and heapifyMax and their auxiliaries + private bool HeapifyMin(int cell) + { + bool swappedroot = false; + // If first > last, swap them + if (2 * cell + 1 < size && comparer.Compare(heap[cell].first, heap[cell].last) > 0) + { + swappedroot = true; + SwapFirstWithLast(cell, cell); + } - private void SwapFirstWithLast(int cell1, int cell2) + int currentmin = cell, l = 2 * cell + 1, r = l + 1; + if (2 * l < size && comparer.Compare(heap[l].first, heap[currentmin].first) < 0) { - T first = heap[cell1].first; - Handle firsthandle = heap[cell1].firsthandle!; - UpdateFirst(cell1, heap[cell2].last, heap[cell2].lasthandle); - UpdateLast(cell2, first, firsthandle); + currentmin = l; } - private void SwapLastWithLast(int cell1, int cell2) + if (2 * r < size && comparer.Compare(heap[r].first, heap[currentmin].first) < 0) { - T last = heap[cell2].last; - Handle lasthandle = heap[cell2].lasthandle!; - UpdateLast(cell2, heap[cell1].last, heap[cell1].lasthandle!); - UpdateLast(cell1, last, lasthandle); + currentmin = r; } - private void SwapFirstWithFirst(int cell1, int cell2) + if (currentmin != cell) { - T first = heap[cell2].first; - Handle firsthandle = heap[cell2].firsthandle!; - UpdateFirst(cell2, heap[cell1].first, heap[cell1].firsthandle); - UpdateFirst(cell1, first, firsthandle); + // cell has at least one daughter, and it contains the min + SwapFirstWithFirst(currentmin, cell); + HeapifyMin(currentmin); } + return swappedroot; + } - private bool HeapifyMin(int cell) + private bool HeapifyMax(int cell) + { + bool swappedroot = false; + if (2 * cell + 1 < size && comparer.Compare(heap[cell].last, heap[cell].first) < 0) { - bool swappedroot = false; - // If first > last, swap them - if (2 * cell + 1 < size && comparer.Compare(heap[cell].first, heap[cell].last) > 0) + swappedroot = true; + SwapFirstWithLast(cell, cell); + } + + int currentmax = cell, l = 2 * cell + 1, r = l + 1; + bool firstmax = false; // currentmax's first field holds max + if (2 * l + 1 < size) + { // both l.first and l.last exist + if (comparer.Compare(heap[l].last, heap[currentmax].last) > 0) { - swappedroot = true; - SwapFirstWithLast(cell, cell); + currentmax = l; } - - int currentmin = cell, l = 2 * cell + 1, r = l + 1; - if (2 * l < size && comparer.Compare(heap[l].first, heap[currentmin].first) < 0) + } + else if (2 * l + 1 == size) + { // only l.first exists + if (comparer.Compare(heap[l].first, heap[currentmax].last) > 0) { - currentmin = l; + currentmax = l; + firstmax = true; } + } - if (2 * r < size && comparer.Compare(heap[r].first, heap[currentmin].first) < 0) + if (2 * r + 1 < size) + { // both r.first and r.last exist + if (comparer.Compare(heap[r].last, heap[currentmax].last) > 0) { - currentmin = r; + currentmax = r; } - - if (currentmin != cell) + } + else if (2 * r + 1 == size) + { // only r.first exists + if (comparer.Compare(heap[r].first, heap[currentmax].last) > 0) { - // cell has at least one daughter, and it contains the min - SwapFirstWithFirst(currentmin, cell); - HeapifyMin(currentmin); + currentmax = r; + firstmax = true; } - return swappedroot; } - private bool HeapifyMax(int cell) + if (currentmax != cell) { - bool swappedroot = false; - if (2 * cell + 1 < size && comparer.Compare(heap[cell].last, heap[cell].first) < 0) + // The cell has at least one daughter, and it contains the max + if (firstmax) { - swappedroot = true; - SwapFirstWithLast(cell, cell); - } - - int currentmax = cell, l = 2 * cell + 1, r = l + 1; - bool firstmax = false; // currentmax's first field holds max - if (2 * l + 1 < size) - { // both l.first and l.last exist - if (comparer.Compare(heap[l].last, heap[currentmax].last) > 0) - { - currentmax = l; - } + SwapFirstWithLast(currentmax, cell); } - else if (2 * l + 1 == size) - { // only l.first exists - if (comparer.Compare(heap[l].first, heap[currentmax].last) > 0) - { - currentmax = l; - firstmax = true; - } + else + { + SwapLastWithLast(currentmax, cell); } - if (2 * r + 1 < size) - { // both r.first and r.last exist - if (comparer.Compare(heap[r].last, heap[currentmax].last) > 0) - { - currentmax = r; - } - } - else if (2 * r + 1 == size) - { // only r.first exists - if (comparer.Compare(heap[r].first, heap[currentmax].last) > 0) - { - currentmax = r; - firstmax = true; - } - } + HeapifyMax(currentmax); + } + return swappedroot; + } - if (currentmax != cell) + private void BubbleUpMin(int i) + { + if (i > 0) + { + T min = heap[i].first, iv = min; + Handle minhandle = heap[i].firsthandle!; + _ = (i + 1) / 2 - 1; + + while (i > 0) { - // The cell has at least one daughter, and it contains the max - if (firstmax) + int p; + if (comparer.Compare(iv, min = heap[p = (i + 1) / 2 - 1].first) < 0) { - SwapFirstWithLast(currentmax, cell); + UpdateFirst(i, min, heap[p].firsthandle); + i = p; } else { - SwapLastWithLast(currentmax, cell); + break; } - - HeapifyMax(currentmax); } - return swappedroot; + + UpdateFirst(i, iv, minhandle); } + } - private void BubbleUpMin(int i) + private void BubbleUpMax(int i) + { + if (i > 0) { - if (i > 0) - { - T min = heap[i].first, iv = min; - Handle minhandle = heap[i].firsthandle!; - _ = (i + 1) / 2 - 1; + T max = heap[i].last, iv = max; + Handle maxhandle = heap[i].lasthandle!; + _ = (i + 1) / 2 - 1; - while (i > 0) + while (i > 0) + { + int p; + if (comparer.Compare(iv, max = heap[p = (i + 1) / 2 - 1].last) > 0) { - int p; - if (comparer.Compare(iv, min = heap[p = (i + 1) / 2 - 1].first) < 0) - { - UpdateFirst(i, min, heap[p].firsthandle); - i = p; - } - else - { - break; - } + UpdateLast(i, max, heap[p].lasthandle); + i = p; } - - UpdateFirst(i, iv, minhandle); - } - } - - private void BubbleUpMax(int i) - { - if (i > 0) - { - T max = heap[i].last, iv = max; - Handle maxhandle = heap[i].lasthandle!; - _ = (i + 1) / 2 - 1; - - while (i > 0) + else { - int p; - if (comparer.Compare(iv, max = heap[p = (i + 1) / 2 - 1].last) > 0) - { - UpdateLast(i, max, heap[p].lasthandle); - i = p; - } - else - { - break; - } + break; } + } - UpdateLast(i, iv, maxhandle); + UpdateLast(i, iv, maxhandle); - } } + } - #endregion + #endregion - #region Constructors - /// - /// Create an interval heap with natural item comparer and default initial capacity (16) - /// - public IntervalHeap() : this(16) { } + #region Constructors + /// + /// Create an interval heap with natural item comparer and default initial capacity (16) + /// + public IntervalHeap() : this(16) { } - /// - /// Create an interval heap with external item comparer and default initial capacity (16) - /// - /// The external comparer - public IntervalHeap(SCG.IComparer comparer) : this(16, comparer) { } + /// + /// Create an interval heap with external item comparer and default initial capacity (16) + /// + /// The external comparer + public IntervalHeap(SCG.IComparer comparer) : this(16, comparer) { } - //TODO: maybe remove - /// - /// Create an interval heap with natural item comparer and prescribed initial capacity - /// - /// The initial capacity - public IntervalHeap(int capacity) : this(capacity, SCG.Comparer.Default, EqualityComparer.Default) { } + //TODO: maybe remove + /// + /// Create an interval heap with natural item comparer and prescribed initial capacity + /// + /// The initial capacity + public IntervalHeap(int capacity) : this(capacity, SCG.Comparer.Default, EqualityComparer.Default) { } - /// - /// Create an interval heap with external item comparer and prescribed initial capacity - /// - /// The initial capacity - /// The external comparer - public IntervalHeap(int capacity, SCG.IComparer comparer) : this(capacity, comparer, new ComparerZeroHashCodeEqualityComparer(comparer)) { } + /// + /// Create an interval heap with external item comparer and prescribed initial capacity + /// + /// The initial capacity + /// The external comparer + public IntervalHeap(int capacity, SCG.IComparer comparer) : this(capacity, comparer, new ComparerZeroHashCodeEqualityComparer(comparer)) { } - private IntervalHeap(int capacity, SCG.IComparer comparer, SCG.IEqualityComparer itemequalityComparer) + private IntervalHeap(int capacity, SCG.IComparer comparer, SCG.IEqualityComparer itemequalityComparer) + { + this.comparer = comparer ?? throw new NullReferenceException("Item comparer cannot be null"); + this.itemequalityComparer = itemequalityComparer ?? throw new NullReferenceException("Item equality comparer cannot be null"); + int length = 1; + while (length < capacity) { - this.comparer = comparer ?? throw new NullReferenceException("Item comparer cannot be null"); - this.itemequalityComparer = itemequalityComparer ?? throw new NullReferenceException("Item equality comparer cannot be null"); - int length = 1; - while (length < capacity) - { - length <<= 1; - } - - heap = new Interval[length]; + length <<= 1; } - #endregion + heap = new Interval[length]; + } - #region IPriorityQueue Members + #endregion - /// - /// Find the current least item of this priority queue. - /// if queue is empty - /// - /// The least item. - public T FindMin() - { - if (size == 0) - { - throw new NoSuchItemException(); - } + #region IPriorityQueue Members - return heap[0].first; + /// + /// Find the current least item of this priority queue. + /// if queue is empty + /// + /// The least item. + public T FindMin() + { + if (size == 0) + { + throw new NoSuchItemException(); } + return heap[0].first; + } + - /// - /// Remove the least item from this priority queue. - /// if queue is empty - /// - /// The removed item. - public T DeleteMin() - { - return DeleteMin(out _); - } + /// + /// Remove the least item from this priority queue. + /// if queue is empty + /// + /// The removed item. + public T DeleteMin() + { + return DeleteMin(out _); + } - /// - /// Find the current largest item of this priority queue. - /// if queue is empty - /// - /// The largest item. - public T FindMax() + /// + /// Find the current largest item of this priority queue. + /// if queue is empty + /// + /// The largest item. + public T FindMax() + { + if (size == 0) { - if (size == 0) - { - throw new NoSuchItemException("Heap is empty"); - } - else if (size == 1) - { - return heap[0].first; - } - else - { - return heap[0].last; - } + throw new NoSuchItemException("Heap is empty"); } - - - /// - /// Remove the largest item from this priority queue. - /// if queue is empty - /// - /// The removed item. - public T DeleteMax() + else if (size == 1) + { + return heap[0].first; + } + else { - return DeleteMax(out _); + return heap[0].last; } + } - /// - /// The comparer object supplied at creation time for this collection - /// - /// The comparer - public SCG.IComparer Comparer => comparer; + /// + /// Remove the largest item from this priority queue. + /// if queue is empty + /// + /// The removed item. + public T DeleteMax() + { + return DeleteMax(out _); + } - #endregion - #region IExtensible Members + /// + /// The comparer object supplied at creation time for this collection + /// + /// The comparer + public SCG.IComparer Comparer => comparer; - /// - /// If true any call of an updating operation will throw an - /// ReadOnlyCollectionException - /// - /// True if this collection is read-only. - public bool IsReadOnly => false; + #endregion - /// - /// - /// - /// True since this collection has bag semantics - public bool AllowsDuplicates => true; + #region IExtensible Members - /// - /// Value is null since this collection has no equality concept for its items. - /// - /// - public virtual SCG.IEqualityComparer EqualityComparer => itemequalityComparer; + /// + /// If true any call of an updating operation will throw an + /// ReadOnlyCollectionException + /// + /// True if this collection is read-only. + public bool IsReadOnly => false; - /// - /// By convention this is true for any collection with set semantics. - /// - /// True if only one representative of a group of equal items - /// is kept in the collection together with the total count. - public virtual bool DuplicatesByCounting => false; + /// + /// + /// + /// True since this collection has bag semantics + public bool AllowsDuplicates => true; + + /// + /// Value is null since this collection has no equality concept for its items. + /// + /// + public virtual SCG.IEqualityComparer EqualityComparer => itemequalityComparer; + /// + /// By convention this is true for any collection with set semantics. + /// + /// True if only one representative of a group of equal items + /// is kept in the collection together with the total count. + public virtual bool DuplicatesByCounting => false; - /// - /// Add an item to this priority queue. - /// - /// The item to add. - /// True - public bool Add(T item) + + /// + /// Add an item to this priority queue. + /// + /// The item to add. + /// True + public bool Add(T item) + { + stamp++; + if (Add(null, item)) { - stamp++; - if (Add(null, item)) - { - RaiseItemsAdded(item, 1); - RaiseCollectionChanged(); - return true; - } - return false; + RaiseItemsAdded(item, 1); + RaiseCollectionChanged(); + return true; } + return false; + } - private bool Add(Handle? itemhandle, T item) + private bool Add(Handle? itemhandle, T item) + { + if (size == 0) { - if (size == 0) - { - size = 1; - UpdateFirst(0, item, itemhandle); - return true; - } - - if (size == 2 * heap.Length) - { - Interval[] newheap = new Interval[2 * heap.Length]; + size = 1; + UpdateFirst(0, item, itemhandle); + return true; + } - Array.Copy(heap, newheap, heap.Length); - heap = newheap; - } + if (size == 2 * heap.Length) + { + Interval[] newheap = new Interval[2 * heap.Length]; - if (size % 2 == 0) - { - int i = size / 2, p = (i + 1) / 2 - 1; - T tmp = heap[p].last; + Array.Copy(heap, newheap, heap.Length); + heap = newheap; + } - if (comparer.Compare(item, tmp) > 0) - { - UpdateFirst(i, tmp, heap[p].lasthandle); - UpdateLast(p, item, itemhandle); - BubbleUpMax(p); - } - else - { - UpdateFirst(i, item, itemhandle); + if (size % 2 == 0) + { + int i = size / 2, p = (i + 1) / 2 - 1; + T tmp = heap[p].last; - if (comparer.Compare(item, heap[p].first) < 0) - { - BubbleUpMin(i); - } - } + if (comparer.Compare(item, tmp) > 0) + { + UpdateFirst(i, tmp, heap[p].lasthandle); + UpdateLast(p, item, itemhandle); + BubbleUpMax(p); } else { - int i = size / 2; - T other = heap[i].first; + UpdateFirst(i, item, itemhandle); - if (comparer.Compare(item, other) < 0) + if (comparer.Compare(item, heap[p].first) < 0) { - UpdateLast(i, other, heap[i].firsthandle); - UpdateFirst(i, item, itemhandle); BubbleUpMin(i); } - else - { - UpdateLast(i, item, itemhandle); - BubbleUpMax(i); - } } - size++; - - return true; } - - private void UpdateLast(int cell, T item, Handle? handle) + else { - heap[cell].last = item; - if (handle != null) + int i = size / 2; + T other = heap[i].first; + + if (comparer.Compare(item, other) < 0) { - handle.index = 2 * cell + 1; + UpdateLast(i, other, heap[i].firsthandle); + UpdateFirst(i, item, itemhandle); + BubbleUpMin(i); + } + else + { + UpdateLast(i, item, itemhandle); + BubbleUpMax(i); } - - heap[cell].lasthandle = handle; } + size++; + + return true; + } - private void UpdateFirst(int cell, T item, Handle? handle) + private void UpdateLast(int cell, T item, Handle? handle) + { + heap[cell].last = item; + if (handle != null) { - heap[cell].first = item; - if (handle != null) - { - handle.index = 2 * cell; - } + handle.index = 2 * cell + 1; + } + + heap[cell].lasthandle = handle; + } - heap[cell].firsthandle = handle; + private void UpdateFirst(int cell, T item, Handle? handle) + { + heap[cell].first = item; + if (handle != null) + { + handle.index = 2 * cell; } + heap[cell].firsthandle = handle; + } - /// - /// Add the elements from another collection with a more specialized item type - /// to this collection. - /// - /// The items to add - public void AddAll(SCG.IEnumerable items) + + /// + /// Add the elements from another collection with a more specialized item type + /// to this collection. + /// + /// The items to add + public void AddAll(SCG.IEnumerable items) + { + stamp++; + int oldsize = size; + foreach (T item in items) { - stamp++; - int oldsize = size; - foreach (T item in items) - { - Add(null, item); - } + Add(null, item); + } - if (size != oldsize) + if (size != oldsize) + { + if ((ActiveEvents & EventType.Added) != 0) { - if ((ActiveEvents & EventType.Added) != 0) + foreach (T item in items) { - foreach (T item in items) - { - RaiseItemsAdded(item, 1); - } + RaiseItemsAdded(item, 1); } - - RaiseCollectionChanged(); } + + RaiseCollectionChanged(); } + } - #endregion + #endregion - #region ICollection members + #region ICollection members - /// - /// - /// - /// True if this collection is empty. - public override bool IsEmpty => size == 0; + /// + /// + /// + /// True if this collection is empty. + public override bool IsEmpty => size == 0; - /// - /// - /// - /// The size of this collection - public override int Count => size; + /// + /// + /// + /// The size of this collection + public override int Count => size; - /// - /// The value is symbolic indicating the type of asymptotic complexity - /// in terms of the size of this collection (worst-case or amortized as - /// relevant). - /// - /// A characterization of the speed of the - /// Count property in this collection. - public override Speed CountSpeed => Speed.Constant; + /// + /// The value is symbolic indicating the type of asymptotic complexity + /// in terms of the size of this collection (worst-case or amortized as + /// relevant). + /// + /// A characterization of the speed of the + /// Count property in this collection. + public override Speed CountSpeed => Speed.Constant; - /// - /// Choose some item of this collection. - /// - /// if collection is empty. - /// - public override T Choose() + /// + /// Choose some item of this collection. + /// + /// if collection is empty. + /// + public override T Choose() + { + if (size == 0) { - if (size == 0) - { - throw new NoSuchItemException("Collection is empty"); - } - - return heap[0].first; + throw new NoSuchItemException("Collection is empty"); } + return heap[0].first; + } - /// - /// Create an enumerator for the collection - /// Note: the enumerator does *not* enumerate the items in sorted order, - /// but in the internal table order. - /// - /// The enumerator(SIC) - public override SCG.IEnumerator GetEnumerator() + + /// + /// Create an enumerator for the collection + /// Note: the enumerator does *not* enumerate the items in sorted order, + /// but in the internal table order. + /// + /// The enumerator(SIC) + public override SCG.IEnumerator GetEnumerator() + { + int mystamp = stamp; + for (int i = 0; i < size; i++) { - int mystamp = stamp; - for (int i = 0; i < size; i++) + if (mystamp != stamp) { - if (mystamp != stamp) - { - throw new CollectionModifiedException(); - } - - yield return i % 2 == 0 ? heap[i >> 1].first : heap[i >> 1].last; + throw new CollectionModifiedException(); } - yield break; + + yield return i % 2 == 0 ? heap[i >> 1].first : heap[i >> 1].last; } + yield break; + } - #endregion + #endregion - #region Diagnostics + #region Diagnostics - // Check invariants: - // * first <= last in a cell if both are valid - // * a parent interval (cell) contains both its daughter intervals (cells) - // * a handle, if non-null, points to the cell it is associated with - private bool Check(int i, T min, T max) - { - bool retval = true; - Interval interval = heap[i]; - T first = interval.first, last = interval.last; + // Check invariants: + // * first <= last in a cell if both are valid + // * a parent interval (cell) contains both its daughter intervals (cells) + // * a handle, if non-null, points to the cell it is associated with + private bool Check(int i, T min, T max) + { + bool retval = true; + Interval interval = heap[i]; + T first = interval.first, last = interval.last; - if (2 * i + 1 == size) + if (2 * i + 1 == size) + { + if (comparer.Compare(min, first) > 0) { - if (comparer.Compare(min, first) > 0) - { - Logger.Log(string.Format("Cell {0}: parent.first({1}) > first({2}) [size={3}]", i, min, first, size)); - retval = false; - } - - if (comparer.Compare(first, max) > 0) - { - Logger.Log(string.Format("Cell {0}: first({1}) > parent.last({2}) [size={3}]", i, first, max, size)); - retval = false; - } - if (interval.firsthandle != null && interval.firsthandle.index != 2 * i) - { - Logger.Log(string.Format("Cell {0}: firsthandle.index({1}) != 2*cell({2}) [size={3}]", i, interval.firsthandle.index, 2 * i, size)); - retval = false; - } + Logger.Log(string.Format("Cell {0}: parent.first({1}) > first({2}) [size={3}]", i, min, first, size)); + retval = false; + } - return retval; + if (comparer.Compare(first, max) > 0) + { + Logger.Log(string.Format("Cell {0}: first({1}) > parent.last({2}) [size={3}]", i, first, max, size)); + retval = false; } - else + if (interval.firsthandle != null && interval.firsthandle.index != 2 * i) { - if (comparer.Compare(min, first) > 0) - { - Logger.Log(string.Format("Cell {0}: parent.first({1}) > first({2}) [size={3}]", i, min, first, size)); - retval = false; - } - - if (comparer.Compare(first, last) > 0) - { - Logger.Log(string.Format("Cell {0}: first({1}) > last({2}) [size={3}]", i, first, last, size)); - retval = false; - } - - if (comparer.Compare(last, max) > 0) - { - Logger.Log(string.Format("Cell {0}: last({1}) > parent.last({2}) [size={3}]", i, last, max, size)); - retval = false; - } - if (interval.firsthandle != null && interval.firsthandle.index != 2 * i) - { - Logger.Log(string.Format("Cell {0}: firsthandle.index({1}) != 2*cell({2}) [size={3}]", i, interval.firsthandle.index, 2 * i, size)); - retval = false; - } - if (interval.lasthandle != null && interval.lasthandle.index != 2 * i + 1) - { - Logger.Log(string.Format("Cell {0}: lasthandle.index({1}) != 2*cell+1({2}) [size={3}]", i, interval.lasthandle.index, 2 * i + 1, size)); - retval = false; - } - - int l = 2 * i + 1, r = l + 1; - - if (2 * l < size) - { - retval = retval && Check(l, first, last); - } - - if (2 * r < size) - { - retval = retval && Check(r, first, last); - } + Logger.Log(string.Format("Cell {0}: firsthandle.index({1}) != 2*cell({2}) [size={3}]", i, interval.firsthandle.index, 2 * i, size)); + retval = false; } return retval; } + else + { + if (comparer.Compare(min, first) > 0) + { + Logger.Log(string.Format("Cell {0}: parent.first({1}) > first({2}) [size={3}]", i, min, first, size)); + retval = false; + } + if (comparer.Compare(first, last) > 0) + { + Logger.Log(string.Format("Cell {0}: first({1}) > last({2}) [size={3}]", i, first, last, size)); + retval = false; + } - /// - /// Check the integrity of the internal data structures of this collection. - /// Only available in DEBUG builds??? - /// - /// True if check does not fail. - public bool Check() - { - if (size == 0) + if (comparer.Compare(last, max) > 0) + { + Logger.Log(string.Format("Cell {0}: last({1}) > parent.last({2}) [size={3}]", i, last, max, size)); + retval = false; + } + if (interval.firsthandle != null && interval.firsthandle.index != 2 * i) + { + Logger.Log(string.Format("Cell {0}: firsthandle.index({1}) != 2*cell({2}) [size={3}]", i, interval.firsthandle.index, 2 * i, size)); + retval = false; + } + if (interval.lasthandle != null && interval.lasthandle.index != 2 * i + 1) { - return true; + Logger.Log(string.Format("Cell {0}: lasthandle.index({1}) != 2*cell+1({2}) [size={3}]", i, interval.lasthandle.index, 2 * i + 1, size)); + retval = false; } - if (size == 1) + int l = 2 * i + 1, r = l + 1; + + if (2 * l < size) { - return heap[0].first != null; + retval = retval && Check(l, first, last); } - return Check(0, heap[0].first, heap[0].last); + if (2 * r < size) + { + retval = retval && Check(r, first, last); + } } - #endregion + return retval; + } - #region IPriorityQueue Members - private class Handle : IPriorityQueueHandle + /// + /// Check the integrity of the internal data structures of this collection. + /// Only available in DEBUG builds??? + /// + /// True if check does not fail. + public bool Check() + { + if (size == 0) { - /// - /// To save space, the index is 2*cell for heap[cell].first, and 2*cell+1 for heap[cell].last - /// - internal int index = -1; - - public override string ToString() - { - return string.Format("[{0}]", index); - } + return true; + } + if (size == 1) + { + return heap[0].first != null; } + return Check(0, heap[0].first, heap[0].last); + } + + #endregion + + #region IPriorityQueue Members + + private class Handle : IPriorityQueueHandle + { /// - /// Get or set the item corresponding to a handle. + /// To save space, the index is 2*cell for heap[cell].first, and 2*cell+1 for heap[cell].last /// - /// if the handle is invalid for this queue - /// The reference into the heap - /// - public T this[IPriorityQueueHandle handle] + internal int index = -1; + + public override string ToString() { - get - { - CheckHandle(handle, out int cell, out bool isfirst); + return string.Format("[{0}]", index); + } - return isfirst ? heap[cell].first : heap[cell].last; - } - set => Replace(handle, value); + } + + /// + /// Get or set the item corresponding to a handle. + /// + /// if the handle is invalid for this queue + /// The reference into the heap + /// + public T this[IPriorityQueueHandle handle] + { + get + { + CheckHandle(handle, out int cell, out bool isfirst); + + return isfirst ? heap[cell].first : heap[cell].last; } + set => Replace(handle, value); + } - /// - /// Check safely if a handle is valid for this queue and if so, report the corresponding queue item. - /// - /// The handle to check - /// If the handle is valid this will contain the corresponding item on output. - /// True if the handle is valid. - public bool Find(IPriorityQueueHandle handle, out T item) + /// + /// Check safely if a handle is valid for this queue and if so, report the corresponding queue item. + /// + /// The handle to check + /// If the handle is valid this will contain the corresponding item on output. + /// True if the handle is valid. + public bool Find(IPriorityQueueHandle handle, out T item) + { + if (handle is not Handle myhandle) { - if (handle is not Handle myhandle) + item = default; + return false; + } + int toremove = myhandle.index; + int cell = toremove / 2; + bool isfirst = toremove % 2 == 0; + { + if (toremove == -1 || toremove >= size) { item = default; return false; } - int toremove = myhandle.index; - int cell = toremove / 2; - bool isfirst = toremove % 2 == 0; + Handle actualhandle = (isfirst ? heap[cell].firsthandle : heap[cell].lasthandle)!; + if (actualhandle != myhandle) { - if (toremove == -1 || toremove >= size) - { - item = default; - return false; - } - Handle actualhandle = (isfirst ? heap[cell].firsthandle : heap[cell].lasthandle)!; - if (actualhandle != myhandle) - { - item = default; - return false; - } + item = default; + return false; } - item = isfirst ? heap[cell].first : heap[cell].last; - return true; } + item = isfirst ? heap[cell].first : heap[cell].last; + return true; + } - /// - /// Add an item to the priority queue, receiving a - /// handle for the item in the queue, - /// or reusing an already existing handle. - /// - /// On output: a handle for the added item. - /// On input: null for allocating a new handle, an invalid handle for reuse. - /// A handle for reuse must be compatible with this priority queue, - /// by being created by a priority queue of the same runtime type, but not - /// necessarily the same priority queue object. - /// The item to add. - /// True since item will always be added unless the call throws an exception. - public bool Add(ref IPriorityQueueHandle handle, T item) + /// + /// Add an item to the priority queue, receiving a + /// handle for the item in the queue, + /// or reusing an already existing handle. + /// + /// On output: a handle for the added item. + /// On input: null for allocating a new handle, an invalid handle for reuse. + /// A handle for reuse must be compatible with this priority queue, + /// by being created by a priority queue of the same runtime type, but not + /// necessarily the same priority queue object. + /// The item to add. + /// True since item will always be added unless the call throws an exception. + public bool Add(ref IPriorityQueueHandle handle, T item) + { + stamp++; + Handle myhandle = (Handle)handle; + if (myhandle == null) { - stamp++; - Handle myhandle = (Handle)handle; - if (myhandle == null) - { - handle = myhandle = new Handle(); - } - else - if (myhandle.index != -1) - { - throw new InvalidPriorityQueueHandleException("Handle not valid for reuse"); - } - - if (Add(myhandle, item)) - { - RaiseItemsAdded(item, 1); - RaiseCollectionChanged(); - return true; - } - return false; + handle = myhandle = new Handle(); + } + else + if (myhandle.index != -1) + { + throw new InvalidPriorityQueueHandleException("Handle not valid for reuse"); } - /// - /// Delete an item with a handle from a priority queue. - /// - /// if the handle is invalid - /// The handle for the item. The handle will be invalidated, but reusable. - /// The deleted item - public T Delete(IPriorityQueueHandle handle) + if (Add(myhandle, item)) { - stamp++; - Handle myhandle = CheckHandle(handle, out int cell, out bool isfirst); + RaiseItemsAdded(item, 1); + RaiseCollectionChanged(); + return true; + } + return false; + } - T retval; - myhandle.index = -1; - int lastcell = (size - 1) / 2; + /// + /// Delete an item with a handle from a priority queue. + /// + /// if the handle is invalid + /// The handle for the item. The handle will be invalidated, but reusable. + /// The deleted item + public T Delete(IPriorityQueueHandle handle) + { + stamp++; + Handle myhandle = CheckHandle(handle, out int cell, out bool isfirst); - if (cell == lastcell) - { - if (isfirst) - { - retval = heap[cell].first; - if (size % 2 == 0) - { - UpdateFirst(cell, heap[cell].last, heap[cell].lasthandle); - heap[cell].last = default; - heap[cell].lasthandle = null; - } - else - { - heap[cell].first = default; - heap[cell].firsthandle = null; - } - } - else - { - retval = heap[cell].last; - heap[cell].last = default; - heap[cell].lasthandle = null; - } - size--; - } - else if (isfirst) + T retval; + myhandle.index = -1; + int lastcell = (size - 1) / 2; + + if (cell == lastcell) + { + if (isfirst) { retval = heap[cell].first; - if (size % 2 == 0) { - UpdateFirst(cell, heap[lastcell].last, heap[lastcell].lasthandle); - heap[lastcell].last = default; - heap[lastcell].lasthandle = null; - } - else - { - UpdateFirst(cell, heap[lastcell].first, heap[lastcell].firsthandle); - heap[lastcell].first = default; - heap[lastcell].firsthandle = null; - } - - size--; - if (HeapifyMin(cell)) - { - BubbleUpMax(cell); + UpdateFirst(cell, heap[cell].last, heap[cell].lasthandle); + heap[cell].last = default; + heap[cell].lasthandle = null; } else { - BubbleUpMin(cell); + heap[cell].first = default; + heap[cell].firsthandle = null; } } else { retval = heap[cell].last; + heap[cell].last = default; + heap[cell].lasthandle = null; + } + size--; + } + else if (isfirst) + { + retval = heap[cell].first; - if (size % 2 == 0) - { - UpdateLast(cell, heap[lastcell].last, heap[lastcell].lasthandle); - heap[lastcell].last = default; - heap[lastcell].lasthandle = null; - } - else - { - UpdateLast(cell, heap[lastcell].first, heap[lastcell].firsthandle); - heap[lastcell].first = default; - heap[lastcell].firsthandle = null; - } + if (size % 2 == 0) + { + UpdateFirst(cell, heap[lastcell].last, heap[lastcell].lasthandle); + heap[lastcell].last = default; + heap[lastcell].lasthandle = null; + } + else + { + UpdateFirst(cell, heap[lastcell].first, heap[lastcell].firsthandle); + heap[lastcell].first = default; + heap[lastcell].firsthandle = null; + } - size--; - if (HeapifyMax(cell)) - { - BubbleUpMin(cell); - } - else - { - BubbleUpMax(cell); - } + size--; + if (HeapifyMin(cell)) + { + BubbleUpMax(cell); } + else + { + BubbleUpMin(cell); + } + } + else + { + retval = heap[cell].last; - RaiseItemsRemoved(retval, 1); - RaiseCollectionChanged(); + if (size % 2 == 0) + { + UpdateLast(cell, heap[lastcell].last, heap[lastcell].lasthandle); + heap[lastcell].last = default; + heap[lastcell].lasthandle = null; + } + else + { + UpdateLast(cell, heap[lastcell].first, heap[lastcell].firsthandle); + heap[lastcell].first = default; + heap[lastcell].firsthandle = null; + } - return retval; + size--; + if (HeapifyMax(cell)) + { + BubbleUpMin(cell); + } + else + { + BubbleUpMax(cell); + } } - private Handle CheckHandle(IPriorityQueueHandle handle, out int cell, out bool isfirst) + RaiseItemsRemoved(retval, 1); + RaiseCollectionChanged(); + + return retval; + } + + private Handle CheckHandle(IPriorityQueueHandle handle, out int cell, out bool isfirst) + { + Handle myhandle = (Handle)handle; + int toremove = myhandle.index; + cell = toremove / 2; + isfirst = toremove % 2 == 0; { - Handle myhandle = (Handle)handle; - int toremove = myhandle.index; - cell = toremove / 2; - isfirst = toremove % 2 == 0; + if (toremove == -1 || toremove >= size) { - if (toremove == -1 || toremove >= size) - { - throw new InvalidPriorityQueueHandleException("Invalid handle, index out of range"); - } + throw new InvalidPriorityQueueHandleException("Invalid handle, index out of range"); + } - Handle actualhandle = (isfirst ? heap[cell].firsthandle : heap[cell].lasthandle)!; - if (actualhandle != myhandle) - { - throw new InvalidPriorityQueueHandleException("Invalid handle, doesn't match queue"); - } + Handle actualhandle = (isfirst ? heap[cell].firsthandle : heap[cell].lasthandle)!; + if (actualhandle != myhandle) + { + throw new InvalidPriorityQueueHandleException("Invalid handle, doesn't match queue"); } - return myhandle; } + return myhandle; + } - /// - /// Replace an item with a handle in a priority queue with a new item. - /// Typically used for changing the priority of some queued object. - /// - /// The handle for the old item - /// The new item - /// The old item - public T Replace(IPriorityQueueHandle handle, T item) + /// + /// Replace an item with a handle in a priority queue with a new item. + /// Typically used for changing the priority of some queued object. + /// + /// The handle for the old item + /// The new item + /// The old item + public T Replace(IPriorityQueueHandle handle, T item) + { + stamp++; + CheckHandle(handle, out int cell, out bool isfirst); + if (size == 0) { - stamp++; - CheckHandle(handle, out int cell, out bool isfirst); - if (size == 0) - { - throw new NoSuchItemException(); - } + throw new NoSuchItemException(); + } - T retval; + T retval; - if (isfirst) + if (isfirst) + { + retval = heap[cell].first; + heap[cell].first = item; + if (size == 1) { - retval = heap[cell].first; - heap[cell].first = item; - if (size == 1) - { - } - else if (size == 2 * cell + 1) // cell == lastcell - { - int p = (cell + 1) / 2 - 1; - if (comparer.Compare(item, heap[p].last) > 0) - { - Handle thehandle = heap[cell].firsthandle!; - UpdateFirst(cell, heap[p].last, heap[p].lasthandle); - UpdateLast(p, item, thehandle); - BubbleUpMax(p); - } - else - { - BubbleUpMin(cell); - } - } - else if (HeapifyMin(cell)) + } + else if (size == 2 * cell + 1) // cell == lastcell + { + int p = (cell + 1) / 2 - 1; + if (comparer.Compare(item, heap[p].last) > 0) { - BubbleUpMax(cell); + Handle thehandle = heap[cell].firsthandle!; + UpdateFirst(cell, heap[p].last, heap[p].lasthandle); + UpdateLast(p, item, thehandle); + BubbleUpMax(p); } else { BubbleUpMin(cell); } } + else if (HeapifyMin(cell)) + { + BubbleUpMax(cell); + } else { - retval = heap[cell].last; - heap[cell].last = item; - if (HeapifyMax(cell)) - { - BubbleUpMin(cell); - } - else - { - BubbleUpMax(cell); - } + BubbleUpMin(cell); } - - RaiseItemsRemoved(retval, 1); - RaiseItemsAdded(item, 1); - RaiseCollectionChanged(); - - return retval; } - - /// - /// Find the current least item of this priority queue. - /// - /// On return: the handle of the item. - /// The least item. - public T FindMin(out IPriorityQueueHandle handle) + else { - if (size == 0) + retval = heap[cell].last; + heap[cell].last = item; + if (HeapifyMax(cell)) { - throw new NoSuchItemException(); + BubbleUpMin(cell); } + else + { + BubbleUpMax(cell); + } + } - handle = heap[0].firsthandle!; + RaiseItemsRemoved(retval, 1); + RaiseItemsAdded(item, 1); + RaiseCollectionChanged(); + return retval; + } + + /// + /// Find the current least item of this priority queue. + /// + /// On return: the handle of the item. + /// The least item. + public T FindMin(out IPriorityQueueHandle handle) + { + if (size == 0) + { + throw new NoSuchItemException(); + } + + handle = heap[0].firsthandle!; + + return heap[0].first; + } + + /// + /// Find the current largest item of this priority queue. + /// + /// On return: the handle of the item. + /// The largest item. + public T FindMax(out IPriorityQueueHandle handle) + { + if (size == 0) + { + throw new NoSuchItemException(); + } + else if (size == 1) + { + handle = heap[0].firsthandle!; return heap[0].first; } + else + { + handle = heap[0].lasthandle!; + return heap[0].last; + } + } - /// - /// Find the current largest item of this priority queue. - /// - /// On return: the handle of the item. - /// The largest item. - public T FindMax(out IPriorityQueueHandle handle) + /// + /// Remove the least item from this priority queue. + /// + /// On return: the handle of the removed item. + /// The removed item. + public T DeleteMin(out IPriorityQueueHandle handle) + { + stamp++; + if (size == 0) { - if (size == 0) - { - throw new NoSuchItemException(); - } - else if (size == 1) - { - handle = heap[0].firsthandle!; - return heap[0].first; - } - else - { - handle = heap[0].lasthandle!; - return heap[0].last; - } + throw new NoSuchItemException(); } - /// - /// Remove the least item from this priority queue. - /// - /// On return: the handle of the removed item. - /// The removed item. - public T DeleteMin(out IPriorityQueueHandle handle) + T retval = heap[0].first; + Handle myhandle = heap[0].firsthandle!; + handle = myhandle; + if (myhandle != null) { - stamp++; - if (size == 0) - { - throw new NoSuchItemException(); - } + myhandle.index = -1; + } - T retval = heap[0].first; - Handle myhandle = heap[0].firsthandle!; - handle = myhandle; - if (myhandle != null) - { - myhandle.index = -1; - } + if (size == 1) + { + size = 0; + heap[0].first = default; + heap[0].firsthandle = null; + } + else + { + int lastcell = (size - 1) / 2; - if (size == 1) + if (size % 2 == 0) { - size = 0; - heap[0].first = default; - heap[0].firsthandle = null; + UpdateFirst(0, heap[lastcell].last, heap[lastcell].lasthandle); + heap[lastcell].last = default; + heap[lastcell].lasthandle = null; } else { - int lastcell = (size - 1) / 2; + UpdateFirst(0, heap[lastcell].first, heap[lastcell].firsthandle); + heap[lastcell].first = default; + heap[lastcell].firsthandle = null; + } - if (size % 2 == 0) - { - UpdateFirst(0, heap[lastcell].last, heap[lastcell].lasthandle); - heap[lastcell].last = default; - heap[lastcell].lasthandle = null; - } - else - { - UpdateFirst(0, heap[lastcell].first, heap[lastcell].firsthandle); - heap[lastcell].first = default; - heap[lastcell].firsthandle = null; - } + size--; + HeapifyMin(0); + } - size--; - HeapifyMin(0); - } + RaiseItemsRemoved(retval, 1); + RaiseCollectionChanged(); + return retval; - RaiseItemsRemoved(retval, 1); - RaiseCollectionChanged(); - return retval; + } + /// + /// Remove the largest item from this priority queue. + /// + /// On return: the handle of the removed item. + /// The removed item. + public T DeleteMax(out IPriorityQueueHandle handle) + { + stamp++; + if (size == 0) + { + throw new NoSuchItemException(); } - /// - /// Remove the largest item from this priority queue. - /// - /// On return: the handle of the removed item. - /// The removed item. - public T DeleteMax(out IPriorityQueueHandle handle) + T retval; + Handle myhandle; + + if (size == 1) { - stamp++; - if (size == 0) + size = 0; + retval = heap[0].first; + myhandle = heap[0].firsthandle!; + if (myhandle != null) { - throw new NoSuchItemException(); + myhandle.index = -1; } - T retval; - Handle myhandle; - - if (size == 1) + heap[0].first = default; + heap[0].firsthandle = null; + } + else + { + retval = heap[0].last; + myhandle = heap[0].lasthandle!; + if (myhandle != null) { - size = 0; - retval = heap[0].first; - myhandle = heap[0].firsthandle!; - if (myhandle != null) - { - myhandle.index = -1; - } + myhandle.index = -1; + } - heap[0].first = default; - heap[0].firsthandle = null; + int lastcell = (size - 1) / 2; + + if (size % 2 == 0) + { + UpdateLast(0, heap[lastcell].last, heap[lastcell].lasthandle); + heap[lastcell].last = default; + heap[lastcell].lasthandle = null; } else { - retval = heap[0].last; - myhandle = heap[0].lasthandle!; - if (myhandle != null) - { - myhandle.index = -1; - } - - int lastcell = (size - 1) / 2; - - if (size % 2 == 0) - { - UpdateLast(0, heap[lastcell].last, heap[lastcell].lasthandle); - heap[lastcell].last = default; - heap[lastcell].lasthandle = null; - } - else - { - UpdateLast(0, heap[lastcell].first, heap[lastcell].firsthandle); - heap[lastcell].first = default; - heap[lastcell].firsthandle = null; - } - - size--; - HeapifyMax(0); + UpdateLast(0, heap[lastcell].first, heap[lastcell].firsthandle); + heap[lastcell].first = default; + heap[lastcell].firsthandle = null; } - RaiseItemsRemoved(retval, 1); - RaiseCollectionChanged(); - handle = myhandle!; - return retval; - } - #endregion + size--; + HeapifyMax(0); + } + RaiseItemsRemoved(retval, 1); + RaiseCollectionChanged(); + handle = myhandle!; + return retval; } + + #endregion } diff --git a/C5/Interfaces/ICollection.cs b/C5/Interfaces/ICollection.cs index 32ddebd2..46f23297 100644 --- a/C5/Interfaces/ICollection.cs +++ b/C5/Interfaces/ICollection.cs @@ -1,233 +1,235 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using SCG = System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// The simplest interface of a main stream generic collection +/// with lookup, insertion and removal operations. +/// +public interface ICollection : IExtensible, SCG.ICollection { + //This is somewhat similar to the RandomAccess marker itf in java + /// + /// The value is symbolic indicating the type of asymptotic complexity + /// in terms of the size of this collection (worst-case or amortized as + /// relevant). + /// See for the set of symbols. + /// + /// A characterization of the speed of lookup operations + /// (Contains() etc.) of the implementation of this collection. + Speed ContainsSpeed { get; } + + /// + /// + /// The number of items in this collection + new int Count { get; } + + /// + /// If true any call of an updating operation will throw an + /// ReadOnlyCollectionException + /// + /// True if this collection is read-only. + new bool IsReadOnly { get; } + + /// + /// Add an item to this collection if possible. If this collection has set + /// semantics, the item will be added if not already in the collection. If + /// bag semantics, the item will always be added. + /// + /// The item to add. + /// True if item was added. + new bool Add(T item); + + /// + /// Copy the items of this collection to a contiguous part of an array. + /// + /// The array to copy to + /// The index at which to copy the first item + new void CopyTo(T[] array, int index); + + /// + /// The unordered collection hashcode is defined as the sum of + /// h(hashcode(item)) over the items + /// of the collection, where the function h is a function from + /// int to int of the form t -> (a0*t+b0)^(a1*t+b1)^(a2*t+b2), where + /// the ax and bx are the same for all collection classes. + /// The current implementation uses fixed values for the ax and bx, + /// specified as constants in the code. + /// + /// The unordered hashcode of this collection. + int GetUnsequencedHashCode(); + + + /// + /// Compare the contents of this collection to another one without regards to + /// the sequence order. The comparison will use this collection's itemequalityComparer + /// to compare individual items. + /// + /// The collection to compare to. + /// True if this collection and that contains the same items. + bool UnsequencedEquals(ICollection otherCollection); + + + /// + /// Check if this collection contains (an item equivalent to according to the + /// itemequalityComparer) a particular value. + /// + /// The value to check for. + /// True if the items is in this collection. + new bool Contains(T item); + + + /// + /// Count the number of items of the collection equal to a particular value. + /// Returns 0 if and only if the value is not in the collection. + /// + /// The value to count. + /// The number of copies found. + int ContainsCount(T item); + + /// - /// The simplest interface of a main stream generic collection - /// with lookup, insertion and removal operations. - /// - public interface ICollection : IExtensible, SCG.ICollection - { - //This is somewhat similar to the RandomAccess marker itf in java - /// - /// The value is symbolic indicating the type of asymptotic complexity - /// in terms of the size of this collection (worst-case or amortized as - /// relevant). - /// See for the set of symbols. - /// - /// A characterization of the speed of lookup operations - /// (Contains() etc.) of the implementation of this collection. - Speed ContainsSpeed { get; } - - /// - /// - /// The number of items in this collection - new int Count { get; } - - /// - /// If true any call of an updating operation will throw an - /// ReadOnlyCollectionException - /// - /// True if this collection is read-only. - new bool IsReadOnly { get; } - - /// - /// Add an item to this collection if possible. If this collection has set - /// semantics, the item will be added if not already in the collection. If - /// bag semantics, the item will always be added. - /// - /// The item to add. - /// True if item was added. - new bool Add(T item); - - /// - /// Copy the items of this collection to a contiguous part of an array. - /// - /// The array to copy to - /// The index at which to copy the first item - new void CopyTo(T[] array, int index); - - /// - /// The unordered collection hashcode is defined as the sum of - /// h(hashcode(item)) over the items - /// of the collection, where the function h is a function from - /// int to int of the form t -> (a0*t+b0)^(a1*t+b1)^(a2*t+b2), where - /// the ax and bx are the same for all collection classes. - /// The current implementation uses fixed values for the ax and bx, - /// specified as constants in the code. - /// - /// The unordered hashcode of this collection. - int GetUnsequencedHashCode(); - - - /// - /// Compare the contents of this collection to another one without regards to - /// the sequence order. The comparison will use this collection's itemequalityComparer - /// to compare individual items. - /// - /// The collection to compare to. - /// True if this collection and that contains the same items. - bool UnsequencedEquals(ICollection otherCollection); - - - /// - /// Check if this collection contains (an item equivalent to according to the - /// itemequalityComparer) a particular value. - /// - /// The value to check for. - /// True if the items is in this collection. - new bool Contains(T item); - - - /// - /// Count the number of items of the collection equal to a particular value. - /// Returns 0 if and only if the value is not in the collection. - /// - /// The value to count. - /// The number of copies found. - int ContainsCount(T item); - - - /// - /// - /// - /// - ICollectionValue UniqueItems(); - - /// - /// - /// - /// - ICollectionValue> ItemMultiplicities(); - - /// - /// Check whether this collection contains all the values in another collection. - /// If this collection has bag semantics (AllowsDuplicates==true) - /// the check is made with respect to multiplicities, else multiplicities - /// are not taken into account. - /// - /// The - /// True if all values in itemsis in this collection. - bool ContainsAll(SCG.IEnumerable items); - - - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, return in the ref argument (a - /// binary copy of) the actual value found. - /// - /// The value to look for. - /// True if the items is in this collection. - bool Find(ref T item); - - - //This should probably just be bool Add(ref T item); !!! - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, return in the ref argument (a - /// binary copy of) the actual value found. Else, add the item to the collection. - /// - /// The value to look for. - /// True if the item was found (hence not added). - bool FindOrAdd(ref T item); - - - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// with a (binary copy of) the supplied value. If the collection has bag semantics, - /// it depends on the value of DuplicatesByCounting if this updates all equivalent copies in - /// the collection or just one. - /// - /// Value to update. - /// True if the item was found and hence updated. - bool Update(T item); - - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// with a (binary copy of) the supplied value. If the collection has bag semantics, - /// it depends on the value of DuplicatesByCounting if this updates all equivalent copies in - /// the collection or just one. - /// - /// Value to update. - /// On output the olditem, if found. - /// True if the item was found and hence updated. - bool Update(T item, out T olditem); - - - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// to with a binary copy of the supplied value; else add the value to the collection. - /// - /// Value to add or update. - /// True if the item was found and updated (hence not added). - bool UpdateOrAdd(T item); - - - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// to with a binary copy of the supplied value; else add the value to the collection. - /// - /// Value to add or update. - /// On output the olditem, if found. - /// True if the item was found and updated (hence not added). - bool UpdateOrAdd(T item, out T olditem); - - /// - /// Remove a particular item from this collection. If the collection has bag - /// semantics only one copy equivalent to the supplied item is removed. - /// - /// The value to remove. - /// True if the item was found (and removed). - new bool Remove(T item); - - - /// - /// Remove a particular item from this collection if found. If the collection - /// has bag semantics only one copy equivalent to the supplied item is removed, - /// which one is implementation dependent. - /// If an item was removed, report a binary copy of the actual item removed in - /// the argument. - /// - /// The value to remove. - /// The value removed if any. - /// True if the item was found (and removed). - bool Remove(T item, out T removeditem); - - - /// - /// Remove all items equivalent to a given value. - /// - /// The value to remove. - void RemoveAllCopies(T item); - - - /// - /// Remove all items in another collection from this one. If this collection - /// has bag semantics, take multiplicities into account. - /// - /// The items to remove. - void RemoveAll(SCG.IEnumerable items); - - //void RemoveAll(Func predicate); - - /// - /// Remove all items from this collection. - /// - new void Clear(); - - - /// - /// Remove all items not in some other collection from this one. If this collection - /// has bag semantics, take multiplicities into account. - /// - /// The items to retain. - void RetainAll(SCG.IEnumerable items); - - //void RetainAll(Func predicate); - //IDictionary UniqueItems() - } + /// + /// + /// + ICollectionValue UniqueItems(); + + /// + /// + /// + /// + ICollectionValue> ItemMultiplicities(); + + /// + /// Check whether this collection contains all the values in another collection. + /// If this collection has bag semantics (AllowsDuplicates==true) + /// the check is made with respect to multiplicities, else multiplicities + /// are not taken into account. + /// + /// The + /// True if all values in itemsis in this collection. + bool ContainsAll(SCG.IEnumerable items); + + + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, return in the ref argument (a + /// binary copy of) the actual value found. + /// + /// The value to look for. + /// True if the items is in this collection. + bool Find(ref T item); + + + //This should probably just be bool Add(ref T item); !!! + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, return in the ref argument (a + /// binary copy of) the actual value found. Else, add the item to the collection. + /// + /// The value to look for. + /// True if the item was found (hence not added). + bool FindOrAdd(ref T item); + + + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// with a (binary copy of) the supplied value. If the collection has bag semantics, + /// it depends on the value of DuplicatesByCounting if this updates all equivalent copies in + /// the collection or just one. + /// + /// Value to update. + /// True if the item was found and hence updated. + bool Update(T item); + + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// with a (binary copy of) the supplied value. If the collection has bag semantics, + /// it depends on the value of DuplicatesByCounting if this updates all equivalent copies in + /// the collection or just one. + /// + /// Value to update. + /// On output the olditem, if found. + /// True if the item was found and hence updated. + bool Update(T item, out T olditem); + + + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// to with a binary copy of the supplied value; else add the value to the collection. + /// + /// Value to add or update. + /// True if the item was found and updated (hence not added). + bool UpdateOrAdd(T item); + + + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// to with a binary copy of the supplied value; else add the value to the collection. + /// + /// Value to add or update. + /// On output the olditem, if found. + /// True if the item was found and updated (hence not added). + bool UpdateOrAdd(T item, out T olditem); + + /// + /// Remove a particular item from this collection. If the collection has bag + /// semantics only one copy equivalent to the supplied item is removed. + /// + /// The value to remove. + /// True if the item was found (and removed). + new bool Remove(T item); + + + /// + /// Remove a particular item from this collection if found. If the collection + /// has bag semantics only one copy equivalent to the supplied item is removed, + /// which one is implementation dependent. + /// If an item was removed, report a binary copy of the actual item removed in + /// the argument. + /// + /// The value to remove. + /// The value removed if any. + /// True if the item was found (and removed). + bool Remove(T item, out T removeditem); + + + /// + /// Remove all items equivalent to a given value. + /// + /// The value to remove. + void RemoveAllCopies(T item); + + + /// + /// Remove all items in another collection from this one. If this collection + /// has bag semantics, take multiplicities into account. + /// + /// The items to remove. + void RemoveAll(SCG.IEnumerable items); + + //void RemoveAll(Func predicate); + + /// + /// Remove all items from this collection. + /// + new void Clear(); + + + /// + /// Remove all items not in some other collection from this one. If this collection + /// has bag semantics, take multiplicities into account. + /// + /// The items to retain. + void RetainAll(SCG.IEnumerable items); + + //void RetainAll(Func predicate); + //IDictionary UniqueItems() } \ No newline at end of file diff --git a/C5/Interfaces/ICollectionValue.cs b/C5/Interfaces/ICollectionValue.cs index a05c83a5..65bfbae6 100644 --- a/C5/Interfaces/ICollectionValue.cs +++ b/C5/Interfaces/ICollectionValue.cs @@ -1,147 +1,149 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; using System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// A generic collection that may be enumerated and can answer +/// efficiently how many items it contains. Like IEnumerable<T>, +/// this interface does not prescribe any operations to initialize or update the +/// collection. The main usage for this interface is to be the return type of +/// query operations on generic collection. +/// +public interface ICollectionValue : IEnumerable, IShowable { /// - /// A generic collection that may be enumerated and can answer - /// efficiently how many items it contains. Like IEnumerable<T>, - /// this interface does not prescribe any operations to initialize or update the - /// collection. The main usage for this interface is to be the return type of - /// query operations on generic collection. - /// - public interface ICollectionValue : IEnumerable, IShowable - { - /// - /// A flag bitmap of the events subscribable to by this collection. - /// - /// - EventType ListenableEvents { get; } - - /// - /// A flag bitmap of the events currently subscribed to by this collection. - /// - /// - EventType ActiveEvents { get; } - - /// - /// The change event. Will be raised for every change operation on the collection. - /// - event CollectionChangedHandler CollectionChanged; - - /// - /// The change event. Will be raised for every clear operation on the collection. - /// - event CollectionClearedHandler CollectionCleared; - - /// - /// The item added event. Will be raised for every individual addition to the collection. - /// - event ItemsAddedHandler ItemsAdded; - - /// - /// The item inserted event. Will be raised for every individual insertion to the collection. - /// - event ItemInsertedHandler ItemInserted; - - /// - /// The item removed event. Will be raised for every individual removal from the collection. - /// - event ItemsRemovedHandler ItemsRemoved; - - /// - /// The item removed at event. Will be raised for every individual removal at from the collection. - /// - event ItemRemovedAtHandler ItemRemovedAt; - - /// - /// - /// - /// True if this collection is empty. - bool IsEmpty { get; } - - /// - /// - /// The number of items in this collection - int Count { get; } - - /// - /// The value is symbolic indicating the type of asymptotic complexity - /// in terms of the size of this collection (worst-case or amortized as - /// relevant). - /// - /// A characterization of the speed of the - /// Count property in this collection. - Speed CountSpeed { get; } - - /// - /// Copy the items of this collection to a contiguous part of an array. - /// - /// The array to copy to - /// The index at which to copy the first item - void CopyTo(T[] array, int index); - - /// - /// Create an array with the items of this collection (in the same order as an - /// enumerator would output them). - /// - /// The array - T[] ToArray(); - - /// - /// Apply a delegate to all items of this collection. - /// - /// The delegate to apply - void Apply(Action action); - - - /// - /// Check if there exists an item that satisfies a - /// specific predicate in this collection. - /// - /// A delegate - /// ( with R == bool) defining the predicate - /// True is such an item exists - bool Exists(Func predicate); - - /// - /// Check if there exists an item that satisfies a - /// specific predicate in this collection and return the first one in enumeration order. - /// - /// A delegate - /// ( with R == bool) defining the predicate - /// - /// True is such an item exists - bool Find(Func predicate, out T item); - - - /// - /// Check if all items in this collection satisfies a specific predicate. - /// - /// A delegate - /// ( with R == bool) defining the predicate - /// True if all items satisfies the predicate - bool All(Func predicate); - - /// - /// Choose some item of this collection. - /// Implementations must assure that the item - /// returned may be efficiently removed. - /// Implementors may decide to implement this method in a way such that repeated - /// calls do not necessarily give the same result, i.e. so that the result of the following - /// test is undetermined: - /// coll.Choose() == coll.Choose() - /// - /// if collection is empty. - /// - T Choose(); - - /// - /// Create an enumerable, enumerating the items of this collection that satisfies - /// a certain condition. - /// - /// The T->bool filter delegate defining the condition - /// The filtered enumerable - IEnumerable Filter(Func filter); - } + /// A flag bitmap of the events subscribable to by this collection. + /// + /// + EventType ListenableEvents { get; } + + /// + /// A flag bitmap of the events currently subscribed to by this collection. + /// + /// + EventType ActiveEvents { get; } + + /// + /// The change event. Will be raised for every change operation on the collection. + /// + event CollectionChangedHandler CollectionChanged; + + /// + /// The change event. Will be raised for every clear operation on the collection. + /// + event CollectionClearedHandler CollectionCleared; + + /// + /// The item added event. Will be raised for every individual addition to the collection. + /// + event ItemsAddedHandler ItemsAdded; + + /// + /// The item inserted event. Will be raised for every individual insertion to the collection. + /// + event ItemInsertedHandler ItemInserted; + + /// + /// The item removed event. Will be raised for every individual removal from the collection. + /// + event ItemsRemovedHandler ItemsRemoved; + + /// + /// The item removed at event. Will be raised for every individual removal at from the collection. + /// + event ItemRemovedAtHandler ItemRemovedAt; + + /// + /// + /// + /// True if this collection is empty. + bool IsEmpty { get; } + + /// + /// + /// The number of items in this collection + int Count { get; } + + /// + /// The value is symbolic indicating the type of asymptotic complexity + /// in terms of the size of this collection (worst-case or amortized as + /// relevant). + /// + /// A characterization of the speed of the + /// Count property in this collection. + Speed CountSpeed { get; } + + /// + /// Copy the items of this collection to a contiguous part of an array. + /// + /// The array to copy to + /// The index at which to copy the first item + void CopyTo(T[] array, int index); + + /// + /// Create an array with the items of this collection (in the same order as an + /// enumerator would output them). + /// + /// The array + T[] ToArray(); + + /// + /// Apply a delegate to all items of this collection. + /// + /// The delegate to apply + void Apply(Action action); + + + /// + /// Check if there exists an item that satisfies a + /// specific predicate in this collection. + /// + /// A delegate + /// ( with R == bool) defining the predicate + /// True is such an item exists + bool Exists(Func predicate); + + /// + /// Check if there exists an item that satisfies a + /// specific predicate in this collection and return the first one in enumeration order. + /// + /// A delegate + /// ( with R == bool) defining the predicate + /// + /// True is such an item exists + bool Find(Func predicate, out T item); + + + /// + /// Check if all items in this collection satisfies a specific predicate. + /// + /// A delegate + /// ( with R == bool) defining the predicate + /// True if all items satisfies the predicate + bool All(Func predicate); + + /// + /// Choose some item of this collection. + /// Implementations must assure that the item + /// returned may be efficiently removed. + /// Implementors may decide to implement this method in a way such that repeated + /// calls do not necessarily give the same result, i.e. so that the result of the following + /// test is undetermined: + /// coll.Choose() == coll.Choose() + /// + /// if collection is empty. + /// + T Choose(); + + /// + /// Create an enumerable, enumerating the items of this collection that satisfies + /// a certain condition. + /// + /// The T->bool filter delegate defining the condition + /// The filtered enumerable + IEnumerable Filter(Func filter); } \ No newline at end of file diff --git a/C5/Interfaces/IDictionary.cs b/C5/Interfaces/IDictionary.cs index 26bd0bd9..a2e52ac3 100644 --- a/C5/Interfaces/IDictionary.cs +++ b/C5/Interfaces/IDictionary.cs @@ -1,192 +1,194 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; using System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// A dictionary with keys of type K and values of type V. Equivalent to a +/// finite partial map from K to V. +/// +public interface IDictionary : ICollectionValue> { /// - /// A dictionary with keys of type K and values of type V. Equivalent to a - /// finite partial map from K to V. - /// - public interface IDictionary : ICollectionValue> - { - /// - /// The key equalityComparer. - /// - /// - System.Collections.Generic.IEqualityComparer EqualityComparer { get; } - - /// - /// Indexer for dictionary. - /// - /// if no entry is found. - /// The value corresponding to the key - V this[K key] { get; set; } - - - /// - /// - /// - /// True if dictionary is read-only - bool IsReadOnly { get; } - - - /// - /// - /// - /// A collection containing all the keys of the dictionary - ICollectionValue Keys { get; } - - - /// - /// - /// - /// A collection containing all the values of the dictionary - ICollectionValue Values { get; } - - /// - /// - /// - /// A delegate of type defining the partial function from K to V give by the dictionary. - Func Func { get; } - - - //TODO: resolve inconsistency: Add thows exception if key already there, AddAll ignores keys already There? - /// - /// Add a new (key, value) pair (a mapping) to the dictionary. - /// - /// if there already is an entry with the same key. > - /// Key to add - /// Value to add - void Add(K key, V val); - - /// - /// Add the entries from a collection of pairs to this dictionary. - /// - /// - /// If the input contains duplicate keys or a key already present in this dictionary. - /// - void AddAll(IEnumerable> entries) - where U : K - where W : V - ; - - /// - /// The value is symbolic indicating the type of asymptotic complexity - /// in terms of the size of this collection (worst-case or amortized as - /// relevant). - /// See for the set of symbols. - /// - /// A characterization of the speed of lookup operations - /// (Contains() etc.) of the implementation of this dictionary. - Speed ContainsSpeed { get; } - - /// - /// Check whether this collection contains all the values in another collection. - /// If this collection has bag semantics (AllowsDuplicates==true) - /// the check is made with respect to multiplicities, else multiplicities - /// are not taken into account. - /// - /// The - /// True if all values in itemsis in this collection. - bool ContainsAll(IEnumerable items) where H : K; - - /// - /// Remove an entry with a given key from the dictionary - /// - /// The key of the entry to remove - /// True if an entry was found (and removed) - bool Remove(K key); - - - /// - /// Remove an entry with a given key from the dictionary and report its value. - /// - /// The key of the entry to remove - /// On exit, the value of the removed entry - /// True if an entry was found (and removed) - bool Remove(K key, out V val); - - - /// - /// Remove all entries from the dictionary - /// - void Clear(); - - - /// - /// Check if there is an entry with a specified key - /// - /// The key to look for - /// True if key was found - bool Contains(K key); - - /// - /// Check if there is an entry with a specified key and report the corresponding - /// value if found. This can be seen as a safe form of "val = this[key]". - /// - /// The key to look for - /// On exit, the value of the entry - /// True if key was found - bool Find(ref K key, out V val); - - - /// - /// Look for a specific key in the dictionary and if found replace the value with a new one. - /// This can be seen as a non-adding version of "this[key] = val". - /// - /// The key to look for - /// The new value - /// True if key was found - bool Update(K key, V val); //no-adding - - - /// - /// Look for a specific key in the dictionary and if found replace the value with a new one. - /// This can be seen as a non-adding version of "this[key] = val" reporting the old value. - /// - /// The key to look for - /// The new value - /// The old value if any - /// True if key was found - bool Update(K key, V val, out V oldval); //no-adding - - /// - /// Look for a specific key in the dictionary. If found, report the corresponding value, - /// else add an entry with the key and the supplied value. - /// - /// The key to look for - /// On entry the value to add if the key is not found. - /// On exit the value found if any. - /// True if key was found - bool FindOrAdd(K key, ref V val); //mixture - - - /// - /// Update value in dictionary corresponding to key if found, else add new entry. - /// More general than "this[key] = val;" by reporting if key was found. - /// - /// The key to look for - /// The value to add or replace with. - /// True if key was found and value updated. - bool UpdateOrAdd(K key, V val); - - - /// - /// Update value in dictionary corresponding to key if found, else add new entry. - /// More general than "this[key] = val;" by reporting if key was found. - /// - /// The key to look for - /// The value to add or replace with. - /// The old value if any - /// True if key was found and value updated. - bool UpdateOrAdd(K key, V val, out V oldval); - - - /// - /// Check the integrity of the internal data structures of this dictionary. - /// Only available in DEBUG builds??? - /// - /// True if check does not fail. - bool Check(); - } + /// The key equalityComparer. + /// + /// + IEqualityComparer EqualityComparer { get; } + + /// + /// Indexer for dictionary. + /// + /// if no entry is found. + /// The value corresponding to the key + V this[K key] { get; set; } + + + /// + /// + /// + /// True if dictionary is read-only + bool IsReadOnly { get; } + + + /// + /// + /// + /// A collection containing all the keys of the dictionary + ICollectionValue Keys { get; } + + + /// + /// + /// + /// A collection containing all the values of the dictionary + ICollectionValue Values { get; } + + /// + /// + /// + /// A delegate of type defining the partial function from K to V give by the dictionary. + Func Func { get; } + + + //TODO: resolve inconsistency: Add thows exception if key already there, AddAll ignores keys already There? + /// + /// Add a new (key, value) pair (a mapping) to the dictionary. + /// + /// if there already is an entry with the same key. > + /// Key to add + /// Value to add + void Add(K key, V val); + + /// + /// Add the entries from a collection of pairs to this dictionary. + /// + /// + /// If the input contains duplicate keys or a key already present in this dictionary. + /// + void AddAll(IEnumerable> entries) + where U : K + where W : V + ; + + /// + /// The value is symbolic indicating the type of asymptotic complexity + /// in terms of the size of this collection (worst-case or amortized as + /// relevant). + /// See for the set of symbols. + /// + /// A characterization of the speed of lookup operations + /// (Contains() etc.) of the implementation of this dictionary. + Speed ContainsSpeed { get; } + + /// + /// Check whether this collection contains all the values in another collection. + /// If this collection has bag semantics (AllowsDuplicates==true) + /// the check is made with respect to multiplicities, else multiplicities + /// are not taken into account. + /// + /// The + /// True if all values in itemsis in this collection. + bool ContainsAll(IEnumerable items) where H : K; + + /// + /// Remove an entry with a given key from the dictionary + /// + /// The key of the entry to remove + /// True if an entry was found (and removed) + bool Remove(K key); + + + /// + /// Remove an entry with a given key from the dictionary and report its value. + /// + /// The key of the entry to remove + /// On exit, the value of the removed entry + /// True if an entry was found (and removed) + bool Remove(K key, out V val); + + + /// + /// Remove all entries from the dictionary + /// + void Clear(); + + + /// + /// Check if there is an entry with a specified key + /// + /// The key to look for + /// True if key was found + bool Contains(K key); + + /// + /// Check if there is an entry with a specified key and report the corresponding + /// value if found. This can be seen as a safe form of "val = this[key]". + /// + /// The key to look for + /// On exit, the value of the entry + /// True if key was found + bool Find(ref K key, out V val); + + + /// + /// Look for a specific key in the dictionary and if found replace the value with a new one. + /// This can be seen as a non-adding version of "this[key] = val". + /// + /// The key to look for + /// The new value + /// True if key was found + bool Update(K key, V val); //no-adding + + + /// + /// Look for a specific key in the dictionary and if found replace the value with a new one. + /// This can be seen as a non-adding version of "this[key] = val" reporting the old value. + /// + /// The key to look for + /// The new value + /// The old value if any + /// True if key was found + bool Update(K key, V val, out V oldval); //no-adding + + /// + /// Look for a specific key in the dictionary. If found, report the corresponding value, + /// else add an entry with the key and the supplied value. + /// + /// The key to look for + /// On entry the value to add if the key is not found. + /// On exit the value found if any. + /// True if key was found + bool FindOrAdd(K key, ref V val); //mixture + + + /// + /// Update value in dictionary corresponding to key if found, else add new entry. + /// More general than "this[key] = val;" by reporting if key was found. + /// + /// The key to look for + /// The value to add or replace with. + /// True if key was found and value updated. + bool UpdateOrAdd(K key, V val); + + + /// + /// Update value in dictionary corresponding to key if found, else add new entry. + /// More general than "this[key] = val;" by reporting if key was found. + /// + /// The key to look for + /// The value to add or replace with. + /// The old value if any + /// True if key was found and value updated. + bool UpdateOrAdd(K key, V val, out V oldval); + + + /// + /// Check the integrity of the internal data structures of this dictionary. + /// Only available in DEBUG builds??? + /// + /// True if check does not fail. + bool Check(); } \ No newline at end of file diff --git a/C5/Interfaces/IDirectedCollectionValue.cs b/C5/Interfaces/IDirectedCollectionValue.cs index d5324d13..e83e4841 100644 --- a/C5/Interfaces/IDirectedCollectionValue.cs +++ b/C5/Interfaces/IDirectedCollectionValue.cs @@ -1,29 +1,31 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// A sized generic collection, that can be enumerated backwards. +/// +public interface IDirectedCollectionValue : ICollectionValue, IDirectedEnumerable { /// - /// A sized generic collection, that can be enumerated backwards. + /// Create a collection containing the same items as this collection, but + /// whose enumerator will enumerate the items backwards. The new collection + /// will become invalid if the original is modified. Method typically used as in + /// foreach (T x in coll.Backwards()) {...} /// - public interface IDirectedCollectionValue : ICollectionValue, IDirectedEnumerable - { - /// - /// Create a collection containing the same items as this collection, but - /// whose enumerator will enumerate the items backwards. The new collection - /// will become invalid if the original is modified. Method typically used as in - /// foreach (T x in coll.Backwards()) {...} - /// - /// The backwards collection. - new IDirectedCollectionValue Backwards(); + /// The backwards collection. + new IDirectedCollectionValue Backwards(); - /// - /// Check if there exists an item that satisfies a - /// specific predicate in this collection and return the first one in enumeration order. - /// - /// A delegate - /// ( with R == bool) defining the predicate - /// - /// True is such an item exists - bool FindLast(Func predicate, out T item); - } + /// + /// Check if there exists an item that satisfies a + /// specific predicate in this collection and return the first one in enumeration order. + /// + /// A delegate + /// ( with R == bool) defining the predicate + /// + /// True is such an item exists + bool FindLast(Func predicate, out T item); } \ No newline at end of file diff --git a/C5/Interfaces/IDirectedEnumerable.cs b/C5/Interfaces/IDirectedEnumerable.cs index fbc4d5ba..ec5c5610 100644 --- a/C5/Interfaces/IDirectedEnumerable.cs +++ b/C5/Interfaces/IDirectedEnumerable.cs @@ -3,90 +3,89 @@ using System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// A generic collection, that can be enumerated backwards. +/// +public interface IDirectedEnumerable : IEnumerable // TODO: Type parameter should be 'out T' when Silverlight supports is (version 5 and onwards) { /// - /// A generic collection, that can be enumerated backwards. + /// Create a collection containing the same items as this collection, but + /// whose enumerator will enumerate the items backwards. The new collection + /// will become invalid if the original is modified. Method typically used as in + /// foreach (T x in coll.Backwards()) {...} /// - public interface IDirectedEnumerable : IEnumerable // TODO: Type parameter should be 'out T' when Silverlight supports is (version 5 and onwards) - { - /// - /// Create a collection containing the same items as this collection, but - /// whose enumerator will enumerate the items backwards. The new collection - /// will become invalid if the original is modified. Method typically used as in - /// foreach (T x in coll.Backwards()) {...} - /// - /// The backwards collection. - IDirectedEnumerable Backwards(); + /// The backwards collection. + IDirectedEnumerable Backwards(); - /// - /// Forwards if same, else Backwards - /// - /// The enumeration direction relative to the original collection. - Direction Direction { get; } - } + /// + /// Forwards if same, else Backwards + /// + /// The enumeration direction relative to the original collection. + Direction Direction { get; } +} - //TODO: decide if this should extend ICollection +//TODO: decide if this should extend ICollection - /*************************************************************************/ +/*************************************************************************/ - /*******************************************************************/ - /*/// - /// The type of an item comparer - /// Implementations of this interface must asure that the method is self-consistent - /// and defines a sorting order on items, or state precise conditions under which this is true. - /// Implementations must assure that repeated calls of - /// the method to the same (in reference or binary identity sense) arguments - /// will return values with the same sign (-1, 0 or +1), or state precise conditions - /// under which the user - /// can be assured repeated calls will return the same sign. - /// Implementations of this interface must always return values from the method - /// and never throw exceptions. - /// This interface is identical to System.Collections.Generic.IComparer<T> - /// - public interface ISystem.Collections.Generic.Comparer - { - /// - /// Compare two items with respect to this item comparer - /// - /// First item - /// Second item - /// Positive if item1 is greater than item2, 0 if they are equal, negative if item1 is less than item2 - int Compare(T item1, T item2); - } +/*******************************************************************/ +/*/// +/// The type of an item comparer +/// Implementations of this interface must asure that the method is self-consistent +/// and defines a sorting order on items, or state precise conditions under which this is true. +/// Implementations must assure that repeated calls of +/// the method to the same (in reference or binary identity sense) arguments +/// will return values with the same sign (-1, 0 or +1), or state precise conditions +/// under which the user +/// can be assured repeated calls will return the same sign. +/// Implementations of this interface must always return values from the method +/// and never throw exceptions. +/// This interface is identical to System.Collections.Generic.IComparer<T> +/// +public interface ISystem.Collections.Generic.Comparer +{ + /// + /// Compare two items with respect to this item comparer + /// + /// First item + /// Second item + /// Positive if item1 is greater than item2, 0 if they are equal, negative if item1 is less than item2 + int Compare(T item1, T item2); +} - /// - /// The type of an item equalityComparer. - /// Implementations of this interface must assure that the methods are - /// consistent, that is, that whenever two items i1 and i2 satisfies that Equals(i1,i2) - /// returns true, then GetHashCode returns the same value for i1 and i2. - /// Implementations of this interface must assure that repeated calls of - /// the methods to the same (in reference or binary identity sense) arguments - /// will return the same values, or state precise conditions under which the user - /// can be assured repeated calls will return the same values. - /// Implementations of this interface must always return values from the methods - /// and never throw exceptions. - /// This interface is similar in function to System.IKeyComparer<T> - /// - public interface System.Collections.Generic.IEqualityComparer - { - /// - /// Get the hash code with respect to this item equalityComparer - /// - /// The item - /// The hash code - int GetHashCode(T item); +/// +/// The type of an item equalityComparer. +/// Implementations of this interface must assure that the methods are +/// consistent, that is, that whenever two items i1 and i2 satisfies that Equals(i1,i2) +/// returns true, then GetHashCode returns the same value for i1 and i2. +/// Implementations of this interface must assure that repeated calls of +/// the methods to the same (in reference or binary identity sense) arguments +/// will return the same values, or state precise conditions under which the user +/// can be assured repeated calls will return the same values. +/// Implementations of this interface must always return values from the methods +/// and never throw exceptions. +/// This interface is similar in function to System.IKeyComparer<T> +/// +public interface System.Collections.Generic.IEqualityComparer +{ + /// + /// Get the hash code with respect to this item equalityComparer + /// + /// The item + /// The hash code + int GetHashCode(T item); - /// - /// Check if two items are equal with respect to this item equalityComparer - /// - /// first item - /// second item - /// True if equal - bool Equals(T item1, T item2); - }*/ -} + /// + /// Check if two items are equal with respect to this item equalityComparer + /// + /// first item + /// second item + /// True if equal + bool Equals(T item1, T item2); +}*/ diff --git a/C5/Interfaces/IExtensible.cs b/C5/Interfaces/IExtensible.cs index 48765ade..10833edb 100644 --- a/C5/Interfaces/IExtensible.cs +++ b/C5/Interfaces/IExtensible.cs @@ -1,72 +1,74 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// A generic collection to which one may add items. This is just the intersection +/// of the main stream generic collection interfaces and the priority queue interface, +/// and . +/// +public interface IExtensible : ICollectionValue { /// - /// A generic collection to which one may add items. This is just the intersection - /// of the main stream generic collection interfaces and the priority queue interface, - /// and . + /// If true any call of an updating operation will throw an + /// ReadOnlyCollectionException /// - public interface IExtensible : ICollectionValue - { - /// - /// If true any call of an updating operation will throw an - /// ReadOnlyCollectionException - /// - /// True if this collection is read-only. - bool IsReadOnly { get; } + /// True if this collection is read-only. + bool IsReadOnly { get; } - //TODO: wonder where the right position of this is - /// - /// - /// - /// False if this collection has set semantics, true if bag semantics. - bool AllowsDuplicates { get; } + //TODO: wonder where the right position of this is + /// + /// + /// + /// False if this collection has set semantics, true if bag semantics. + bool AllowsDuplicates { get; } - //TODO: wonder where the right position of this is. And the semantics. - /// - /// (Here should be a discussion of the role of equalityComparers. Any ). - /// - /// The equalityComparer used by this collection to check equality of items. - /// Or null (????) if collection does not check equality at all or uses a comparer. - System.Collections.Generic.IEqualityComparer EqualityComparer { get; } + //TODO: wonder where the right position of this is. And the semantics. + /// + /// (Here should be a discussion of the role of equalityComparers. Any ). + /// + /// The equalityComparer used by this collection to check equality of items. + /// Or null (????) if collection does not check equality at all or uses a comparer. + System.Collections.Generic.IEqualityComparer EqualityComparer { get; } - //ItemEqualityTypeEnum ItemEqualityType {get ;} + //ItemEqualityTypeEnum ItemEqualityType {get ;} - //TODO: find a good name + //TODO: find a good name - /// - /// By convention this is true for any collection with set semantics. - /// - /// True if only one representative of a group of equal items - /// is kept in the collection together with the total count. - bool DuplicatesByCounting { get; } + /// + /// By convention this is true for any collection with set semantics. + /// + /// True if only one representative of a group of equal items + /// is kept in the collection together with the total count. + bool DuplicatesByCounting { get; } - /// - /// Add an item to this collection if possible. If this collection has set - /// semantics, the item will be added if not already in the collection. If - /// bag semantics, the item will always be added. - /// - /// The item to add. - /// True if item was added. - bool Add(T item); + /// + /// Add an item to this collection if possible. If this collection has set + /// semantics, the item will be added if not already in the collection. If + /// bag semantics, the item will always be added. + /// + /// The item to add. + /// True if item was added. + bool Add(T item); - /// - /// Add the elements from another collection with a more specialized item type - /// to this collection. If this - /// collection has set semantics, only items not already in the collection - /// will be added. - /// - /// The items to add - void AddAll(IEnumerable items); + /// + /// Add the elements from another collection with a more specialized item type + /// to this collection. If this + /// collection has set semantics, only items not already in the collection + /// will be added. + /// + /// The items to add + void AddAll(IEnumerable items); - //void Clear(); // for priority queue - //int Count why not? - /// - /// Check the integrity of the internal data structures of this collection. - /// This is only relevant for developers of the library - /// - /// True if check was passed. - bool Check(); - } + //void Clear(); // for priority queue + //int Count why not? + /// + /// Check the integrity of the internal data structures of this collection. + /// This is only relevant for developers of the library + /// + /// True if check was passed. + bool Check(); } \ No newline at end of file diff --git a/C5/Interfaces/IIndexed.cs b/C5/Interfaces/IIndexed.cs index 4ef1f95f..6711362f 100644 --- a/C5/Interfaces/IIndexed.cs +++ b/C5/Interfaces/IIndexed.cs @@ -1,86 +1,88 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; using System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// A sequenced collection, where indices of items in the order are maintained +/// +public interface IIndexed : ISequenced, IReadOnlyList { /// - /// A sequenced collection, where indices of items in the order are maintained + /// Gets the number of elements in the collection. /// - public interface IIndexed : ISequenced, IReadOnlyList - { - /// - /// Gets the number of elements in the collection. - /// - new int Count { get; } + new int Count { get; } - /// - /// - /// - /// - Speed IndexingSpeed { get; } + /// + /// + /// + /// + Speed IndexingSpeed { get; } - /// - /// - /// - /// The directed collection of items in a specific index interval. - /// The low index of the interval (inclusive). - /// The size of the range. - IDirectedCollectionValue this[int start, int count] { get; } + /// + /// + /// + /// The directed collection of items in a specific index interval. + /// The low index of the interval (inclusive). + /// The size of the range. + IDirectedCollectionValue this[int start, int count] { get; } - /// - /// Searches for an item in the list going forwards from the start. - /// - /// Item to search for. - /// Index of item from start. A negative number if item not found, - /// namely the one's complement of the index at which the Add operation would put the item. - int IndexOf(T item); + /// + /// Searches for an item in the list going forwards from the start. + /// + /// Item to search for. + /// Index of item from start. A negative number if item not found, + /// namely the one's complement of the index at which the Add operation would put the item. + int IndexOf(T item); - /// - /// Searches for an item in the list going backwards from the end. - /// - /// Item to search for. - /// Index of of item from the end. A negative number if item not found, - /// namely the two-complement of the index at which the Add operation would put the item. - int LastIndexOf(T item); + /// + /// Searches for an item in the list going backwards from the end. + /// + /// Item to search for. + /// Index of of item from the end. A negative number if item not found, + /// namely the two-complement of the index at which the Add operation would put the item. + int LastIndexOf(T item); - /// - /// Check if there exists an item that satisfies a - /// specific predicate in this collection and return the index of the first one. - /// - /// A delegate - /// ( with R == bool) defining the predicate - /// the index, if found, a negative value else - int FindIndex(Func predicate); + /// + /// Check if there exists an item that satisfies a + /// specific predicate in this collection and return the index of the first one. + /// + /// A delegate + /// ( with R == bool) defining the predicate + /// the index, if found, a negative value else + int FindIndex(Func predicate); - /// - /// Check if there exists an item that satisfies a - /// specific predicate in this collection and return the index of the last one. - /// - /// A delegate - /// ( with R == bool) defining the predicate - /// the index, if found, a negative value else - int FindLastIndex(Func predicate); + /// + /// Check if there exists an item that satisfies a + /// specific predicate in this collection and return the index of the last one. + /// + /// A delegate + /// ( with R == bool) defining the predicate + /// the index, if found, a negative value else + int FindLastIndex(Func predicate); - /// - /// Remove the item at a specific position of the list. - /// - /// if index is negative or - /// >= the size of the collection. - /// The index of the item to remove. - /// The removed item. - T RemoveAt(int index); + /// + /// Remove the item at a specific position of the list. + /// + /// if index is negative or + /// >= the size of the collection. + /// The index of the item to remove. + /// The removed item. + T RemoveAt(int index); - /// - /// Remove all items in an index interval. - /// - /// if start or count - /// is negative or start+count > the size of the collection. - /// The index of the first item to remove. - /// The number of items to remove. - void RemoveInterval(int start, int count); - } + /// + /// Remove all items in an index interval. + /// + /// if start or count + /// is negative or start+count > the size of the collection. + /// The index of the first item to remove. + /// The number of items to remove. + void RemoveInterval(int start, int count); } \ No newline at end of file diff --git a/C5/Interfaces/IIndexedSorted.cs b/C5/Interfaces/IIndexedSorted.cs index 304f1757..79e46e49 100644 --- a/C5/Interfaces/IIndexedSorted.cs +++ b/C5/Interfaces/IIndexedSorted.cs @@ -1,82 +1,84 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// A collection where items are maintained in sorted order together +/// with their indexes in that order. +/// +public interface IIndexedSorted : ISorted, IIndexed { /// - /// A collection where items are maintained in sorted order together - /// with their indexes in that order. + /// Determine the number of items at or above a supplied threshold. + /// + /// The lower bound (inclusive) + /// The number of matching items. + int CountFrom(T bot); + + + /// + /// Determine the number of items between two supplied thresholds. + /// + /// The lower bound (inclusive) + /// The upper bound (exclusive) + /// The number of matching items. + int CountFromTo(T bot, T top); + + + /// + /// Determine the number of items below a supplied threshold. + /// + /// The upper bound (exclusive) + /// The number of matching items. + int CountTo(T top); + + + /// + /// Query this sorted collection for items greater than or equal to a supplied value. + /// + /// The lower bound (inclusive). + /// The result directed collection. + new IDirectedCollectionValue RangeFrom(T bot); + + + /// + /// Query this sorted collection for items between two supplied values. + /// + /// The lower bound (inclusive). + /// The upper bound (exclusive). + /// The result directed collection. + new IDirectedCollectionValue RangeFromTo(T bot, T top); + + + /// + /// Query this sorted collection for items less than a supplied value. + /// + /// The upper bound (exclusive). + /// The result directed collection. + new IDirectedCollectionValue RangeTo(T top); + + + /// + /// Create a new indexed sorted collection consisting of the items of this + /// indexed sorted collection satisfying a certain predicate. + /// + /// The filter delegate defining the predicate. + /// The new indexed sorted collection. + IIndexedSorted FindAll(Func predicate); + + + /// + /// Create a new indexed sorted collection consisting of the results of + /// mapping all items of this list. + /// if the map is not increasing over + /// the items of this collection (with respect to the two given comparison + /// relations). /// - public interface IIndexedSorted : ISorted, IIndexed - { - /// - /// Determine the number of items at or above a supplied threshold. - /// - /// The lower bound (inclusive) - /// The number of matching items. - int CountFrom(T bot); - - - /// - /// Determine the number of items between two supplied thresholds. - /// - /// The lower bound (inclusive) - /// The upper bound (exclusive) - /// The number of matching items. - int CountFromTo(T bot, T top); - - - /// - /// Determine the number of items below a supplied threshold. - /// - /// The upper bound (exclusive) - /// The number of matching items. - int CountTo(T top); - - - /// - /// Query this sorted collection for items greater than or equal to a supplied value. - /// - /// The lower bound (inclusive). - /// The result directed collection. - new IDirectedCollectionValue RangeFrom(T bot); - - - /// - /// Query this sorted collection for items between two supplied values. - /// - /// The lower bound (inclusive). - /// The upper bound (exclusive). - /// The result directed collection. - new IDirectedCollectionValue RangeFromTo(T bot, T top); - - - /// - /// Query this sorted collection for items less than a supplied value. - /// - /// The upper bound (exclusive). - /// The result directed collection. - new IDirectedCollectionValue RangeTo(T top); - - - /// - /// Create a new indexed sorted collection consisting of the items of this - /// indexed sorted collection satisfying a certain predicate. - /// - /// The filter delegate defining the predicate. - /// The new indexed sorted collection. - IIndexedSorted FindAll(Func predicate); - - - /// - /// Create a new indexed sorted collection consisting of the results of - /// mapping all items of this list. - /// if the map is not increasing over - /// the items of this collection (with respect to the two given comparison - /// relations). - /// - /// The delegate definging the map. - /// The comparion relation to use for the result. - /// The new sorted collection. - IIndexedSorted Map(Func mapper, System.Collections.Generic.IComparer comparer); - } + /// The delegate definging the map. + /// The comparion relation to use for the result. + /// The new sorted collection. + IIndexedSorted Map(Func mapper, System.Collections.Generic.IComparer comparer); } \ No newline at end of file diff --git a/C5/Interfaces/IList.cs b/C5/Interfaces/IList.cs index 17bae531..71196426 100644 --- a/C5/Interfaces/IList.cs +++ b/C5/Interfaces/IList.cs @@ -1,363 +1,365 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; using System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// This is an indexed collection, where the item order is chosen by +/// the user at insertion time. +/// +/// NBNBNB: we need a description of the view functionality here! +/// +public interface IList : IIndexed, IDisposable, System.Collections.Generic.IList, System.Collections.IList { /// - /// This is an indexed collection, where the item order is chosen by - /// the user at insertion time. + /// + /// if this list is empty. + /// The first item in this list. + T First { get; } + + /// + /// + /// if this list is empty. + /// The last item in this list. + T Last { get; } + + /// + /// Since Add(T item) always add at the end of the list, + /// this describes if list has FIFO or LIFO semantics. + /// + /// True if the Remove() operation removes from the + /// start of the list, false if it removes from the end. + bool FIFO { get; set; } + + /// + /// On this list, this indexer is read/write. + /// + /// if index is negative or + /// >= the size of the collection. + /// The index'th item of this list. + /// The index of the item to fetch or store. + new T this[int index] { get; set; } + + #region Ambiguous calls when extending System.Collections.Generic.IList + + #region System.Collections.Generic.ICollection + /// + /// + /// + new int Count { get; } + + /// + /// + /// + new bool IsReadOnly { get; } + + /// + /// + /// + /// + /// + new bool Add(T item); + + /// + /// + /// + new void Clear(); + + /// + /// + /// + /// + /// + new bool Contains(T item); + + /// + /// + /// + /// + /// + new void CopyTo(T[] array, int index); + + /// /// - /// NBNBNB: we need a description of the view functionality here! - /// - public interface IList : IIndexed, IDisposable, System.Collections.Generic.IList, System.Collections.IList - { - /// - /// - /// if this list is empty. - /// The first item in this list. - T First { get; } - - /// - /// - /// if this list is empty. - /// The last item in this list. - T Last { get; } - - /// - /// Since Add(T item) always add at the end of the list, - /// this describes if list has FIFO or LIFO semantics. - /// - /// True if the Remove() operation removes from the - /// start of the list, false if it removes from the end. - bool FIFO { get; set; } - - /// - /// On this list, this indexer is read/write. - /// - /// if index is negative or - /// >= the size of the collection. - /// The index'th item of this list. - /// The index of the item to fetch or store. - new T this[int index] { get; set; } - - #region Ambiguous calls when extending System.Collections.Generic.IList - - #region System.Collections.Generic.ICollection - /// - /// - /// - new int Count { get; } - - /// - /// - /// - new bool IsReadOnly { get; } - - /// - /// - /// - /// - /// - new bool Add(T item); - - /// - /// - /// - new void Clear(); - - /// - /// - /// - /// - /// - new bool Contains(T item); - - /// - /// - /// - /// - /// - new void CopyTo(T[] array, int index); - - /// - /// - /// - /// - /// - new bool Remove(T item); - - #endregion - - #region System.Collections.Generic.IList proper - - /// - /// Searches for an item in the list going forwards from the start. - /// - /// Item to search for. - /// Index of item from start. A negative number if item not found, - /// namely the one's complement of the index at which the Add operation would put the item. - new int IndexOf(T item); - - /// - /// Remove the item at a specific position of the list. - /// - /// if index is negative or - /// >= the size of the collection. - /// The index of the item to remove. - /// The removed item. - new T RemoveAt(int index); - - #endregion - - #endregion - - /*/// - /// Insert an item at a specific index location in this list. + /// + /// + /// + new bool Remove(T item); + + #endregion + + #region System.Collections.Generic.IList proper + + /// + /// Searches for an item in the list going forwards from the start. + /// + /// Item to search for. + /// Index of item from start. A negative number if item not found, + /// namely the one's complement of the index at which the Add operation would put the item. + new int IndexOf(T item); + + /// + /// Remove the item at a specific position of the list. /// /// if index is negative or - /// > the size of the collection. + /// >= the size of the collection. + /// The index of the item to remove. + /// The removed item. + new T RemoveAt(int index); + + #endregion + + #endregion + + /*/// +/// Insert an item at a specific index location in this list. +/// +/// if index is negative or +/// > the size of the collection. +/// if the list has +/// AllowsDuplicates==false and the item is +/// already in the list. +/// The index at which to insert. +/// The item to insert. +void Insert(int index, T item);*/ + + /// + /// Insert an item at the end of a compatible view, used as a pointer. + /// The pointer must be a view on the same list as + /// this and the endpoint of pointer must be + /// a valid insertion point of this + /// + /// If pointer + /// is not a view on the same list as this + /// ?????? if the endpoint of + /// pointer is not inside this /// if the list has - /// AllowsDuplicates==false and the item is + /// AllowsDuplicates==false and the item is /// already in the list. - /// The index at which to insert. + /// + /// + void Insert(IList pointer, T item); + + /// + /// Insert an item at the front of this list. + /// if the list has + /// AllowsDuplicates==false and the item is + /// already in the list. + /// /// The item to insert. - void Insert(int index, T item);*/ - - /// - /// Insert an item at the end of a compatible view, used as a pointer. - /// The pointer must be a view on the same list as - /// this and the endpoint of pointer must be - /// a valid insertion point of this - /// - /// If pointer - /// is not a view on the same list as this - /// ?????? if the endpoint of - /// pointer is not inside this - /// if the list has - /// AllowsDuplicates==false and the item is - /// already in the list. - /// - /// - void Insert(IList pointer, T item); - - /// - /// Insert an item at the front of this list. - /// if the list has - /// AllowsDuplicates==false and the item is - /// already in the list. - /// - /// The item to insert. - void InsertFirst(T item); - - /// - /// Insert an item at the back of this list. - /// if the list has - /// AllowsDuplicates==false and the item is - /// already in the list. - /// - /// The item to insert. - void InsertLast(T item); - - /// - /// Insert into this list all items from an enumerable collection starting - /// at a particular index. - /// - /// if index is negative or - /// > the size of the collection. - /// if the list has - /// AllowsDuplicates==false and one of the items to insert is - /// already in the list. - /// Index to start inserting at - /// Items to insert - void InsertAll(int index, IEnumerable items); - - /// - /// Create a new list consisting of the items of this list satisfying a - /// certain predicate. - /// - /// The filter delegate defining the predicate. - /// The new list. - IList FindAll(Func filter); - - /// - /// Create a new list consisting of the results of mapping all items of this - /// list. The new list will use the default equalityComparer for the item type V. - /// - /// The type of items of the new list - /// The delegate defining the map. - /// The new list. - IList Map(Func mapper); - - /// - /// Create a new list consisting of the results of mapping all items of this - /// list. The new list will use a specified equalityComparer for the item type. - /// - /// The type of items of the new list - /// The delegate defining the map. - /// The equalityComparer to use for the new list - /// The new list. - IList Map(Func mapper, System.Collections.Generic.IEqualityComparer equalityComparer); - - /// - /// Remove one item from the list: from the front if FIFO - /// is true, else from the back. - /// if this list is empty. - /// - /// The removed item. - T Remove(); - - /// - /// Remove one item from the front of the list. - /// if this list is empty. - /// - /// The removed item. - T RemoveFirst(); - - /// - /// Remove one item from the back of the list. - /// if this list is empty. - /// - /// The removed item. - T RemoveLast(); - - /// - /// Create a list view on this list. - /// if the view would not fit into - /// this list. - /// - /// The index in this list of the start of the view. - /// The size of the view. - /// The new list view. - IList? View(int start, int count); - - /// - /// Create a list view on this list containing the (first) occurrence of a particular item. - /// if the item is not in this list. - /// - /// The item to find. - /// The new list view. - IList? ViewOf(T item); - - /// - /// Create a list view on this list containing the last occurrence of a particular item. - /// if the item is not in this list. - /// - /// The item to find. - /// The new list view. - IList? LastViewOf(T item); - - /// - /// Null if this list is not a view. - /// - /// Underlying list for view. - IList? Underlying { get; } - - /// - /// - /// Offset for this list view or 0 for an underlying list. - int Offset { get; } - - /// - /// - /// - /// - bool IsValid { get; } - - /// - /// Slide this list view along the underlying list. - /// - /// if this list is not a view. - /// if the operation - /// would bring either end of the view outside the underlying list. - /// The signed amount to slide: positive to slide - /// towards the end. - IList Slide(int offset); - - /// - /// Slide this list view along the underlying list, changing its size. - /// - /// - /// if this list is not a view. - /// if the operation - /// would bring either end of the view outside the underlying list. - /// The signed amount to slide: positive to slide - /// towards the end. - /// The new size of the view. - IList Slide(int offset, int size); - - /// - /// - /// - /// - /// - bool TrySlide(int offset); - - /// - /// - /// - /// - /// - /// - bool TrySlide(int offset, int size); - - /// - /// - /// Returns null if otherView is strictly to the left of this view - /// - /// - /// If otherView does not have the same underlying list as this - /// If otherView is strictly to the left of this view - /// - IList? Span(IList otherView); - - /// - /// Reverse the list so the items are in the opposite sequence order. - /// - void Reverse(); - - /// - /// Check if this list is sorted according to the default sorting order - /// for the item type T, as defined by the class - /// - /// if T is not comparable - /// True if the list is sorted, else false. - bool IsSorted(); - - /// - /// Check if this list is sorted according to a specific sorting order. - /// - /// The comparer defining the sorting order. - /// True if the list is sorted, else false. - bool IsSorted(System.Collections.Generic.IComparer comparer); - - /// - /// Sort the items of the list according to the default sorting order - /// for the item type T, as defined by the class - /// - /// if T is not comparable - void Sort(); - - /// - /// Sort the items of the list according to a specified sorting order. - /// The sorting does not perform duplicate elimination or identify items - /// according to the comparer or itemequalityComparer. I.e. the list as an - /// unsequenced collection with binary equality, will not change. - /// - /// - /// The comparer defining the sorting order. - void Sort(System.Collections.Generic.IComparer comparer); - - - /// - /// Randomly shuffle the items of this list. - /// - void Shuffle(); - - - /// - /// Shuffle the items of this list according to a specific random source. - /// - /// The random source. - void Shuffle(Random rnd); - } + void InsertFirst(T item); + + /// + /// Insert an item at the back of this list. + /// if the list has + /// AllowsDuplicates==false and the item is + /// already in the list. + /// + /// The item to insert. + void InsertLast(T item); + + /// + /// Insert into this list all items from an enumerable collection starting + /// at a particular index. + /// + /// if index is negative or + /// > the size of the collection. + /// if the list has + /// AllowsDuplicates==false and one of the items to insert is + /// already in the list. + /// Index to start inserting at + /// Items to insert + void InsertAll(int index, IEnumerable items); + + /// + /// Create a new list consisting of the items of this list satisfying a + /// certain predicate. + /// + /// The filter delegate defining the predicate. + /// The new list. + IList FindAll(Func filter); + + /// + /// Create a new list consisting of the results of mapping all items of this + /// list. The new list will use the default equalityComparer for the item type V. + /// + /// The type of items of the new list + /// The delegate defining the map. + /// The new list. + IList Map(Func mapper); + + /// + /// Create a new list consisting of the results of mapping all items of this + /// list. The new list will use a specified equalityComparer for the item type. + /// + /// The type of items of the new list + /// The delegate defining the map. + /// The equalityComparer to use for the new list + /// The new list. + IList Map(Func mapper, System.Collections.Generic.IEqualityComparer equalityComparer); + + /// + /// Remove one item from the list: from the front if FIFO + /// is true, else from the back. + /// if this list is empty. + /// + /// The removed item. + T Remove(); + + /// + /// Remove one item from the front of the list. + /// if this list is empty. + /// + /// The removed item. + T RemoveFirst(); + + /// + /// Remove one item from the back of the list. + /// if this list is empty. + /// + /// The removed item. + T RemoveLast(); + + /// + /// Create a list view on this list. + /// if the view would not fit into + /// this list. + /// + /// The index in this list of the start of the view. + /// The size of the view. + /// The new list view. + IList? View(int start, int count); + + /// + /// Create a list view on this list containing the (first) occurrence of a particular item. + /// if the item is not in this list. + /// + /// The item to find. + /// The new list view. + IList? ViewOf(T item); + + /// + /// Create a list view on this list containing the last occurrence of a particular item. + /// if the item is not in this list. + /// + /// The item to find. + /// The new list view. + IList? LastViewOf(T item); + + /// + /// Null if this list is not a view. + /// + /// Underlying list for view. + IList? Underlying { get; } + + /// + /// + /// Offset for this list view or 0 for an underlying list. + int Offset { get; } + + /// + /// + /// + /// + bool IsValid { get; } + + /// + /// Slide this list view along the underlying list. + /// + /// if this list is not a view. + /// if the operation + /// would bring either end of the view outside the underlying list. + /// The signed amount to slide: positive to slide + /// towards the end. + IList Slide(int offset); + + /// + /// Slide this list view along the underlying list, changing its size. + /// + /// + /// if this list is not a view. + /// if the operation + /// would bring either end of the view outside the underlying list. + /// The signed amount to slide: positive to slide + /// towards the end. + /// The new size of the view. + IList Slide(int offset, int size); + + /// + /// + /// + /// + /// + bool TrySlide(int offset); + + /// + /// + /// + /// + /// + /// + bool TrySlide(int offset, int size); + + /// + /// + /// Returns null if otherView is strictly to the left of this view + /// + /// + /// If otherView does not have the same underlying list as this + /// If otherView is strictly to the left of this view + /// + IList? Span(IList otherView); + + /// + /// Reverse the list so the items are in the opposite sequence order. + /// + void Reverse(); + + /// + /// Check if this list is sorted according to the default sorting order + /// for the item type T, as defined by the class + /// + /// if T is not comparable + /// True if the list is sorted, else false. + bool IsSorted(); + + /// + /// Check if this list is sorted according to a specific sorting order. + /// + /// The comparer defining the sorting order. + /// True if the list is sorted, else false. + bool IsSorted(System.Collections.Generic.IComparer comparer); + + /// + /// Sort the items of the list according to the default sorting order + /// for the item type T, as defined by the class + /// + /// if T is not comparable + void Sort(); + + /// + /// Sort the items of the list according to a specified sorting order. + /// The sorting does not perform duplicate elimination or identify items + /// according to the comparer or itemequalityComparer. I.e. the list as an + /// unsequenced collection with binary equality, will not change. + /// + /// + /// The comparer defining the sorting order. + void Sort(System.Collections.Generic.IComparer comparer); + + + /// + /// Randomly shuffle the items of this list. + /// + void Shuffle(); + + + /// + /// Shuffle the items of this list according to a specific random source. + /// + /// The random source. + void Shuffle(Random rnd); } \ No newline at end of file diff --git a/C5/Interfaces/IPersistentSorted.cs b/C5/Interfaces/IPersistentSorted.cs index 3b4c2f42..095bad6c 100644 --- a/C5/Interfaces/IPersistentSorted.cs +++ b/C5/Interfaces/IPersistentSorted.cs @@ -1,16 +1,18 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// The type of a sorted collection with persistence +/// +public interface IPersistentSorted : ISorted, IDisposable { /// - /// The type of a sorted collection with persistence + /// Make a (read-only) snap shot of this collection. /// - public interface IPersistentSorted : ISorted, IDisposable - { - /// - /// Make a (read-only) snap shot of this collection. - /// - /// The snap shot. - ISorted Snapshot(); - } + /// The snap shot. + ISorted Snapshot(); } \ No newline at end of file diff --git a/C5/Interfaces/IPriorityQueue.cs b/C5/Interfaces/IPriorityQueue.cs index 58c326cb..c76d053d 100644 --- a/C5/Interfaces/IPriorityQueue.cs +++ b/C5/Interfaces/IPriorityQueue.cs @@ -1,124 +1,126 @@ -namespace C5 +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +namespace C5; + +/// +/// A generic collection of items prioritized by a comparison (order) relation. +/// Supports adding items and reporting or removing extremal elements. +/// +/// +/// +/// When adding an item, the user may choose to have a handle allocated for this item in the queue. +/// The resulting handle may be used for deleting the item even if not extremal, and for replacing the item. +/// A priority queue typically only holds numeric priorities associated with some objects +/// maintained separately in other collection objects. +/// +public interface IPriorityQueue : IExtensible { /// - /// A generic collection of items prioritized by a comparison (order) relation. - /// Supports adding items and reporting or removing extremal elements. - /// - /// - /// - /// When adding an item, the user may choose to have a handle allocated for this item in the queue. - /// The resulting handle may be used for deleting the item even if not extremal, and for replacing the item. - /// A priority queue typically only holds numeric priorities associated with some objects - /// maintained separately in other collection objects. + /// Find the current least item of this priority queue. /// - public interface IPriorityQueue : IExtensible - { - /// - /// Find the current least item of this priority queue. - /// - /// The least item. - T FindMin(); - - - /// - /// Remove the least item from this priority queue. - /// - /// The removed item. - T DeleteMin(); - - - /// - /// Find the current largest item of this priority queue. - /// - /// The largest item. - T FindMax(); - - - /// - /// Remove the largest item from this priority queue. - /// - /// The removed item. - T DeleteMax(); - - /// - /// The comparer object supplied at creation time for this collection - /// - /// The comparer - System.Collections.Generic.IComparer Comparer { get; } - /// - /// Get or set the item corresponding to a handle. Throws exceptions on - /// invalid handles. - /// - /// - /// - T this[IPriorityQueueHandle handle] { get; set; } - - /// - /// Check if the entry corresponding to a handle is in the priority queue. - /// - /// - /// - /// - bool Find(IPriorityQueueHandle handle, out T item); - - /// - /// Add an item to the priority queue, receiving a - /// handle for the item in the queue, - /// or reusing an existing unused handle. - /// - /// On output: a handle for the added item. - /// On input: null for allocating a new handle, or a currently unused handle for reuse. - /// A handle for reuse must be compatible with this priority queue, - /// by being created by a priority queue of the same runtime type, but not - /// necessarily the same priority queue object. - /// - /// - bool Add(ref IPriorityQueueHandle handle, T item); - - /// - /// Delete an item with a handle from a priority queue - /// - /// The handle for the item. The handle will be invalidated, but reusable. - /// The deleted item - T Delete(IPriorityQueueHandle handle); - - /// - /// Replace an item with a handle in a priority queue with a new item. - /// Typically used for changing the priority of some queued object. - /// - /// The handle for the old item - /// The new item - /// The old item - T Replace(IPriorityQueueHandle handle, T item); - - /// - /// Find the current least item of this priority queue. - /// - /// On return: the handle of the item. - /// The least item. - T FindMin(out IPriorityQueueHandle handle); - - /// - /// Find the current largest item of this priority queue. - /// - /// On return: the handle of the item. - /// The largest item. - - T FindMax(out IPriorityQueueHandle handle); - - /// - /// Remove the least item from this priority queue. - /// - /// On return: the handle of the removed item. - /// The removed item. - - T DeleteMin(out IPriorityQueueHandle handle); - - /// - /// Remove the largest item from this priority queue. - /// - /// On return: the handle of the removed item. - /// The removed item. - T DeleteMax(out IPriorityQueueHandle handle); - } + /// The least item. + T FindMin(); + + + /// + /// Remove the least item from this priority queue. + /// + /// The removed item. + T DeleteMin(); + + + /// + /// Find the current largest item of this priority queue. + /// + /// The largest item. + T FindMax(); + + + /// + /// Remove the largest item from this priority queue. + /// + /// The removed item. + T DeleteMax(); + + /// + /// The comparer object supplied at creation time for this collection + /// + /// The comparer + System.Collections.Generic.IComparer Comparer { get; } + /// + /// Get or set the item corresponding to a handle. Throws exceptions on + /// invalid handles. + /// + /// + /// + T this[IPriorityQueueHandle handle] { get; set; } + + /// + /// Check if the entry corresponding to a handle is in the priority queue. + /// + /// + /// + /// + bool Find(IPriorityQueueHandle handle, out T item); + + /// + /// Add an item to the priority queue, receiving a + /// handle for the item in the queue, + /// or reusing an existing unused handle. + /// + /// On output: a handle for the added item. + /// On input: null for allocating a new handle, or a currently unused handle for reuse. + /// A handle for reuse must be compatible with this priority queue, + /// by being created by a priority queue of the same runtime type, but not + /// necessarily the same priority queue object. + /// + /// + bool Add(ref IPriorityQueueHandle handle, T item); + + /// + /// Delete an item with a handle from a priority queue + /// + /// The handle for the item. The handle will be invalidated, but reusable. + /// The deleted item + T Delete(IPriorityQueueHandle handle); + + /// + /// Replace an item with a handle in a priority queue with a new item. + /// Typically used for changing the priority of some queued object. + /// + /// The handle for the old item + /// The new item + /// The old item + T Replace(IPriorityQueueHandle handle, T item); + + /// + /// Find the current least item of this priority queue. + /// + /// On return: the handle of the item. + /// The least item. + T FindMin(out IPriorityQueueHandle handle); + + /// + /// Find the current largest item of this priority queue. + /// + /// On return: the handle of the item. + /// The largest item. + + T FindMax(out IPriorityQueueHandle handle); + + /// + /// Remove the least item from this priority queue. + /// + /// On return: the handle of the removed item. + /// The removed item. + + T DeleteMin(out IPriorityQueueHandle handle); + + /// + /// Remove the largest item from this priority queue. + /// + /// On return: the handle of the removed item. + /// The removed item. + T DeleteMax(out IPriorityQueueHandle handle); } \ No newline at end of file diff --git a/C5/Interfaces/IPriorityQueueHandle.cs b/C5/Interfaces/IPriorityQueueHandle.cs index 1f617d1b..4ad8228e 100644 --- a/C5/Interfaces/IPriorityQueueHandle.cs +++ b/C5/Interfaces/IPriorityQueueHandle.cs @@ -1,13 +1,15 @@ -namespace C5 +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +namespace C5; + +/// +/// The base type of a priority queue handle +/// +/// +public interface IPriorityQueueHandle { - /// - /// The base type of a priority queue handle - /// - /// - public interface IPriorityQueueHandle - { - //TODO: make abstract and prepare for double dispatch: - //public virtual bool Delete(IPriorityQueue q) { throw new InvalidFooException();} - //bool Replace(T item); - } + //TODO: make abstract and prepare for double dispatch: + //public virtual bool Delete(IPriorityQueue q) { throw new InvalidFooException();} + //bool Replace(T item); } \ No newline at end of file diff --git a/C5/Interfaces/IQueue.cs b/C5/Interfaces/IQueue.cs index 5bd26430..1c50177d 100644 --- a/C5/Interfaces/IQueue.cs +++ b/C5/Interfaces/IQueue.cs @@ -1,31 +1,33 @@ -namespace C5 +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +namespace C5; + +/// +/// The interface describing the operations of a FIFO queue data structure. +/// +/// The item type +public interface IQueue : IDirectedCollectionValue { /// - /// The interface describing the operations of a FIFO queue data structure. + /// /// - /// The item type - public interface IQueue : IDirectedCollectionValue - { - /// - /// - /// - /// - bool AllowsDuplicates { get; } - /// - /// Get the index'th element of the queue. The front of the queue has index 0. - /// - /// - /// - T this[int index] { get; } - /// - /// Enqueue an item at the back of the queue. - /// - /// The item - void Enqueue(T item); - /// - /// Dequeue an item from the front of the queue. - /// - /// The item - T Dequeue(); - } + /// + bool AllowsDuplicates { get; } + /// + /// Get the index'th element of the queue. The front of the queue has index 0. + /// + /// + /// + T this[int index] { get; } + /// + /// Enqueue an item at the back of the queue. + /// + /// The item + void Enqueue(T item); + /// + /// Dequeue an item from the front of the queue. + /// + /// The item + T Dequeue(); } \ No newline at end of file diff --git a/C5/Interfaces/ISequenced.cs b/C5/Interfaces/ISequenced.cs index d7e12206..c9e0cb30 100644 --- a/C5/Interfaces/ISequenced.cs +++ b/C5/Interfaces/ISequenced.cs @@ -1,31 +1,33 @@ -namespace C5 +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +namespace C5; + +/// +/// An editable collection maintaining a definite sequence order of the items. +/// +/// Implementations of this interface must compute the hash code and +/// equality exactly as prescribed in the method definitions in order to +/// be consistent with other collection classes implementing this interface. +/// This interface is usually implemented by explicit interface implementation, +/// not as ordinary virtual methods. +/// +public interface ISequenced : ICollection, IDirectedCollectionValue { /// - /// An editable collection maintaining a definite sequence order of the items. - /// - /// Implementations of this interface must compute the hash code and - /// equality exactly as prescribed in the method definitions in order to - /// be consistent with other collection classes implementing this interface. - /// This interface is usually implemented by explicit interface implementation, - /// not as ordinary virtual methods. + /// The hashcode is defined as h(...h(h(h(x1),x2),x3),...,xn) for + /// h(a,b)=CONSTANT*a+b and the x's the hash codes of the items of + /// this collection. /// - public interface ISequenced : ICollection, IDirectedCollectionValue - { - /// - /// The hashcode is defined as h(...h(h(h(x1),x2),x3),...,xn) for - /// h(a,b)=CONSTANT*a+b and the x's the hash codes of the items of - /// this collection. - /// - /// The sequence order hashcode of this collection. - int GetSequencedHashCode(); + /// The sequence order hashcode of this collection. + int GetSequencedHashCode(); - /// - /// Compare this sequenced collection to another one in sequence order. - /// - /// The sequenced collection to compare to. - /// True if this collection and that contains equal (according to - /// this collection's itemequalityComparer) in the same sequence order. - bool SequencedEquals(ISequenced otherCollection); - } + /// + /// Compare this sequenced collection to another one in sequence order. + /// + /// The sequenced collection to compare to. + /// True if this collection and that contains equal (according to + /// this collection's itemequalityComparer) in the same sequence order. + bool SequencedEquals(ISequenced otherCollection); } \ No newline at end of file diff --git a/C5/Interfaces/IShowable.cs b/C5/Interfaces/IShowable.cs index 99f1a569..bf9d7ba7 100644 --- a/C5/Interfaces/IShowable.cs +++ b/C5/Interfaces/IShowable.cs @@ -1,23 +1,25 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; using System.Text; -namespace C5 +namespace C5; + +/// +/// (Describe usage of "L:300" format string.) +/// +public interface IShowable : IFormattable { + //TODO: wonder if we should use TextWriters instead of StringBuilders? /// - /// (Describe usage of "L:300" format string.) + /// Format this using at most approximately rest chars and + /// append the result, possibly truncated, to stringbuilder. + /// Subtract the actual number of used chars from rest. /// - public interface IShowable : IFormattable - { - //TODO: wonder if we should use TextWriters instead of StringBuilders? - /// - /// Format this using at most approximately rest chars and - /// append the result, possibly truncated, to stringbuilder. - /// Subtract the actual number of used chars from rest. - /// - /// - /// - /// - /// True if the appended formatted string was complete (not truncated). - bool Show(StringBuilder stringbuilder, ref int rest, IFormatProvider? formatProvider); - } + /// + /// + /// + /// True if the appended formatted string was complete (not truncated). + bool Show(StringBuilder stringbuilder, ref int rest, IFormatProvider? formatProvider); } \ No newline at end of file diff --git a/C5/Interfaces/ISorted.cs b/C5/Interfaces/ISorted.cs index 45ff8b6e..ebeb5f24 100644 --- a/C5/Interfaces/ISorted.cs +++ b/C5/Interfaces/ISorted.cs @@ -1,277 +1,279 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; using System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// A sorted collection, i.e. a collection where items are maintained and can be searched for in sorted order. +/// Thus the sequence order is given as a sorting order. +/// +/// The sorting order is defined by a comparer, an object of type IComparer<T> +/// (). Implementors of this interface will normally let the user +/// define the comparer as an argument to a constructor. +/// Usually there will also be constructors without a comparer argument, in which case the +/// comparer should be the defalt comparer for the item type, . +/// +/// The comparer of the sorted collection is available as the System.Collections.Generic.Comparer property +/// (). +/// +/// The methods are grouped according to +/// +/// Extrema: report or report and delete an extremal item. This is reminiscent of simplified priority queues. +/// Nearest neighbor: report predecessor or successor in the collection of an item. Cut belongs to this group. +/// Range: report a view of a range of elements or remove all elements in a range. +/// AddSorted: add a collection of items known to be sorted in the same order (should be faster) (to be removed?) +/// +/// +/// +/// Since this interface extends ISequenced<T>, sorted collections will also have an +/// item equalityComparer (). This equalityComparer will not be used in connection with +/// the inner workings of the sorted collection, but will be used if the sorted collection is used as +/// an item in a collection of unsequenced or sequenced collections, +/// ( and ) +/// +/// Note that code may check if two sorted collections has the same sorting order +/// by checking if the Comparer properties are equal. This is done a few places in this library +/// for optimization purposes. +/// +public interface ISorted : ISequenced { /// - /// A sorted collection, i.e. a collection where items are maintained and can be searched for in sorted order. - /// Thus the sequence order is given as a sorting order. - /// - /// The sorting order is defined by a comparer, an object of type IComparer<T> - /// (). Implementors of this interface will normally let the user - /// define the comparer as an argument to a constructor. - /// Usually there will also be constructors without a comparer argument, in which case the - /// comparer should be the defalt comparer for the item type, . - /// - /// The comparer of the sorted collection is available as the System.Collections.Generic.Comparer property - /// (). - /// - /// The methods are grouped according to + /// Find the current least item of this sorted collection. + /// + /// if the collection is empty. + /// The least item. + T FindMin(); + + + /// + /// Remove the least item from this sorted collection. + /// + /// if the collection is empty. + /// The removed item. + T DeleteMin(); + + + /// + /// Find the current largest item of this sorted collection. + /// + /// if the collection is empty. + /// The largest item. + T FindMax(); + + + /// + /// Remove the largest item from this sorted collection. + /// + /// if the collection is empty. + /// The removed item. + T DeleteMax(); + + /// + /// The comparer object supplied at creation time for this sorted collection. + /// + /// The comparer + System.Collections.Generic.IComparer Comparer { get; } + + /// + /// Find the strict predecessor of item in the sorted collection, + /// that is, the greatest item in the collection smaller than the item. + /// + /// The item to find the predecessor for. + /// The predecessor, if any; otherwise the default value for T. + /// True if item has a predecessor; otherwise false. + bool TryPredecessor(T item, out T res); + + + /// + /// Find the strict successor of item in the sorted collection, + /// that is, the least item in the collection greater than the supplied value. + /// + /// The item to find the successor for. + /// The successor, if any; otherwise the default value for T. + /// True if item has a successor; otherwise false. + bool TrySuccessor(T item, out T res); + + + /// + /// Find the weak predecessor of item in the sorted collection, + /// that is, the greatest item in the collection smaller than or equal to the item. + /// + /// The item to find the weak predecessor for. + /// The weak predecessor, if any; otherwise the default value for T. + /// True if item has a weak predecessor; otherwise false. + bool TryWeakPredecessor(T item, out T res); + + + /// + /// Find the weak successor of item in the sorted collection, + /// that is, the least item in the collection greater than or equal to the supplied value. + /// + /// The item to find the weak successor for. + /// The weak successor, if any; otherwise the default value for T. + /// True if item has a weak successor; otherwise false. + bool TryWeakSuccessor(T item, out T res); + + + /// + /// Find the strict predecessor in the sorted collection of a particular value, + /// that is, the largest item in the collection less than the supplied value. + /// + /// if no such element exists (the + /// supplied value is less than or equal to the minimum of this collection.) + /// The item to find the predecessor for. + /// The predecessor. + T Predecessor(T item); + + + /// + /// Find the strict successor in the sorted collection of a particular value, + /// that is, the least item in the collection greater than the supplied value. + /// + /// if no such element exists (the + /// supplied value is greater than or equal to the maximum of this collection.) + /// The item to find the successor for. + /// The successor. + T Successor(T item); + + + /// + /// Find the weak predecessor in the sorted collection of a particular value, + /// that is, the largest item in the collection less than or equal to the supplied value. + /// + /// if no such element exists (the + /// supplied value is less than the minimum of this collection.) + /// The item to find the weak predecessor for. + /// The weak predecessor. + T WeakPredecessor(T item); + + + /// + /// Find the weak successor in the sorted collection of a particular value, + /// that is, the least item in the collection greater than or equal to the supplied value. + /// + /// if no such element exists (the + /// supplied value is greater than the maximum of this collection.) + ///The item to find the weak successor for. + /// The weak successor. + T WeakSuccessor(T item); + + + /// + /// Given a "cut" function from the items of the sorted collection to int + /// whose only sign changes when going through items in increasing order + /// can be /// - /// Extrema: report or report and delete an extremal item. This is reminiscent of simplified priority queues. - /// Nearest neighbor: report predecessor or successor in the collection of an item. Cut belongs to this group. - /// Range: report a view of a range of elements or remove all elements in a range. - /// AddSorted: add a collection of items known to be sorted in the same order (should be faster) (to be removed?) + /// from positive to zero + /// from positive to negative + /// from zero to negative /// + /// The "cut" function is supplied as the CompareTo method + /// of an object c implementing + /// IComparable<T>. + /// A typical example is the case where T is comparable and + /// cutFunction is itself of type T. + /// This method performs a search in the sorted collection for the ranges in which the + /// "cut" function is negative, zero respectively positive. If T is comparable + /// and c is of type T, this is a safe way (no exceptions thrown) + /// to find predecessor and successor of c. /// - /// - /// Since this interface extends ISequenced<T>, sorted collections will also have an - /// item equalityComparer (). This equalityComparer will not be used in connection with - /// the inner workings of the sorted collection, but will be used if the sorted collection is used as - /// an item in a collection of unsequenced or sequenced collections, - /// ( and ) - /// - /// Note that code may check if two sorted collections has the same sorting order - /// by checking if the Comparer properties are equal. This is done a few places in this library - /// for optimization purposes. + /// If the supplied cut function does not satisfy the sign-change condition, + /// the result of this call is undefined. + /// + /// + /// + /// The cut function T to int, given + /// by the CompareTo method of an object implementing + /// IComparable<T>. + /// Returns the largest item in the collection, where the + /// cut function is positive (if any). + /// Returns true if the cut function is positive somewhere + /// on this collection. + /// Returns the least item in the collection, where the + /// cut function is negative (if any). + /// Returns true if the cut function is negative somewhere + /// on this collection. + /// True if the cut function is zero somewhere + /// on this collection. + bool Cut(IComparable cutFunction, out T low, out bool lowIsValid, out T high, out bool highIsValid); + + + /// + /// Query this sorted collection for items greater than or equal to a supplied value. + /// The returned collection is not a copy but a view into the collection. + /// The view is fragile in the sense that changes to the underlying collection will + /// invalidate the view so that further operations on the view throws InvalidView exceptions. + /// + /// The lower bound (inclusive). + /// The result directed collection. + IDirectedEnumerable RangeFrom(T bot); + + + /// + /// Query this sorted collection for items between two supplied values. + /// The returned collection is not a copy but a view into the collection. + /// The view is fragile in the sense that changes to the underlying collection will + /// invalidate the view so that further operations on the view throws InvalidView exceptions. + /// + /// The lower bound (inclusive). + /// The upper bound (exclusive). + /// The result directed collection. + IDirectedEnumerable RangeFromTo(T bot, T top); + + + /// + /// Query this sorted collection for items less than a supplied value. + /// The returned collection is not a copy but a view into the collection. + /// The view is fragile in the sense that changes to the underlying collection will + /// invalidate the view so that further operations on the view throws InvalidView exceptions. + /// + /// The upper bound (exclusive). + /// The result directed collection. + IDirectedEnumerable RangeTo(T top); + + + /// + /// Create a directed collection with the same items as this collection. + /// The returned collection is not a copy but a view into the collection. + /// The view is fragile in the sense that changes to the underlying collection will + /// invalidate the view so that further operations on the view throws InvalidView exceptions. + /// + /// The result directed collection. + IDirectedCollectionValue RangeAll(); + + + //TODO: remove now that we assume that we can check the sorting order? + /// + /// Add all the items from another collection with an enumeration order that + /// is increasing in the items. + /// + /// if the enumerated items turns out + /// not to be in increasing order. + /// The collection to add. + void AddSorted(IEnumerable items); + + + /// + /// Remove all items of this collection above or at a supplied threshold. + /// + /// The lower threshold (inclusive). + void RemoveRangeFrom(T low); + + + /// + /// Remove all items of this collection between two supplied thresholds. + /// + /// The lower threshold (inclusive). + /// The upper threshold (exclusive). + void RemoveRangeFromTo(T low, T hi); + + + /// + /// Remove all items of this collection below a supplied threshold. /// - public interface ISorted : ISequenced - { - /// - /// Find the current least item of this sorted collection. - /// - /// if the collection is empty. - /// The least item. - T FindMin(); - - - /// - /// Remove the least item from this sorted collection. - /// - /// if the collection is empty. - /// The removed item. - T DeleteMin(); - - - /// - /// Find the current largest item of this sorted collection. - /// - /// if the collection is empty. - /// The largest item. - T FindMax(); - - - /// - /// Remove the largest item from this sorted collection. - /// - /// if the collection is empty. - /// The removed item. - T DeleteMax(); - - /// - /// The comparer object supplied at creation time for this sorted collection. - /// - /// The comparer - System.Collections.Generic.IComparer Comparer { get; } - - /// - /// Find the strict predecessor of item in the sorted collection, - /// that is, the greatest item in the collection smaller than the item. - /// - /// The item to find the predecessor for. - /// The predecessor, if any; otherwise the default value for T. - /// True if item has a predecessor; otherwise false. - bool TryPredecessor(T item, out T res); - - - /// - /// Find the strict successor of item in the sorted collection, - /// that is, the least item in the collection greater than the supplied value. - /// - /// The item to find the successor for. - /// The successor, if any; otherwise the default value for T. - /// True if item has a successor; otherwise false. - bool TrySuccessor(T item, out T res); - - - /// - /// Find the weak predecessor of item in the sorted collection, - /// that is, the greatest item in the collection smaller than or equal to the item. - /// - /// The item to find the weak predecessor for. - /// The weak predecessor, if any; otherwise the default value for T. - /// True if item has a weak predecessor; otherwise false. - bool TryWeakPredecessor(T item, out T res); - - - /// - /// Find the weak successor of item in the sorted collection, - /// that is, the least item in the collection greater than or equal to the supplied value. - /// - /// The item to find the weak successor for. - /// The weak successor, if any; otherwise the default value for T. - /// True if item has a weak successor; otherwise false. - bool TryWeakSuccessor(T item, out T res); - - - /// - /// Find the strict predecessor in the sorted collection of a particular value, - /// that is, the largest item in the collection less than the supplied value. - /// - /// if no such element exists (the - /// supplied value is less than or equal to the minimum of this collection.) - /// The item to find the predecessor for. - /// The predecessor. - T Predecessor(T item); - - - /// - /// Find the strict successor in the sorted collection of a particular value, - /// that is, the least item in the collection greater than the supplied value. - /// - /// if no such element exists (the - /// supplied value is greater than or equal to the maximum of this collection.) - /// The item to find the successor for. - /// The successor. - T Successor(T item); - - - /// - /// Find the weak predecessor in the sorted collection of a particular value, - /// that is, the largest item in the collection less than or equal to the supplied value. - /// - /// if no such element exists (the - /// supplied value is less than the minimum of this collection.) - /// The item to find the weak predecessor for. - /// The weak predecessor. - T WeakPredecessor(T item); - - - /// - /// Find the weak successor in the sorted collection of a particular value, - /// that is, the least item in the collection greater than or equal to the supplied value. - /// - /// if no such element exists (the - /// supplied value is greater than the maximum of this collection.) - ///The item to find the weak successor for. - /// The weak successor. - T WeakSuccessor(T item); - - - /// - /// Given a "cut" function from the items of the sorted collection to int - /// whose only sign changes when going through items in increasing order - /// can be - /// - /// from positive to zero - /// from positive to negative - /// from zero to negative - /// - /// The "cut" function is supplied as the CompareTo method - /// of an object c implementing - /// IComparable<T>. - /// A typical example is the case where T is comparable and - /// cutFunction is itself of type T. - /// This method performs a search in the sorted collection for the ranges in which the - /// "cut" function is negative, zero respectively positive. If T is comparable - /// and c is of type T, this is a safe way (no exceptions thrown) - /// to find predecessor and successor of c. - /// - /// If the supplied cut function does not satisfy the sign-change condition, - /// the result of this call is undefined. - /// - /// - /// - /// The cut function T to int, given - /// by the CompareTo method of an object implementing - /// IComparable<T>. - /// Returns the largest item in the collection, where the - /// cut function is positive (if any). - /// Returns true if the cut function is positive somewhere - /// on this collection. - /// Returns the least item in the collection, where the - /// cut function is negative (if any). - /// Returns true if the cut function is negative somewhere - /// on this collection. - /// True if the cut function is zero somewhere - /// on this collection. - bool Cut(IComparable cutFunction, out T low, out bool lowIsValid, out T high, out bool highIsValid); - - - /// - /// Query this sorted collection for items greater than or equal to a supplied value. - /// The returned collection is not a copy but a view into the collection. - /// The view is fragile in the sense that changes to the underlying collection will - /// invalidate the view so that further operations on the view throws InvalidView exceptions. - /// - /// The lower bound (inclusive). - /// The result directed collection. - IDirectedEnumerable RangeFrom(T bot); - - - /// - /// Query this sorted collection for items between two supplied values. - /// The returned collection is not a copy but a view into the collection. - /// The view is fragile in the sense that changes to the underlying collection will - /// invalidate the view so that further operations on the view throws InvalidView exceptions. - /// - /// The lower bound (inclusive). - /// The upper bound (exclusive). - /// The result directed collection. - IDirectedEnumerable RangeFromTo(T bot, T top); - - - /// - /// Query this sorted collection for items less than a supplied value. - /// The returned collection is not a copy but a view into the collection. - /// The view is fragile in the sense that changes to the underlying collection will - /// invalidate the view so that further operations on the view throws InvalidView exceptions. - /// - /// The upper bound (exclusive). - /// The result directed collection. - IDirectedEnumerable RangeTo(T top); - - - /// - /// Create a directed collection with the same items as this collection. - /// The returned collection is not a copy but a view into the collection. - /// The view is fragile in the sense that changes to the underlying collection will - /// invalidate the view so that further operations on the view throws InvalidView exceptions. - /// - /// The result directed collection. - IDirectedCollectionValue RangeAll(); - - - //TODO: remove now that we assume that we can check the sorting order? - /// - /// Add all the items from another collection with an enumeration order that - /// is increasing in the items. - /// - /// if the enumerated items turns out - /// not to be in increasing order. - /// The collection to add. - void AddSorted(IEnumerable items); - - - /// - /// Remove all items of this collection above or at a supplied threshold. - /// - /// The lower threshold (inclusive). - void RemoveRangeFrom(T low); - - - /// - /// Remove all items of this collection between two supplied thresholds. - /// - /// The lower threshold (inclusive). - /// The upper threshold (exclusive). - void RemoveRangeFromTo(T low, T hi); - - - /// - /// Remove all items of this collection below a supplied threshold. - /// - /// The upper threshold (exclusive). - void RemoveRangeTo(T hi); - } + /// The upper threshold (exclusive). + void RemoveRangeTo(T hi); } \ No newline at end of file diff --git a/C5/Interfaces/ISortedDictionary.cs b/C5/Interfaces/ISortedDictionary.cs index 9342becf..9b71e822 100644 --- a/C5/Interfaces/ISortedDictionary.cs +++ b/C5/Interfaces/ISortedDictionary.cs @@ -1,230 +1,232 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; using SCG = System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// A dictionary with sorted keys. +/// +public interface ISortedDictionary : IDictionary { /// - /// A dictionary with sorted keys. - /// - public interface ISortedDictionary : IDictionary - { - /// - /// - /// - /// - new ISorted Keys { get; } - - /// - /// Find the current least item of this sorted collection. - /// - /// if the collection is empty. - /// The least item. - SCG.KeyValuePair FindMin(); - - - /// - /// Remove the least item from this sorted collection. - /// - /// if the collection is empty. - /// The removed item. - SCG.KeyValuePair DeleteMin(); - - - /// - /// Find the current largest item of this sorted collection. - /// - /// if the collection is empty. - /// The largest item. - SCG.KeyValuePair FindMax(); - - - /// - /// Remove the largest item from this sorted collection. - /// - /// if the collection is empty. - /// The removed item. - SCG.KeyValuePair DeleteMax(); - - /// - /// The key comparer used by this dictionary. - /// - /// - SCG.IComparer Comparer { get; } - - /// - /// Find the entry in the dictionary whose key is the - /// predecessor of the specified key. - /// - /// The key - /// The predecessor, if any - /// True if key has a predecessor - bool TryPredecessor(K key, out SCG.KeyValuePair res); - - /// - /// Find the entry in the dictionary whose key is the - /// successor of the specified key. - /// - /// The key - /// The successor, if any - /// True if the key has a successor - bool TrySuccessor(K key, out SCG.KeyValuePair res); - - /// - /// Find the entry in the dictionary whose key is the - /// weak predecessor of the specified key. - /// - /// The key - /// The predecessor, if any - /// True if key has a weak predecessor - bool TryWeakPredecessor(K key, out SCG.KeyValuePair res); - - /// - /// Find the entry in the dictionary whose key is the - /// weak successor of the specified key. - /// - /// The key - /// The weak successor, if any - /// True if the key has a weak successor - bool TryWeakSuccessor(K key, out SCG.KeyValuePair res); - - /// - /// Find the entry with the largest key less than a given key. - /// - /// if there is no such entry. - /// The key to compare to - /// The entry - SCG.KeyValuePair Predecessor(K key); - - /// - /// Find the entry with the least key greater than a given key. - /// - /// if there is no such entry. - /// The key to compare to - /// The entry - SCG.KeyValuePair Successor(K key); - - /// - /// Find the entry with the largest key less than or equal to a given key. - /// - /// if there is no such entry. - /// The key to compare to - /// The entry - SCG.KeyValuePair WeakPredecessor(K key); - - /// - /// Find the entry with the least key greater than or equal to a given key. - /// - /// if there is no such entry. - /// The key to compare to - /// The entry - SCG.KeyValuePair WeakSuccessor(K key); - - /// - /// Given a "cut" function from the items of the sorted collection to int - /// whose only sign changes when going through items in increasing order - /// can be - /// - /// from positive to zero - /// from positive to negative - /// from zero to negative - /// - /// The "cut" function is supplied as the CompareTo method - /// of an object c implementing - /// IComparable<K>. - /// A typical example is the case where K is comparable and - /// c is itself of type K. - /// This method performs a search in the sorted collection for the ranges in which the - /// "cut" function is negative, zero respectively positive. If K is comparable - /// and c is of type K, this is a safe way (no exceptions thrown) - /// to find predecessor and successor of c. - /// - /// If the supplied cut function does not satisfy the sign-change condition, - /// the result of this call is undefined. - /// - /// - /// - /// The cut function K to int, given - /// by the CompareTo method of an object implementing - /// IComparable<K>. - /// Returns the largest item in the collection, where the - /// cut function is positive (if any). - /// Returns true if the cut function is positive somewhere - /// on this collection. - /// Returns the least item in the collection, where the - /// cut function is negative (if any). - /// Returns true if the cut function is negative somewhere - /// on this collection. - /// True if the cut function is zero somewhere - /// on this collection. - bool Cut(IComparable cutFunction, out SCG.KeyValuePair lowEntry, out bool lowIsValid, out System.Collections.Generic.KeyValuePair highEntry, out bool highIsValid); - - /// - /// Query this sorted collection for items greater than or equal to a supplied value. - /// The returned collection is not a copy but a view into the collection. - /// The view is fragile in the sense that changes to the underlying collection will - /// invalidate the view so that further operations on the view throws InvalidView exceptions. - /// - /// The lower bound (inclusive). - /// The result directed collection. - IDirectedEnumerable> RangeFrom(K bot); - - /// - /// Query this sorted collection for items between two supplied values. - /// The returned collection is not a copy but a view into the collection. - /// The view is fragile in the sense that changes to the underlying collection will - /// invalidate the view so that further operations on the view throws InvalidView exceptions. - /// - /// The lower bound (inclusive). - /// The upper bound (exclusive). - /// The result directed collection. - IDirectedEnumerable> RangeFromTo(K lowerBound, K upperBound); - - /// - /// Query this sorted collection for items less than a supplied value. - /// The returned collection is not a copy but a view into the collection. - /// The view is fragile in the sense that changes to the underlying collection will - /// invalidate the view so that further operations on the view throws InvalidView exceptions. - /// - /// The upper bound (exclusive). - /// The result directed collection. - IDirectedEnumerable> RangeTo(K top); - - /// - /// Create a directed collection with the same items as this collection. - /// The returned collection is not a copy but a view into the collection. - /// The view is fragile in the sense that changes to the underlying collection will - /// invalidate the view so that further operations on the view throws InvalidView exceptions. - /// - /// The result directed collection. - IDirectedCollectionValue> RangeAll(); - - //TODO: remove now that we assume that we can check the sorting order? - /// - /// Add all the items from another collection with an enumeration order that - /// is increasing in the items. - /// - /// if the enumerated items turns out - /// not to be in increasing order. - /// The collection to add. - void AddSorted(SCG.IEnumerable> items); - - /// - /// Remove all items of this collection above or at a supplied threshold. - /// - /// The lower threshold (inclusive). - void RemoveRangeFrom(K low); - - /// - /// Remove all items of this collection between two supplied thresholds. - /// - /// The lower threshold (inclusive). - /// The upper threshold (exclusive). - void RemoveRangeFromTo(K low, K hi); - - /// - /// Remove all items of this collection below a supplied threshold. - /// - /// The upper threshold (exclusive). - void RemoveRangeTo(K hi); - } + /// + /// + /// + new ISorted Keys { get; } + + /// + /// Find the current least item of this sorted collection. + /// + /// if the collection is empty. + /// The least item. + SCG.KeyValuePair FindMin(); + + + /// + /// Remove the least item from this sorted collection. + /// + /// if the collection is empty. + /// The removed item. + SCG.KeyValuePair DeleteMin(); + + + /// + /// Find the current largest item of this sorted collection. + /// + /// if the collection is empty. + /// The largest item. + SCG.KeyValuePair FindMax(); + + + /// + /// Remove the largest item from this sorted collection. + /// + /// if the collection is empty. + /// The removed item. + SCG.KeyValuePair DeleteMax(); + + /// + /// The key comparer used by this dictionary. + /// + /// + SCG.IComparer Comparer { get; } + + /// + /// Find the entry in the dictionary whose key is the + /// predecessor of the specified key. + /// + /// The key + /// The predecessor, if any + /// True if key has a predecessor + bool TryPredecessor(K key, out SCG.KeyValuePair res); + + /// + /// Find the entry in the dictionary whose key is the + /// successor of the specified key. + /// + /// The key + /// The successor, if any + /// True if the key has a successor + bool TrySuccessor(K key, out SCG.KeyValuePair res); + + /// + /// Find the entry in the dictionary whose key is the + /// weak predecessor of the specified key. + /// + /// The key + /// The predecessor, if any + /// True if key has a weak predecessor + bool TryWeakPredecessor(K key, out SCG.KeyValuePair res); + + /// + /// Find the entry in the dictionary whose key is the + /// weak successor of the specified key. + /// + /// The key + /// The weak successor, if any + /// True if the key has a weak successor + bool TryWeakSuccessor(K key, out SCG.KeyValuePair res); + + /// + /// Find the entry with the largest key less than a given key. + /// + /// if there is no such entry. + /// The key to compare to + /// The entry + SCG.KeyValuePair Predecessor(K key); + + /// + /// Find the entry with the least key greater than a given key. + /// + /// if there is no such entry. + /// The key to compare to + /// The entry + SCG.KeyValuePair Successor(K key); + + /// + /// Find the entry with the largest key less than or equal to a given key. + /// + /// if there is no such entry. + /// The key to compare to + /// The entry + SCG.KeyValuePair WeakPredecessor(K key); + + /// + /// Find the entry with the least key greater than or equal to a given key. + /// + /// if there is no such entry. + /// The key to compare to + /// The entry + SCG.KeyValuePair WeakSuccessor(K key); + + /// + /// Given a "cut" function from the items of the sorted collection to int + /// whose only sign changes when going through items in increasing order + /// can be + /// + /// from positive to zero + /// from positive to negative + /// from zero to negative + /// + /// The "cut" function is supplied as the CompareTo method + /// of an object c implementing + /// IComparable<K>. + /// A typical example is the case where K is comparable and + /// c is itself of type K. + /// This method performs a search in the sorted collection for the ranges in which the + /// "cut" function is negative, zero respectively positive. If K is comparable + /// and c is of type K, this is a safe way (no exceptions thrown) + /// to find predecessor and successor of c. + /// + /// If the supplied cut function does not satisfy the sign-change condition, + /// the result of this call is undefined. + /// + /// + /// + /// The cut function K to int, given + /// by the CompareTo method of an object implementing + /// IComparable<K>. + /// Returns the largest item in the collection, where the + /// cut function is positive (if any). + /// Returns true if the cut function is positive somewhere + /// on this collection. + /// Returns the least item in the collection, where the + /// cut function is negative (if any). + /// Returns true if the cut function is negative somewhere + /// on this collection. + /// True if the cut function is zero somewhere + /// on this collection. + bool Cut(IComparable cutFunction, out SCG.KeyValuePair lowEntry, out bool lowIsValid, out System.Collections.Generic.KeyValuePair highEntry, out bool highIsValid); + + /// + /// Query this sorted collection for items greater than or equal to a supplied value. + /// The returned collection is not a copy but a view into the collection. + /// The view is fragile in the sense that changes to the underlying collection will + /// invalidate the view so that further operations on the view throws InvalidView exceptions. + /// + /// The lower bound (inclusive). + /// The result directed collection. + IDirectedEnumerable> RangeFrom(K bot); + + /// + /// Query this sorted collection for items between two supplied values. + /// The returned collection is not a copy but a view into the collection. + /// The view is fragile in the sense that changes to the underlying collection will + /// invalidate the view so that further operations on the view throws InvalidView exceptions. + /// + /// The lower bound (inclusive). + /// The upper bound (exclusive). + /// The result directed collection. + IDirectedEnumerable> RangeFromTo(K lowerBound, K upperBound); + + /// + /// Query this sorted collection for items less than a supplied value. + /// The returned collection is not a copy but a view into the collection. + /// The view is fragile in the sense that changes to the underlying collection will + /// invalidate the view so that further operations on the view throws InvalidView exceptions. + /// + /// The upper bound (exclusive). + /// The result directed collection. + IDirectedEnumerable> RangeTo(K top); + + /// + /// Create a directed collection with the same items as this collection. + /// The returned collection is not a copy but a view into the collection. + /// The view is fragile in the sense that changes to the underlying collection will + /// invalidate the view so that further operations on the view throws InvalidView exceptions. + /// + /// The result directed collection. + IDirectedCollectionValue> RangeAll(); + + //TODO: remove now that we assume that we can check the sorting order? + /// + /// Add all the items from another collection with an enumeration order that + /// is increasing in the items. + /// + /// if the enumerated items turns out + /// not to be in increasing order. + /// The collection to add. + void AddSorted(SCG.IEnumerable> items); + + /// + /// Remove all items of this collection above or at a supplied threshold. + /// + /// The lower threshold (inclusive). + void RemoveRangeFrom(K low); + + /// + /// Remove all items of this collection between two supplied thresholds. + /// + /// The lower threshold (inclusive). + /// The upper threshold (exclusive). + void RemoveRangeFromTo(K low, K hi); + + /// + /// Remove all items of this collection below a supplied threshold. + /// + /// The upper threshold (exclusive). + void RemoveRangeTo(K hi); } \ No newline at end of file diff --git a/C5/Interfaces/IStack.cs b/C5/Interfaces/IStack.cs index 5aa106e2..1ee2430a 100644 --- a/C5/Interfaces/IStack.cs +++ b/C5/Interfaces/IStack.cs @@ -1,31 +1,33 @@ -namespace C5 +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +namespace C5; + +/// +/// The interface describing the operations of a LIFO stack data structure. +/// +/// The item type +public interface IStack : IDirectedCollectionValue { /// - /// The interface describing the operations of a LIFO stack data structure. + /// /// - /// The item type - public interface IStack : IDirectedCollectionValue - { - /// - /// - /// - /// - bool AllowsDuplicates { get; } - /// - /// Get the index'th element of the stack. The bottom of the stack has index 0. - /// - /// - /// - T this[int index] { get; } - /// - /// Push an item to the top of the stack. - /// - /// The item - void Push(T item); - /// - /// Pop the item at the top of the stack from the stack. - /// - /// The popped item. - T Pop(); - } + /// + bool AllowsDuplicates { get; } + /// + /// Get the index'th element of the stack. The bottom of the stack has index 0. + /// + /// + /// + T this[int index] { get; } + /// + /// Push an item to the top of the stack. + /// + /// The item + void Push(T item); + /// + /// Pop the item at the top of the stack from the stack. + /// + /// The popped item. + T Pop(); } \ No newline at end of file diff --git a/C5/LinkedLists/HashedLinkedList.cs b/C5/LinkedLists/HashedLinkedList.cs index 3f845d59..0a96c5ea 100644 --- a/C5/LinkedLists/HashedLinkedList.cs +++ b/C5/LinkedLists/HashedLinkedList.cs @@ -4,3459 +4,3479 @@ using System; using SCG = System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// A list collection class based on a doubly linked list data structure. +/// +public class HashedLinkedList : SequencedBase, IList, SCG.IList { + #region Fields /// - /// A list collection class based on a doubly linked list data structure. + /// IExtensible.Add(T) always does AddLast(T), fIFO determines + /// if T Remove() does RemoveFirst() or RemoveLast() /// - public class HashedLinkedList : SequencedBase, IList, SCG.IList - { - #region Fields - /// - /// IExtensible.Add(T) always does AddLast(T), fIFO determines - /// if T Remove() does RemoveFirst() or RemoveLast() - /// - private bool fIFO = true; + private bool fIFO = true; - #region Events + #region Events - /// - /// - /// - /// - public override EventType ListenableEvents => underlying == null ? EventType.All : EventType.None; + /// + /// + /// + /// + public override EventType ListenableEvents => underlying == null ? EventType.All : EventType.None; - #endregion + #endregion - //Invariant: startsentinel != null && endsentinel != null - //If size==0: startsentinel.next == endsentinel && endsentinel.prev == startsentinel - //Else: startsentinel.next == First && endsentinel.prev == Last) - /// - /// Node to the left of first node - /// - private Node? startsentinel; + //Invariant: startsentinel != null && endsentinel != null + //If size==0: startsentinel.next == endsentinel && endsentinel.prev == startsentinel + //Else: startsentinel.next == First && endsentinel.prev == Last) + /// + /// Node to the left of first node + /// + private Node? startsentinel; - /// - /// Node to the right of last node - /// - private Node? endsentinel; + /// + /// Node to the right of last node + /// + private Node? endsentinel; - /// - /// Offset of this view in underlying list - /// - private int? offset; + /// + /// Offset of this view in underlying list + /// + private int? offset; - /// - /// underlying list of this view (or null for the underlying list) - /// - private HashedLinkedList? underlying; + /// + /// underlying list of this view (or null for the underlying list) + /// + private HashedLinkedList? underlying; - //Note: all views will have the same views list since all view objects are created by MemberwiseClone() - private WeakViewList>? views; - private WeakViewList>.Node? myWeakReference; + //Note: all views will have the same views list since all view objects are created by MemberwiseClone() + private WeakViewList>? views; + private WeakViewList>.Node? myWeakReference; - /// - /// Has this list or view not been invalidated by some operation (by someone calling Dispose()) - /// - private bool isValid = true; - private readonly HashDictionary dict; + /// + /// Has this list or view not been invalidated by some operation (by someone calling Dispose()) + /// + private bool isValid = true; + private readonly HashDictionary dict; - /// - /// Number of taggroups - /// - private int taggroups; + /// + /// Number of taggroups + /// + private int taggroups; - /// - /// - /// - /// - private int Taggroups + /// + /// + /// + /// + private int Taggroups + { + get => underlying == null ? taggroups : underlying.taggroups; + set { - get => underlying == null ? taggroups : underlying.taggroups; - set + if (underlying == null) { - if (underlying == null) - { - taggroups = value; - } - else - { - underlying.taggroups = value; - } + taggroups = value; + } + else + { + underlying.taggroups = value; } } + } - #endregion + #endregion - #region Util + #region Util - // bool equals(T i1, T i2) { return itemequalityComparer.Equals(i1, i2); } + // bool equals(T i1, T i2) { return itemequalityComparer.Equals(i1, i2); } - #region Check utilities - /// - /// Check if it is valid to perform updates and increment stamp of - /// underlying if this is a view. - /// This method should be called in every public modifying - /// methods before any modifications are performed. - /// - /// - /// if check fails. - protected override void UpdateCheck() + #region Check utilities + /// + /// Check if it is valid to perform updates and increment stamp of + /// underlying if this is a view. + /// This method should be called in every public modifying + /// methods before any modifications are performed. + /// + /// + /// if check fails. + protected override void UpdateCheck() + { + Validitycheck(); + base.UpdateCheck(); + if (underlying != null) { - Validitycheck(); - base.UpdateCheck(); - if (underlying != null) - { - underlying.stamp++; - } + underlying.stamp++; } + } - /// - /// Check if we are a view that the underlying list has only been updated through us. - ///
- /// This method should be called from enumerators etc to guard against - /// modification of the base collection. - ///
- /// if check fails. - private void Validitycheck() + /// + /// Check if we are a view that the underlying list has only been updated through us. + ///
+ /// This method should be called from enumerators etc to guard against + /// modification of the base collection. + ///
+ /// if check fails. + private void Validitycheck() + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException(); - } + throw new ViewDisposedException(); } + } - /// - /// Check that the list has not been updated since a particular time. - /// - /// The stamp indicating the time. - /// if check fails. - protected override void ModifyCheck(int stamp) + /// + /// Check that the list has not been updated since a particular time. + /// + /// The stamp indicating the time. + /// if check fails. + protected override void ModifyCheck(int stamp) + { + Validitycheck(); + if ((underlying != null ? underlying.stamp : this.stamp) != stamp) { - Validitycheck(); - if ((underlying != null ? underlying.stamp : this.stamp) != stamp) - { - throw new CollectionModifiedException(); - } + throw new CollectionModifiedException(); } - #endregion + } + #endregion - #region Searching - private bool Contains(T item, out Node node) + #region Searching + private bool Contains(T item, out Node node) + { + if (dict.Find(ref item, out node)) { - if (dict.Find(ref item, out node)) - { - return InsideView(node); - } - - return false; + return InsideView(node); } - /// - /// Search forwards from a node for a node with a particular item. - /// - /// The item to look for - /// On input, the node to start at. If item was found, the node found on output. - /// If node was found, the value will be the number of links followed higher than - /// the value on input. If item was not found, the value on output is undefined. - /// True if node was found. - private bool Find(T item, ref Node node, ref int index) - { - while (node != endsentinel) - { - //if (item.Equals(node.item)) - if (itemequalityComparer.Equals(item, node!.item)) - { - return true; - } - - index++; - node = node.next!; - } - - return false; - } + return false; + } - /* - bool dnif(T item, ref Node node, ref int index) + /// + /// Search forwards from a node for a node with a particular item. + /// + /// The item to look for + /// On input, the node to start at. If item was found, the node found on output. + /// If node was found, the value will be the number of links followed higher than + /// the value on input. If item was not found, the value on output is undefined. + /// True if node was found. + private bool Find(T item, ref Node node, ref int index) + { + while (node != endsentinel) { - while (node != startsentinel) + //if (item.Equals(node.item)) + if (itemEqualityComparer.Equals(item, node!.item)) { - //if (item.Equals(node.item)) - if (itemequalityComparer.Equals(item, node.item)) - return true; - - index--; - node = node.prev!; + return true; } - return false; + index++; + node = node.next!; } - */ - private bool InsideView(Node node) + return false; + } + + /* + bool dnif(T item, ref Node node, ref int index) + { + while (node != startsentinel) { - if (underlying == null) - { + //if (item.Equals(node.item)) + if (itemequalityComparer.Equals(item, node.item)) return true; - } - return (startsentinel!.Precedes(node) && node.Precedes(endsentinel!)); + index--; + node = node.prev!; } - #endregion + return false; + } + */ - #region Indexing - /// - /// Return the node at position pos - /// - /// - /// - private Node Get(int pos) + private bool InsideView(Node node) + { + if (underlying == null) { - if (pos < 0 || pos >= size) - { - throw new IndexOutOfRangeException(); - } - else if (pos < size / 2) - { // Closer to front - Node? node = startsentinel; - - for (int i = 0; i <= pos; i++) - { - node = node!.next; - } + return true; + } - return node!; - } - else - { // Closer to end - Node? node = endsentinel; + return (startsentinel!.Precedes(node) && node.Precedes(endsentinel!)); + } - for (int i = size; i > pos; i--) - { - node = node!.prev; - } + #endregion - return node!; - } + #region Indexing + /// + /// Return the node at position pos + /// + /// + /// + private Node Get(int pos) + { + if (pos < 0 || pos >= size) + { + throw new IndexOutOfRangeException(); } + else if (pos < size / 2) + { // Closer to front + Node? node = startsentinel; - /// - /// Find the distance from pos to the set given by positions. Return the - /// signed distance as return value and as an out parameter, the - /// array index of the nearest position. This is used for up to length 5 of - /// positions, and we do not assume it is sorted. - /// - /// - /// - /// - /// - private int Dist(int pos, out int nearest, int[] positions) - { - nearest = -1; - int bestdist = int.MaxValue; - int signeddist = bestdist; - for (int i = 0; i < positions.Length; i++) + for (int i = 0; i <= pos; i++) { - int thisdist = positions[i] - pos; - if (thisdist >= 0 && thisdist < bestdist) { nearest = i; bestdist = thisdist; signeddist = thisdist; } - if (thisdist < 0 && -thisdist < bestdist) { nearest = i; bestdist = -thisdist; signeddist = thisdist; } + node = node!.next; } - return signeddist; + + return node!; } + else + { // Closer to end + Node? node = endsentinel; - /// - /// Find the node at position pos, given known positions of several nodes. - /// - /// - /// - /// - /// - private Node Get(int pos, int[] positions, Node[] nodes) - { - int delta = Dist(pos, out int nearest, positions); - Node node = nodes[nearest]; - if (delta > 0) - { - for (int i = 0; i < delta; i++) - { - node = node.prev!; - } - } - else + for (int i = size; i > pos; i--) { - for (int i = 0; i > delta; i--) - { - node = node.next!; - } + node = node!.prev; } return node!; } + } - /// - /// Get nodes at positions p1 and p2, given nodes at several positions. - /// - /// - /// - /// - /// - /// - /// - private void GetPair(int p1, int p2, out Node n1, out Node n2, int[] positions, Node[] nodes) + /// + /// Find the distance from pos to the set given by positions. Return the + /// signed distance as return value and as an out parameter, the + /// array index of the nearest position. This is used for up to length 5 of + /// positions, and we do not assume it is sorted. + /// + /// + /// + /// + /// + private int Dist(int pos, out int nearest, int[] positions) + { + nearest = -1; + int bestdist = int.MaxValue; + int signeddist = bestdist; + for (int i = 0; i < positions.Length; i++) { - int delta1 = Dist(p1, out int nearest1, positions), d1 = delta1 < 0 ? -delta1 : delta1; - int delta2 = Dist(p2, out int nearest2, positions), d2 = delta2 < 0 ? -delta2 : delta2; + int thisdist = positions[i] - pos; + if (thisdist >= 0 && thisdist < bestdist) { nearest = i; bestdist = thisdist; signeddist = thisdist; } + if (thisdist < 0 && -thisdist < bestdist) { nearest = i; bestdist = -thisdist; signeddist = thisdist; } + } + return signeddist; + } - if (d1 < d2) + /// + /// Find the node at position pos, given known positions of several nodes. + /// + /// + /// + /// + /// + private Node Get(int pos, int[] positions, Node[] nodes) + { + int delta = Dist(pos, out int nearest, positions); + Node node = nodes[nearest]; + if (delta > 0) + { + for (int i = 0; i < delta; i++) { - n1 = Get(p1, positions, nodes); - n2 = Get(p2, new int[] { positions[nearest2], p1 }, new Node[] { nodes[nearest2], n1 }); + node = node.prev!; } - else + } + else + { + for (int i = 0; i > delta; i--) { - n2 = Get(p2, positions, nodes); - n1 = Get(p1, new int[] { positions[nearest1], p2 }, new Node[] { nodes[nearest1], n2 }); + node = node.next!; } } - #endregion - #region Insertion + return node!; + } + + /// + /// Get nodes at positions p1 and p2, given nodes at several positions. + /// + /// + /// + /// + /// + /// + /// + private void GetPair(int p1, int p2, out Node n1, out Node n2, int[] positions, Node[] nodes) + { + int delta1 = Dist(p1, out int nearest1, positions), d1 = delta1 < 0 ? -delta1 : delta1; + int delta2 = Dist(p2, out int nearest2, positions), d2 = delta2 < 0 ? -delta2 : delta2; - private void Insert(Node succ, T item) + if (d1 < d2) { - Node newnode = new Node(item); - if (dict.FindOrAdd(item, ref newnode)) - { - throw new DuplicateNotAllowedException("Item already in indexed list"); - } - - InsertNode(true, succ, newnode); + n1 = Get(p1, positions, nodes); + n2 = Get(p2, [positions[nearest2], p1], [nodes[nearest2], n1]); + } + else + { + n2 = Get(p2, positions, nodes); + n1 = Get(p1, [positions[nearest1], p2], [nodes[nearest1], n2]); } + } + #endregion - /// - /// Insert a Node before another one. Unchecked version. - /// - /// update overlapping view in this call - /// The successor to be - /// Node to insert - private void InsertNode(bool updateViews, Node succ, Node newnode) - { - newnode.next = succ; - Node pred = newnode.prev = succ.prev!; - succ.prev!.next = newnode; - succ.prev = newnode; - size++; - if (underlying != null) - { - underlying.size++; - } + #region Insertion - SetTag(newnode); - if (updateViews) - { - FixViewsAfterInsert(succ, pred!, 1); - } + private void Insert(Node succ, T item) + { + Node newnode = new(item); + if (dict.FindOrAdd(item, ref newnode)) + { + throw new DuplicateNotAllowedException("Item already in indexed list"); } - #endregion + InsertNode(true, succ, newnode); + } + + /// + /// Insert a Node before another one. Unchecked version. + /// + /// update overlapping view in this call + /// The successor to be + /// Node to insert + private void InsertNode(bool updateViews, Node succ, Node newnode) + { + newnode.next = succ; + Node pred = newnode.prev = succ.prev!; + succ.prev!.next = newnode; + succ.prev = newnode; + size++; + if (underlying != null) + { + underlying.size++; + } - #region Removal - private T Remove(Node node) + SetTag(newnode); + if (updateViews) { - FixViewsBeforeSingleRemove(node); //, Offset + index); - node.prev!.next = node.next; - node.next!.prev = node.prev; - size--; - if (underlying != null) - { - underlying.size--; - } + FixViewsAfterInsert(succ, pred!, 1); + } + } - RemoveFromTagGroup(node); + #endregion - return node.item; + #region Removal + private T Remove(Node node) + { + FixViewsBeforeSingleRemove(node); //, Offset + index); + node.prev!.next = node.next; + node.next!.prev = node.prev; + size--; + if (underlying != null) + { + underlying.size--; } - private bool DictRemove(T item, out Node node) + RemoveFromTagGroup(node); + + return node.item; + } + + private bool DictRemove(T item, out Node node) + { + if (underlying == null) { - if (underlying == null) + if (!dict.Remove(item, out node)) { - if (!dict.Remove(item, out node)) - { - return false; - } + return false; } - else + } + else + { + //We cannot avoid calling dict twice - have to intersperse the listorder test! + if (!Contains(item, out node)) { - //We cannot avoid calling dict twice - have to intersperse the listorder test! - if (!Contains(item, out node)) - { - return false; - } - - dict.Remove(item); + return false; } - return true; + + dict.Remove(item); } - #endregion + return true; + } + #endregion - #region fixView utilities - /// - /// - /// - /// The successor of the added nodes - /// The predecessor of the inserted nodes - /// The actual number of inserted nodes - private void FixViewsAfterInsert(Node succ, Node pred, int added) + #region fixView utilities + /// + /// + /// + /// The successor of the added nodes + /// The predecessor of the inserted nodes + /// The actual number of inserted nodes + private void FixViewsAfterInsert(Node succ, Node pred, int added) + { + if (views != null) { - if (views != null) + foreach (HashedLinkedList view in views) { - foreach (HashedLinkedList view in views) + if (view != this) { - if (view != this) + if (pred.Precedes(view.startsentinel!) || (view.startsentinel == pred && view.size > 0)) { - if (pred.Precedes(view.startsentinel!) || (view.startsentinel == pred && view.size > 0)) - { - view.offset += added; - } + view.offset += added; + } - if (view.startsentinel!.Precedes(pred) && succ.Precedes(view.endsentinel!)) - { - view.size += added; - } + if (view.startsentinel!.Precedes(pred) && succ.Precedes(view.endsentinel!)) + { + view.size += added; + } - if (view.startsentinel == pred && view.size > 0) - { - view.startsentinel = succ.prev; - } + if (view.startsentinel == pred && view.size > 0) + { + view.startsentinel = succ.prev; + } - if (view.endsentinel == succ) - { - view.endsentinel = pred.next; - } + if (view.endsentinel == succ) + { + view.endsentinel = pred.next; } } } } + } - private void FixViewsBeforeSingleRemove(Node node) + private void FixViewsBeforeSingleRemove(Node node) + { + if (views != null) { - if (views != null) + foreach (HashedLinkedList view in views) { - foreach (HashedLinkedList view in views) + if (view != this) { - if (view != this) + if (view.startsentinel!.Precedes(node) && node.Precedes(view.endsentinel!)) { - if (view.startsentinel!.Precedes(node) && node.Precedes(view.endsentinel!)) - { - view.size--; - } + view.size--; + } - if (!view.startsentinel.Precedes(node)) - { - view.offset--; - } + if (!view.startsentinel.Precedes(node)) + { + view.offset--; + } - if (view.startsentinel == node) - { - view.startsentinel = node.prev; - } + if (view.startsentinel == node) + { + view.startsentinel = node.prev; + } - if (view.endsentinel == node) - { - view.endsentinel = node.next; - } + if (view.endsentinel == node) + { + view.endsentinel = node.next; } } } } + } - /// - /// - /// - /// - /// The position of View(otherOffset, otherSize) wrt. this view - private MutualViewPosition ViewPosition(HashedLinkedList otherView) + /// + /// + /// + /// + /// The position of View(otherOffset, otherSize) wrt. this view + private MutualViewPosition ViewPosition(HashedLinkedList otherView) + { + Node otherstartsentinel = otherView.startsentinel!, otherendsentinel = otherView.endsentinel!, + first = startsentinel!.next!, last = endsentinel!.prev!, + otherfirst = otherstartsentinel.next!, otherlast = otherendsentinel.prev!; + if (last.Precedes(otherfirst!) || otherlast.Precedes(first!)) { - Node otherstartsentinel = otherView.startsentinel!, otherendsentinel = otherView.endsentinel!, - first = startsentinel!.next!, last = endsentinel!.prev!, - otherfirst = otherstartsentinel.next!, otherlast = otherendsentinel.prev!; - if (last.Precedes(otherfirst!) || otherlast.Precedes(first!)) - { - return MutualViewPosition.NonOverlapping; - } + return MutualViewPosition.NonOverlapping; + } - if (size == 0 || (otherstartsentinel.Precedes(first!) && last.Precedes(otherendsentinel))) - { - return MutualViewPosition.Contains; - } + if (size == 0 || (otherstartsentinel.Precedes(first!) && last.Precedes(otherendsentinel))) + { + return MutualViewPosition.Contains; + } - if (otherView.size == 0 || (startsentinel.Precedes(otherfirst!) && otherlast.Precedes(endsentinel))) - { - return MutualViewPosition.ContainedIn; - } + if (otherView.size == 0 || (startsentinel.Precedes(otherfirst!) && otherlast.Precedes(endsentinel))) + { + return MutualViewPosition.ContainedIn; + } - return MutualViewPosition.Overlapping; + return MutualViewPosition.Overlapping; - } + } - private void DisposeOverlappingViews(bool reverse) + private void DisposeOverlappingViews(bool reverse) + { + if (views != null) { - if (views != null) + foreach (HashedLinkedList view in views) { - foreach (HashedLinkedList view in views) + if (view != this) { - if (view != this) + switch (ViewPosition(view)) { - switch (ViewPosition(view)) - { - case MutualViewPosition.ContainedIn: - if (reverse) - { } - else - { - view.Dispose(); - } - - break; - case MutualViewPosition.Overlapping: + case MutualViewPosition.ContainedIn: + if (reverse) + { } + else + { view.Dispose(); - break; - case MutualViewPosition.Contains: - case MutualViewPosition.NonOverlapping: - break; - } + } + + break; + case MutualViewPosition.Overlapping: + view.Dispose(); + break; + case MutualViewPosition.Contains: + case MutualViewPosition.NonOverlapping: + break; } } } } + } - #endregion + #endregion - #endregion + #endregion - #region Constructors + #region Constructors - /// - /// Create a linked list with en external item equalityComparer - /// - /// The external equalitySCG.Comparer - public HashedLinkedList(SCG.IEqualityComparer itemequalityComparer) - : base(itemequalityComparer) - { - offset = 0; - size = stamp = 0; - startsentinel = new Node(default); - endsentinel = new Node(default); - startsentinel.next = endsentinel; - endsentinel.prev = startsentinel; - //It is important that the sentinels are different: - startsentinel.taggroup = new TagGroup - { - tag = int.MinValue, - count = 0 - }; - endsentinel.taggroup = new TagGroup - { - tag = int.MaxValue, - count = 0 - }; - dict = new HashDictionary(itemequalityComparer); - } + /// + /// Create a linked list with en external item equalityComparer + /// + /// The external equalitySCG.Comparer + public HashedLinkedList(SCG.IEqualityComparer itemequalityComparer) + : base(itemequalityComparer) + { + offset = 0; + size = stamp = 0; + startsentinel = new Node(default); + endsentinel = new Node(default); + startsentinel.next = endsentinel; + endsentinel.prev = startsentinel; + //It is important that the sentinels are different: + startsentinel.taggroup = new TagGroup + { + tag = int.MinValue, + count = 0 + }; + endsentinel.taggroup = new TagGroup + { + tag = int.MaxValue, + count = 0 + }; + dict = new HashDictionary(itemequalityComparer); + } - /// - /// Create a linked list with the natural item equalityComparer - /// - public HashedLinkedList() : this(EqualityComparer.Default) { } + /// + /// Create a linked list with the natural item equalityComparer + /// + public HashedLinkedList() : this(EqualityComparer.Default) { } - #endregion + #endregion - #region Node nested class + #region Node nested class - /// - /// An individual cell in the linked list - /// - private class Node - { - public Node? prev; + /// + /// An individual cell in the linked list + /// + private class Node + { + public Node? prev; - public Node? next; + public Node? next; - public T item; + public T item; - #region Tag support - internal int tag; + #region Tag support + internal int tag; - internal TagGroup taggroup; + internal TagGroup taggroup; - internal bool Precedes(Node that) - { - //Debug.Assert(taggroup != null, "taggroup field null"); - //Debug.Assert(that.taggroup != null, "that.taggroup field null"); - int t1 = taggroup.tag; - int t2 = that.taggroup.tag; + internal bool Precedes(Node that) + { + //Debug.Assert(taggroup != null, "taggroup field null"); + //Debug.Assert(that.taggroup != null, "that.taggroup field null"); + int t1 = taggroup.tag; + int t2 = that.taggroup.tag; - return t1 < t2 || (t1 == t2 && tag < that.tag); - } - #endregion + return t1 < t2 || (t1 == t2 && tag < that.tag); + } + #endregion - internal Node(T item) { this.item = item; } + internal Node(T item) { this.item = item; } - internal Node(T item, Node prev, Node? next) - { - this.item = item; this.prev = prev; this.next = next; - } + internal Node(T item, Node prev, Node? next) + { + this.item = item; this.prev = prev; this.next = next; + } - public override string ToString() - { - return string.Format("Node: (item={0}, tag={1})", item, tag); + public override string ToString() + { + return string.Format("Node: (item={0}, tag={1})", item, tag); - } } + } - #endregion + #endregion + + #region Taggroup nested class and tag maintenance utilities + /// + /// A group of nodes with the same high tag. Purpose is to be + /// able to tell the sequence order of two nodes without having to scan through + /// the list. + /// + private class TagGroup + { + internal int tag, count; + + internal Node? first, last; - #region Taggroup nested class and tag maintenance utilities /// - /// A group of nodes with the same high tag. Purpose is to be - /// able to tell the sequence order of two nodes without having to scan through - /// the list. + /// Pretty print a tag group /// - private class TagGroup - { - internal int tag, count; + /// Formatted tag group + public override string ToString() + { return string.Format("TagGroup(tag={0}, cnt={1}, fst={2}, lst={3})", tag, count, first, last); } + } + + //Constants for tag maintenance + private const int wordsize = 32; + private const int lobits = 3; + private const int hibits = lobits + 1; + private const int losize = 1 << lobits; + private const int hisize = 1 << hibits; - internal Node? first, last; + // const int logwordsize = 5; + + private TagGroup GetTagGroup(Node pred, Node succ, out int lowbound, out int highbound) + { + TagGroup predgroup = pred.taggroup, succgroup = succ.taggroup; - /// - /// Pretty print a tag group - /// - /// Formatted tag group - public override string ToString() - { return string.Format("TagGroup(tag={0}, cnt={1}, fst={2}, lst={3})", tag, count, first, last); } + if (predgroup == succgroup) + { + lowbound = pred.tag + 1; + highbound = succ.tag - 1; + return predgroup; + } + else if (predgroup.first != null) + { + lowbound = pred.tag + 1; + highbound = int.MaxValue; + return predgroup; + } + else if (succgroup.first != null) + { + lowbound = int.MinValue; + highbound = succ.tag - 1; + return succgroup; + } + else + { + lowbound = int.MinValue; + highbound = int.MaxValue; + return new TagGroup(); } + } - //Constants for tag maintenance - private const int wordsize = 32; - private const int lobits = 3; - private const int hibits = lobits + 1; - private const int losize = 1 << lobits; - private const int hisize = 1 << hibits; - // const int logwordsize = 5; + /// + /// Put a tag on a node (already inserted in the list). Split taggroups and renumber as + /// necessary. + /// + /// The node to tag + private void SetTag(Node node) + { + Node pred = node.prev!, succ = node.next!; + TagGroup predgroup = pred.taggroup, succgroup = succ.taggroup; - private TagGroup GetTagGroup(Node pred, Node succ, out int lowbound, out int highbound) + if (predgroup == succgroup) { - TagGroup predgroup = pred.taggroup, succgroup = succ.taggroup; - - if (predgroup == succgroup) - { - lowbound = pred.tag + 1; - highbound = succ.tag - 1; - return predgroup; - } - else if (predgroup.first != null) - { - lowbound = pred.tag + 1; - highbound = int.MaxValue; - return predgroup; - } - else if (succgroup.first != null) + node.taggroup = predgroup; + predgroup.count++; + if (pred.tag + 1 == succ.tag) { - lowbound = int.MinValue; - highbound = succ.tag - 1; - return succgroup; + SplitTagGroup(predgroup); } else { - lowbound = int.MinValue; - highbound = int.MaxValue; - return new TagGroup(); + node.tag = (pred.tag + 1) / 2 + (succ.tag - 1) / 2; } } - - - /// - /// Put a tag on a node (already inserted in the list). Split taggroups and renumber as - /// necessary. - /// - /// The node to tag - private void SetTag(Node node) + else if (predgroup.first != null) { - Node pred = node.prev!, succ = node.next!; - TagGroup predgroup = pred.taggroup, succgroup = succ.taggroup; - - if (predgroup == succgroup) + node.taggroup = predgroup; + predgroup.last = node; + predgroup.count++; + if (pred.tag == int.MaxValue) { - node.taggroup = predgroup; - predgroup.count++; - if (pred.tag + 1 == succ.tag) - { - SplitTagGroup(predgroup); - } - else - { - node.tag = (pred.tag + 1) / 2 + (succ.tag - 1) / 2; - } + SplitTagGroup(predgroup); } - else if (predgroup.first != null) + else { - node.taggroup = predgroup; - predgroup.last = node; - predgroup.count++; - if (pred.tag == int.MaxValue) - { - SplitTagGroup(predgroup); - } - else - { - node.tag = pred.tag / 2 + int.MaxValue / 2 + 1; - } + node.tag = pred.tag / 2 + int.MaxValue / 2 + 1; } - else if (succgroup.first != null) + } + else if (succgroup.first != null) + { + node.taggroup = succgroup; + succgroup.first = node; + succgroup.count++; + if (succ.tag == int.MinValue) { - node.taggroup = succgroup; - succgroup.first = node; - succgroup.count++; - if (succ.tag == int.MinValue) - { - SplitTagGroup(node.taggroup); - } - else - { - node.tag = int.MinValue / 2 + (succ.tag - 1) / 2; - } + SplitTagGroup(node.taggroup); } else { - System.Diagnostics.Debug.Assert(Taggroups == 0); - - TagGroup newgroup = new TagGroup(); - - Taggroups = 1; - node.taggroup = newgroup; - newgroup.first = newgroup.last = node; - newgroup.count = 1; - return; + node.tag = int.MinValue / 2 + (succ.tag - 1) / 2; } } - - - /// - /// Remove a node from its taggroup. - ///
When this is called, node must already have been removed from the underlying list - ///
- /// The node to remove - private void RemoveFromTagGroup(Node node) + else { + System.Diagnostics.Debug.Assert(Taggroups == 0); - TagGroup taggroup = node.taggroup; - - if (--taggroup.count == 0) - { - Taggroups--; - return; - } + TagGroup newgroup = new(); - if (node == taggroup.first) - { - taggroup.first = node.next!; - } + Taggroups = 1; + node.taggroup = newgroup; + newgroup.first = newgroup.last = node; + newgroup.count = 1; + return; + } + } - if (node == taggroup.last) - { - taggroup.last = node.prev!; - } - //node.taggroup = null; - if (taggroup.count != losize || Taggroups == 1) - { - return; - } + /// + /// Remove a node from its taggroup. + ///
When this is called, node must already have been removed from the underlying list + ///
+ /// The node to remove + private void RemoveFromTagGroup(Node node) + { - TagGroup otg; - // bug20070911: - Node neighbor; - if ((neighbor = taggroup.first!.prev!) != startsentinel - && (otg = neighbor.taggroup).count <= losize) - { - taggroup.first = otg.first; - } - else if ((neighbor = taggroup.last!.next!) != endsentinel - && (otg = neighbor.taggroup).count <= losize) - { - taggroup.last = otg.last; - } - else - { - return; - } + TagGroup taggroup = node.taggroup; - Node n = otg.first!; + if (--taggroup.count == 0) + { + Taggroups--; + return; + } - for (int i = 0, length = otg.count; i < length; i++) - { - n.taggroup = taggroup; - n = n.next!; - } + if (node == taggroup.first) + { + taggroup.first = node.next!; + } - taggroup.count += otg.count; - Taggroups--; - n = taggroup.first!; + if (node == taggroup.last) + { + taggroup.last = node.prev!; + } - const int ofs = wordsize - hibits; + //node.taggroup = null; + if (taggroup.count != losize || Taggroups == 1) + { + return; + } - for (int i = 0, count = taggroup.count; i < count; i++) - { - n.tag = (i - losize) << ofs; //(i-8)<<28 - n = n.next!; - } + TagGroup otg; + // bug20070911: + Node neighbor; + if ((neighbor = taggroup.first!.prev!) != startsentinel + && (otg = neighbor.taggroup).count <= losize) + { + taggroup.first = otg.first; + } + else if ((neighbor = taggroup.last!.next!) != endsentinel + && (otg = neighbor.taggroup).count <= losize) + { + taggroup.last = otg.last; + } + else + { + return; } + Node n = otg.first!; - /// - /// Split a tag group to make rom for more tags. - /// - /// The tag group - private void SplitTagGroup(TagGroup taggroup) + for (int i = 0, length = otg.count; i < length; i++) { - Node n = taggroup.first!; - int ptgt = taggroup.first!.prev!.taggroup.tag; - int ntgt = taggroup.last!.next!.taggroup.tag; + n.taggroup = taggroup; + n = n.next!; + } - System.Diagnostics.Debug.Assert(ptgt + 1 <= ntgt - 1); + taggroup.count += otg.count; + Taggroups--; + n = taggroup.first!; - int ofs = wordsize - hibits; - int newtgs = (taggroup.count - 1) / hisize; - int tgtdelta = (int)((ntgt + 0.0 - ptgt) / (newtgs + 2)), tgtag = ptgt; + const int ofs = wordsize - hibits; - tgtdelta = tgtdelta == 0 ? 1 : tgtdelta; - for (int j = 0; j < newtgs; j++) - { - TagGroup newtaggroup = new TagGroup - { - tag = (tgtag = tgtag >= ntgt - tgtdelta ? ntgt : tgtag + tgtdelta), - first = n, - count = hisize - }; - for (int i = 0; i < hisize; i++) - { - n.taggroup = newtaggroup; - n.tag = (i - losize) << ofs; //(i-8)<<28 - n = n.next!; - } + for (int i = 0, count = taggroup.count; i < count; i++) + { + n.tag = (i - losize) << ofs; //(i-8)<<28 + n = n.next!; + } + } - newtaggroup.last = n.prev!; - } - int rest = taggroup.count - hisize * newtgs; + /// + /// Split a tag group to make rom for more tags. + /// + /// The tag group + private void SplitTagGroup(TagGroup taggroup) + { + Node n = taggroup.first!; + int ptgt = taggroup.first!.prev!.taggroup.tag; + int ntgt = taggroup.last!.next!.taggroup.tag; + + System.Diagnostics.Debug.Assert(ptgt + 1 <= ntgt - 1); + + int ofs = wordsize - hibits; + int newtgs = (taggroup.count - 1) / hisize; + int tgtdelta = (int)((ntgt + 0.0 - ptgt) / (newtgs + 2)), tgtag = ptgt; - taggroup.first = n; - taggroup.count = rest; - taggroup.tag = (tgtag = tgtag >= ntgt - tgtdelta ? ntgt : tgtag + tgtdelta); ofs--; - for (int i = 0; i < rest; i++) + tgtdelta = tgtdelta == 0 ? 1 : tgtdelta; + for (int j = 0; j < newtgs; j++) + { + TagGroup newtaggroup = new() + { + tag = (tgtag = tgtag >= ntgt - tgtdelta ? ntgt : tgtag + tgtdelta), + first = n, + count = hisize + }; + for (int i = 0; i < hisize; i++) { - n.tag = (i - hisize) << ofs; //(i-16)<<27 + n.taggroup = newtaggroup; + n.tag = (i - losize) << ofs; //(i-8)<<28 n = n.next!; } - taggroup.last = n.prev!; - Taggroups += newtgs; - if (tgtag == ntgt) - { - RedistributeTagGroups(taggroup); - } + newtaggroup.last = n.prev!; } + int rest = taggroup.count - hisize * newtgs; - private void RedistributeTagGroups(TagGroup taggroup) + taggroup.first = n; + taggroup.count = rest; + taggroup.tag = (tgtag = tgtag >= ntgt - tgtdelta ? ntgt : tgtag + tgtdelta); ofs--; + for (int i = 0; i < rest; i++) { - TagGroup pred = taggroup, succ = taggroup, tmp; - int bits = 1, count = 1; - double limit = 1, bigt = Math.Pow(Taggroups, 1.0 / 30);//????? + n.tag = (i - hisize) << ofs; //(i-16)<<27 + n = n.next!; + } + + taggroup.last = n.prev!; + Taggroups += newtgs; + if (tgtag == ntgt) + { + RedistributeTagGroups(taggroup); + } + } - do - { - bits++; - int lowmask = (1 << bits) - 1; - int himask = ~lowmask; - int target = taggroup.tag & himask; - while ((tmp = pred.first!.prev!.taggroup).first != null && (tmp.tag & himask) == target) - { count++; pred = tmp; } - while ((tmp = succ.last!.next!.taggroup).last != null && (tmp.tag & himask) == target) - { count++; succ = tmp; } + private void RedistributeTagGroups(TagGroup taggroup) + { + TagGroup pred = taggroup, succ = taggroup, tmp; + int bits = 1, count = 1; + double limit = 1, bigt = Math.Pow(Taggroups, 1.0 / 30);//????? - limit *= bigt; - } while (count > limit); + do + { + bits++; + int lowmask = (1 << bits) - 1; + int himask = ~lowmask; + int target = taggroup.tag & himask; + while ((tmp = pred.first!.prev!.taggroup).first != null && (tmp.tag & himask) == target) + { count++; pred = tmp; } - //redistibute tags - int lob = pred.first.prev.taggroup.tag, upb = succ.last.next.taggroup.tag; - int delta = upb / (count + 1) - lob / (count + 1); + while ((tmp = succ.last!.next!.taggroup).last != null && (tmp.tag & himask) == target) + { count++; succ = tmp; } - System.Diagnostics.Debug.Assert(delta > 0); - for (int i = 0; i < count; i++) - { - pred.tag = lob + (i + 1) * delta; - pred = pred.last!.next!.taggroup; - } - } + limit *= bigt; + } while (count > limit); - #endregion + //redistibute tags + int lob = pred.first.prev.taggroup.tag, upb = succ.last.next.taggroup.tag; + int delta = upb / (count + 1) - lob / (count + 1); - #region Position, PositionComparer and ViewHandler nested types - private class PositionComparer : SCG.IComparer + System.Diagnostics.Debug.Assert(delta > 0); + for (int i = 0; i < count; i++) { - private static PositionComparer _default; + pred.tag = lob + (i + 1) * delta; + pred = pred.last!.next!.taggroup; + } + } - private PositionComparer() { } - public static PositionComparer Default => _default ??= new PositionComparer(); - public int Compare(Position a, Position b) - { - return a.Endpoint == b.Endpoint ? 0 : a.Endpoint.Precedes(b.Endpoint) ? -1 : 1; + #endregion - } - } + #region Position, PositionComparer and ViewHandler nested types + private class PositionComparer : SCG.IComparer + { + private static PositionComparer _default; - /// - /// During RemoveAll, we need to cache the original endpoint indices of views - /// - private struct Position + private PositionComparer() { } + public static PositionComparer Default => _default ??= new PositionComparer(); + public int Compare(Position a, Position b) { - public HashedLinkedList? View { get; } + return a.Endpoint == b.Endpoint ? 0 : a.Endpoint.Precedes(b.Endpoint) ? -1 : 1; + + } + } - public bool Left { get; private set; } + /// + /// During RemoveAll, we need to cache the original endpoint indices of views + /// + private struct Position + { + public HashedLinkedList? View { get; } - public Node Endpoint { get; } + public bool Left { get; private set; } - public Position(HashedLinkedList view, bool left) - { - View = view; - Left = left; - Endpoint = (left ? view.startsentinel!.next : view.endsentinel!.prev)!; - } + public Node Endpoint { get; } - public Position(Node node) - { - Endpoint = node; - View = null; - Left = false; - } + public Position(HashedLinkedList view, bool left) + { + View = view; + Left = left; + Endpoint = (left ? view.startsentinel!.next : view.endsentinel!.prev)!; + } + public Position(Node node) + { + Endpoint = node; + View = null; + Left = false; } - //TODO: merge the two implementations using Position values as arguments - /// - /// Handle the update of (other) views during a multi-remove operation. - /// - private struct ViewHandler + } + + //TODO: merge the two implementations using Position values as arguments + /// + /// Handle the update of (other) views during a multi-remove operation. + /// + private struct ViewHandler + { + private readonly ArrayList? leftEnds; + private readonly ArrayList? rightEnds; + private int leftEndIndex, rightEndIndex, leftEndIndex2, rightEndIndex2; + internal readonly int viewCount; + internal ViewHandler(HashedLinkedList list) { - private readonly ArrayList? leftEnds; - private readonly ArrayList? rightEnds; - private int leftEndIndex, rightEndIndex, leftEndIndex2, rightEndIndex2; - internal readonly int viewCount; - internal ViewHandler(HashedLinkedList list) + leftEndIndex = rightEndIndex = leftEndIndex2 = rightEndIndex2 = viewCount = 0; + leftEnds = rightEnds = null; + if (list.views != null) { - leftEndIndex = rightEndIndex = leftEndIndex2 = rightEndIndex2 = viewCount = 0; - leftEnds = rightEnds = null; - if (list.views != null) + foreach (HashedLinkedList v in list.views) { - foreach (HashedLinkedList v in list.views) + if (v != list) { - if (v != list) + if (leftEnds == null || rightEnds == null) { - if (leftEnds == null || rightEnds == null) - { - leftEnds = new ArrayList(); - rightEnds = new ArrayList(); - } - leftEnds.Add(new Position(v, true)); - rightEnds.Add(new Position(v, false)); + leftEnds = new ArrayList(); + rightEnds = new ArrayList(); } + leftEnds.Add(new Position(v, true)); + rightEnds.Add(new Position(v, false)); } } + } - if (leftEnds == null || rightEnds == null) - { - return; - } - - viewCount = leftEnds.Count; - leftEnds.Sort(PositionComparer.Default); - rightEnds.Sort(PositionComparer.Default); + if (leftEnds == null || rightEnds == null) + { + return; } - internal void SkipEndpoints(int removed, Node n) + + viewCount = leftEnds.Count; + leftEnds.Sort(PositionComparer.Default); + rightEnds.Sort(PositionComparer.Default); + } + internal void SkipEndpoints(int removed, Node n) + { + if (viewCount > 0) { - if (viewCount > 0) + Position endpoint; + while (leftEndIndex < viewCount && ((endpoint = leftEnds![leftEndIndex]).Endpoint.prev!.Precedes(n))) { - Position endpoint; - while (leftEndIndex < viewCount && ((endpoint = leftEnds![leftEndIndex]).Endpoint.prev!.Precedes(n))) - { - HashedLinkedList view = endpoint.View!; - view.offset -= removed;//TODO: extract offset.Value? - view.size += removed; - leftEndIndex++; - } - while (rightEndIndex < viewCount && (endpoint = rightEnds![rightEndIndex]).Endpoint.Precedes(n)) - { - HashedLinkedList view = endpoint.View!; - view.size -= removed; - rightEndIndex++; - } + HashedLinkedList view = endpoint.View!; + view.offset -= removed;//TODO: extract offset.Value? + view.size += removed; + leftEndIndex++; } - if (viewCount > 0) + while (rightEndIndex < viewCount && (endpoint = rightEnds![rightEndIndex]).Endpoint.Precedes(n)) { - while (leftEndIndex2 < viewCount && (_ = leftEnds![leftEndIndex2]).Endpoint.prev!.Precedes(n)) - { - leftEndIndex2++; - } - - while (rightEndIndex2 < viewCount && (_ = rightEnds![rightEndIndex2]).Endpoint.next!.Precedes(n)) - { - rightEndIndex2++; - } + HashedLinkedList view = endpoint.View!; + view.size -= removed; + rightEndIndex++; } } - /// - /// To be called with n pointing to the right of each node to be removed in a stretch. - /// And at the endsentinel. - /// - /// Update offset of a view whose left endpoint (has not already been handled and) is n or precedes n. - /// I.e. startsentinel precedes n. - /// Also update the size as a prelude to handling the right endpoint. - /// - /// Update size of a view not already handled and whose right endpoint precedes n. - /// - /// The number of nodes left of n to be removed - /// - internal void UpdateViewSizesAndCounts(int removed, Node n) - { - if (viewCount > 0) + if (viewCount > 0) + { + while (leftEndIndex2 < viewCount && (_ = leftEnds![leftEndIndex2]).Endpoint.prev!.Precedes(n)) { - Position endpoint; - while (leftEndIndex < viewCount && ((endpoint = leftEnds![leftEndIndex]).Endpoint.prev!.Precedes(n))) - { - HashedLinkedList view = endpoint.View!; - view.offset -= removed; //TODO: fix use of offset - view.size += removed; - leftEndIndex++; - } - while (rightEndIndex < viewCount && (endpoint = rightEnds![rightEndIndex]).Endpoint.Precedes(n)) - { - HashedLinkedList view = endpoint.View!; - view.size -= removed; - rightEndIndex++; - } + leftEndIndex2++; + } + + while (rightEndIndex2 < viewCount && (_ = rightEnds![rightEndIndex2]).Endpoint.next!.Precedes(n)) + { + rightEndIndex2++; } } - /// - /// To be called with n being the first not-to-be-removed node after a (stretch of) node(s) to be removed. - /// - /// It will update the startsentinel of views (that have not been handled before and) - /// whose startsentinel precedes n, i.e. is to be deleted. - /// - /// It will update the endsentinel of views (...) whose endsentinel precedes n, i.e. is to be deleted. - /// - /// PROBLEM: DOESNT WORK AS ORIGINALLY ADVERTISED. WE MUST DO THIS BEFORE WE ACTUALLY REMOVE THE NODES. WHEN THE - /// NODES HAVE BEEN REMOVED, THE precedes METHOD WILL NOT WORK! - /// - /// - /// - /// - internal void UpdateSentinels(Node n, Node newstart, Node newend) - { - if (viewCount > 0) + } + /// + /// To be called with n pointing to the right of each node to be removed in a stretch. + /// And at the endsentinel. + /// + /// Update offset of a view whose left endpoint (has not already been handled and) is n or precedes n. + /// I.e. startsentinel precedes n. + /// Also update the size as a prelude to handling the right endpoint. + /// + /// Update size of a view not already handled and whose right endpoint precedes n. + /// + /// The number of nodes left of n to be removed + /// + internal void UpdateViewSizesAndCounts(int removed, Node n) + { + if (viewCount > 0) + { + Position endpoint; + while (leftEndIndex < viewCount && ((endpoint = leftEnds![leftEndIndex]).Endpoint.prev!.Precedes(n))) { - Position endpoint; - while (leftEndIndex2 < viewCount && (endpoint = leftEnds![leftEndIndex2]).Endpoint.prev!.Precedes(n)) - { - HashedLinkedList view = endpoint.View!; - view.startsentinel = newstart; - leftEndIndex2++; - } - while (rightEndIndex2 < viewCount && (endpoint = rightEnds![rightEndIndex2]).Endpoint.next!.Precedes(n)) - { - HashedLinkedList view = endpoint.View!; - view.endsentinel = newend; - rightEndIndex2++; - } + HashedLinkedList view = endpoint.View!; + view.offset -= removed; //TODO: fix use of offset + view.size += removed; + leftEndIndex++; + } + while (rightEndIndex < viewCount && (endpoint = rightEnds![rightEndIndex]).Endpoint.Precedes(n)) + { + HashedLinkedList view = endpoint.View!; + view.size -= removed; + rightEndIndex++; } } - } - #endregion - - #region Range nested class - - private class Range : DirectedCollectionValueBase, IDirectedCollectionValue + /// + /// To be called with n being the first not-to-be-removed node after a (stretch of) node(s) to be removed. + /// + /// It will update the startsentinel of views (that have not been handled before and) + /// whose startsentinel precedes n, i.e. is to be deleted. + /// + /// It will update the endsentinel of views (...) whose endsentinel precedes n, i.e. is to be deleted. + /// + /// PROBLEM: DOESNT WORK AS ORIGINALLY ADVERTISED. WE MUST DO THIS BEFORE WE ACTUALLY REMOVE THE NODES. WHEN THE + /// NODES HAVE BEEN REMOVED, THE precedes METHOD WILL NOT WORK! + /// + /// + /// + /// + internal void UpdateSentinels(Node n, Node newstart, Node newend) { - // int start; - private readonly int count, rangestamp; - private readonly Node? startnode, endnode; - private readonly HashedLinkedList list; - private bool forwards; - - - internal Range(HashedLinkedList list, int start, int count, bool forwards) + if (viewCount > 0) { - this.list = list; - rangestamp = list.underlying != null ? list.underlying.stamp : list.stamp; - // this.start = start; - this.count = count; - this.forwards = forwards; - if (count > 0) + Position endpoint; + while (leftEndIndex2 < viewCount && (endpoint = leftEnds![leftEndIndex2]).Endpoint.prev!.Precedes(n)) + { + HashedLinkedList view = endpoint.View!; + view.startsentinel = newstart; + leftEndIndex2++; + } + while (rightEndIndex2 < viewCount && (endpoint = rightEnds![rightEndIndex2]).Endpoint.next!.Precedes(n)) { - startnode = list.Get(start); - endnode = list.Get(start + count - 1); + HashedLinkedList view = endpoint.View!; + view.endsentinel = newend; + rightEndIndex2++; } } + } - public override bool IsEmpty { get { list.ModifyCheck(rangestamp); return count == 0; } } - - public override int Count { get { list.ModifyCheck(rangestamp); return count; } } + } + #endregion + #region Range nested class - public override Speed CountSpeed { get { list.ModifyCheck(rangestamp); return Speed.Constant; } } + private class Range : DirectedCollectionValueBase, IDirectedCollectionValue + { + // int start; + private readonly int count, rangestamp; + private readonly Node? startnode, endnode; + private readonly HashedLinkedList list; + private bool forwards; - public override T Choose() + internal Range(HashedLinkedList list, int start, int count, bool forwards) + { + this.list = list; + rangestamp = list.underlying != null ? list.underlying.stamp : list.stamp; + // this.start = start; + this.count = count; + this.forwards = forwards; + if (count > 0) { - list.ModifyCheck(rangestamp); - if (count > 0) - { - return startnode!.item; - } - - throw new NoSuchItemException(); + startnode = list.Get(start); + endnode = list.Get(start + count - 1); } + } + public override bool IsEmpty { get { list.ModifyCheck(rangestamp); return count == 0; } } - public override SCG.IEnumerator GetEnumerator() - { - int togo = count; + public override int Count { get { list.ModifyCheck(rangestamp); return count; } } - list.ModifyCheck(rangestamp); - if (togo == 0) - { - yield break; - } - Node cursor = (forwards ? startnode : endnode)!; + public override Speed CountSpeed { get { list.ModifyCheck(rangestamp); return Speed.Constant; } } - yield return cursor.item; - while (--togo > 0) - { - cursor = (forwards ? cursor.next : cursor.prev)!; - list.ModifyCheck(rangestamp); - yield return cursor!.item; - } + + public override T Choose() + { + list.ModifyCheck(rangestamp); + if (count > 0) + { + return startnode!.item; } + throw new NoSuchItemException(); + } + + + public override SCG.IEnumerator GetEnumerator() + { + int togo = count; - public override IDirectedCollectionValue Backwards() + list.ModifyCheck(rangestamp); + if (togo == 0) { - list.ModifyCheck(rangestamp); + yield break; + } - Range b = (Range)MemberwiseClone(); + Node cursor = (forwards ? startnode : endnode)!; - b.forwards = !forwards; - return b; + yield return cursor.item; + while (--togo > 0) + { + cursor = (forwards ? cursor.next : cursor.prev)!; + list.ModifyCheck(rangestamp); + yield return cursor!.item; } + } - IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } + public override IDirectedCollectionValue Backwards() + { + list.ModifyCheck(rangestamp); + Range b = (Range)MemberwiseClone(); - public override Direction Direction => forwards ? Direction.Forwards : Direction.Backwards; + b.forwards = !forwards; + return b; } - #endregion + IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } - #region IDisposable Members - /// - /// Invalidate this list. If a view, just invalidate the view. - /// If not a view, invalidate the list and all views on it. - /// - public virtual void Dispose() - { - Dispose(false); - } + public override Direction Direction => forwards ? Direction.Forwards : Direction.Backwards; + } + + + #endregion + + #region IDisposable Members + + /// + /// Invalidate this list. If a view, just invalidate the view. + /// If not a view, invalidate the list and all views on it. + /// + public virtual void Dispose() + { + Dispose(false); + } - private void Dispose(bool disposingUnderlying) + private void Dispose(bool disposingUnderlying) + { + if (isValid) { - if (isValid) + if (underlying != null) { - if (underlying != null) + isValid = false; + if (!disposingUnderlying && views != null) { - isValid = false; - if (!disposingUnderlying && views != null) - { - views.Remove(myWeakReference!); - } - - endsentinel = null; - startsentinel = null; - underlying = null; - views = null; - myWeakReference = null; + views.Remove(myWeakReference!); } - else + + endsentinel = null; + startsentinel = null; + underlying = null; + views = null; + myWeakReference = null; + } + else + { + //isValid = false; + //endsentinel = null; + //startsentinel = null; + if (views != null) { - //isValid = false; - //endsentinel = null; - //startsentinel = null; - if (views != null) + foreach (HashedLinkedList view in views) { - foreach (HashedLinkedList view in views) - { - view.Dispose(true); - } + view.Dispose(true); } - //views = null; - Clear(); } + //views = null; + Clear(); } } + } - #endregion IDisposable stuff + #endregion IDisposable stuff - #region IList Members + #region IList Members - /// - /// - /// if this list is empty. - /// The first item in this list. - public virtual T First + /// + /// + /// if this list is empty. + /// The first item in this list. + public virtual T First + { + get { - get + Validitycheck(); + if (size == 0) { - Validitycheck(); - if (size == 0) - { - throw new NoSuchItemException(); - } - - return startsentinel!.next!.item; + throw new NoSuchItemException(); } + + return startsentinel!.next!.item; } + } - /// - /// - /// if this list is empty. - /// The last item in this list. - public virtual T Last + /// + /// + /// if this list is empty. + /// The last item in this list. + public virtual T Last + { + get { - get + Validitycheck(); + if (size == 0) { - Validitycheck(); - if (size == 0) - { - throw new NoSuchItemException(); - } - - return endsentinel!.prev!.item; + throw new NoSuchItemException(); } - } - - /// - /// Since Add(T item) always add at the end of the list, - /// this describes if list has FIFO or LIFO semantics. - /// - /// True if the Remove() operation removes from the - /// start of the list, false if it removes from the end. THe default for a new linked list is true. - public virtual bool FIFO - { - get { Validitycheck(); return fIFO; } - set { UpdateCheck(); fIFO = value; } - } - /// - /// - /// - public virtual bool IsFixedSize - { - get { Validitycheck(); return false; } + return endsentinel!.prev!.item; } + } - /// - /// On this list, this indexer is read/write. - /// if i is negative or - /// >= the size of the collection. - /// - /// The i'th item of this list. - /// The index of the item to fetch or store. - public virtual T this[int index] - { - get { Validitycheck(); return Get(index).item; } - set - { - UpdateCheck(); - Node n = Get(index); - // - T item = n.item; - - if (itemequalityComparer.Equals(value, item)) - { - n.item = value; - dict.Update(value, n); - } - else if (!dict.FindOrAdd(value, ref n)) - { - dict.Remove(item); - n.item = value; - } - else - { - throw new ArgumentException("Item already in indexed list"); - } (underlying ?? this).RaiseForSetThis(index, value, item); - } - } + /// + /// Since Add(T item) always add at the end of the list, + /// this describes if list has FIFO or LIFO semantics. + /// + /// True if the Remove() operation removes from the + /// start of the list, false if it removes from the end. THe default for a new linked list is true. + public virtual bool FIFO + { + get { Validitycheck(); return fIFO; } + set { UpdateCheck(); fIFO = value; } + } - /// - /// - /// - /// - public virtual Speed IndexingSpeed => Speed.Linear; + /// + /// + /// + public virtual bool IsFixedSize + { + get { Validitycheck(); return false; } + } - /// - /// Insert an item at a specific index location in this list. - /// if i is negative or - /// > the size of the collection. - /// The index at which to insert. - /// The item to insert. - public virtual void Insert(int i, T item) + /// + /// On this list, this indexer is read/write. + /// if i is negative or + /// >= the size of the collection. + /// + /// The i'th item of this list. + /// The index of the item to fetch or store. + public virtual T this[int index] + { + get { Validitycheck(); return Get(index).item; } + set { UpdateCheck(); - Insert((i == size ? endsentinel : Get(i))!, item); - if (ActiveEvents != EventType.None) + Node n = Get(index); + // + T item = n.item; + + if (itemEqualityComparer.Equals(value, item)) + { + n.item = value; + dict.Update(value, n); + } + else if (!dict.FindOrAdd(value, ref n)) { - (underlying ?? this).RaiseForInsert(i + Offset, item); + dict.Remove(item); + n.item = value; } + else + { + throw new ArgumentException("Item already in indexed list"); + } (underlying ?? this).RaiseForSetThis(index, value, item); } + } - /// - /// Insert an item at the end of a compatible view, used as a pointer. - /// The pointer must be a view on the same list as - /// this and the endpoint of pointer must be - /// a valid insertion point of this - /// - /// If pointer - /// is not a view on the same list as this - /// ?????? if the endpoint of - /// pointer is not inside this - /// if the list has - /// AllowsDuplicates==false and the item is - /// already in the list. - /// - /// - public void Insert(IList pointer, T item) + /// + /// + /// + /// + public virtual Speed IndexingSpeed => Speed.Linear; + + /// + /// Insert an item at a specific index location in this list. + /// if i is negative or + /// > the size of the collection. + /// The index at which to insert. + /// The item to insert. + public virtual void Insert(int i, T item) + { + UpdateCheck(); + Insert((i == size ? endsentinel : Get(i))!, item); + if (ActiveEvents != EventType.None) { - UpdateCheck(); - if ((pointer == null) || ((pointer.Underlying ?? pointer) != (underlying ?? this))) - { - throw new IncompatibleViewException(); - } -#warning INEFFICIENT - //TODO: make this efficient (the whole point of the method: - //Do NOT use Insert, but insert the node at pointer.endsentinel, checking - //via the ordering that this is a valid insertion point - Insert(pointer.Offset + pointer.Count - Offset, item); + (underlying ?? this).RaiseForInsert(i + Offset, item); } + } - /// - /// Insert into this list all items from an enumerable collection starting - /// at a particular index. - /// if i is negative or - /// > the size of the collection. - /// - /// Index to start inserting at - /// Items to insert - public virtual void InsertAll(int i, SCG.IEnumerable items) + /// + /// Insert an item at the end of a compatible view, used as a pointer. + /// The pointer must be a view on the same list as + /// this and the endpoint of pointer must be + /// a valid insertion point of this + /// + /// If pointer + /// is not a view on the same list as this + /// ?????? if the endpoint of + /// pointer is not inside this + /// if the list has + /// AllowsDuplicates==false and the item is + /// already in the list. + /// + /// + public void Insert(IList pointer, T item) + { + UpdateCheck(); + if ((pointer == null) || ((pointer.Underlying ?? pointer) != (underlying ?? this))) { - InsertAll(i, items, true); + throw new IncompatibleViewException(); } +#warning INEFFICIENT + //TODO: make this efficient (the whole point of the method: + //Do NOT use Insert, but insert the node at pointer.endsentinel, checking + //via the ordering that this is a valid insertion point + Insert(pointer.Offset + pointer.Count - Offset, item); + } + + /// + /// Insert into this list all items from an enumerable collection starting + /// at a particular index. + /// if i is negative or + /// > the size of the collection. + /// + /// Index to start inserting at + /// Items to insert + public virtual void InsertAll(int i, SCG.IEnumerable items) + { + InsertAll(i, items, true); + } - private void InsertAll(int i, SCG.IEnumerable items, bool insertion) + private void InsertAll(int i, SCG.IEnumerable items, bool insertion) + { + UpdateCheck(); + Node succ, node, pred; + int count = 0; + succ = (i == size ? endsentinel : Get(i))!; + pred = node = succ.prev!; + TagGroup taggroup = GetTagGroup(node!, succ, out int thetag, out int taglimit); + try { - UpdateCheck(); - Node succ, node, pred; - int count = 0; - succ = (i == size ? endsentinel : Get(i))!; - pred = node = succ.prev!; - TagGroup taggroup = GetTagGroup(node!, succ, out int thetag, out int taglimit); - try + foreach (T item in items) { - foreach (T item in items) + Node tmp = new(item, node!, null); + if (!dict.FindOrAdd(item, ref tmp)) { - Node tmp = new Node(item, node!, null); - if (!dict.FindOrAdd(item, ref tmp)) - { - tmp.tag = thetag < taglimit ? ++thetag : thetag; - tmp.taggroup = taggroup; - node.next = tmp; - count++; - node = tmp; - } - else - { - throw new DuplicateNotAllowedException("Item already in indexed list"); - } + tmp.tag = thetag < taglimit ? ++thetag : thetag; + tmp.taggroup = taggroup; + node.next = tmp; + count++; + node = tmp; + } + else + { + throw new DuplicateNotAllowedException("Item already in indexed list"); } } - finally + } + finally + { + if (count != 0) { - if (count != 0) + taggroup.count += count; + if (taggroup != pred.taggroup) { - taggroup.count += count; - if (taggroup != pred.taggroup) - { - taggroup.first = pred.next!; - } - - if (taggroup != succ.taggroup) - { - taggroup.last = node; - } + taggroup.first = pred.next!; + } - succ.prev = node; - node.next = succ; - if (node.tag == node.prev!.tag) - { - SplitTagGroup(taggroup); - } + if (taggroup != succ.taggroup) + { + taggroup.last = node; + } - size += count; - if (underlying != null) - { - underlying.size += count; - } + succ.prev = node; + node.next = succ; + if (node.tag == node.prev!.tag) + { + SplitTagGroup(taggroup); + } - FixViewsAfterInsert(succ, pred, count); - RaiseForInsertAll(pred, i, count, insertion); + size += count; + if (underlying != null) + { + underlying.size += count; } - } + FixViewsAfterInsert(succ, pred, count); + RaiseForInsertAll(pred, i, count, insertion); + } } - private void RaiseForInsertAll(Node node, int i, int added, bool insertion) + } + + private void RaiseForInsertAll(Node node, int i, int added, bool insertion) + { + if (ActiveEvents != 0) { - if (ActiveEvents != 0) + int index = Offset + i; + if ((ActiveEvents & (EventType.Added | EventType.Inserted)) != 0) { - int index = Offset + i; - if ((ActiveEvents & (EventType.Added | EventType.Inserted)) != 0) + for (int j = index; j < index + added; j++) { - for (int j = index; j < index + added; j++) - { #warning must we check stamps here? - node = node.next!; - T item = node!.item; - if (insertion) - { - RaiseItemInserted(item, j); - } - - RaiseItemsAdded(item, 1); + node = node.next!; + T item = node!.item; + if (insertion) + { + RaiseItemInserted(item, j); } - } - RaiseCollectionChanged(); + RaiseItemsAdded(item, 1); + } } - } - /// - /// Insert an item at the front of this list. - /// - /// The item to insert. - public virtual void InsertFirst(T item) - { - UpdateCheck(); - Insert(startsentinel!.next!, item); - if (ActiveEvents != EventType.None) - { - (underlying ?? this).RaiseForInsert(0 + Offset, item); - } + RaiseCollectionChanged(); } + } - /// - /// Insert an item at the back of this list. - /// - /// The item to insert. - public virtual void InsertLast(T item) + /// + /// Insert an item at the front of this list. + /// + /// The item to insert. + public virtual void InsertFirst(T item) + { + UpdateCheck(); + Insert(startsentinel!.next!, item); + if (ActiveEvents != EventType.None) { - UpdateCheck(); - Insert(endsentinel!, item); - if (ActiveEvents != EventType.None) - { - (underlying ?? this).RaiseForInsert(size - 1 + Offset, item); - } + (underlying ?? this).RaiseForInsert(0 + Offset, item); } + } - /// - /// Create a new list consisting of the results of mapping all items of this - /// list. - /// - /// The delegate defining the map. - /// The new list. - public IList Map(Func mapper) + /// + /// Insert an item at the back of this list. + /// + /// The item to insert. + public virtual void InsertLast(T item) + { + UpdateCheck(); + Insert(endsentinel!, item); + if (ActiveEvents != EventType.None) { - Validitycheck(); - - HashedLinkedList retval = new HashedLinkedList(); - return Map(mapper, retval); + (underlying ?? this).RaiseForInsert(size - 1 + Offset, item); } + } - /// - /// Create a new list consisting of the results of mapping all items of this - /// list. The new list will use a specified equalityComparer for the item type. - /// - /// The type of items of the new list - /// The delegate defining the map. - /// The equalityComparer to use for the new list - /// The new list. - public IList Map(Func mapper, SCG.IEqualityComparer equalityComparer) - { - Validitycheck(); + /// + /// Create a new list consisting of the results of mapping all items of this + /// list. + /// + /// The delegate defining the map. + /// The new list. + public IList Map(Func mapper) + { + Validitycheck(); - HashedLinkedList retval = new HashedLinkedList(equalityComparer); - return Map(mapper, retval); - } + HashedLinkedList retval = new(); + return Map(mapper, retval); + } - private IList Map(Func mapper, HashedLinkedList retval) - { - if (size == 0) - { - return retval; - } + /// + /// Create a new list consisting of the results of mapping all items of this + /// list. The new list will use a specified equalityComparer for the item type. + /// + /// The type of items of the new list + /// The delegate defining the map. + /// The equalityComparer to use for the new list + /// The new list. + public IList Map(Func mapper, SCG.IEqualityComparer equalityComparer) + { + Validitycheck(); - int stamp = this.stamp; - Node cursor = startsentinel!.next!; - HashedLinkedList.Node mcursor = retval.startsentinel!; + HashedLinkedList retval = new(equalityComparer); + return Map(mapper, retval); + } - double tagdelta = int.MaxValue / (size + 1.0); - int count = 1; - HashedLinkedList.TagGroup taggroup = new HashedLinkedList.TagGroup(); - retval.taggroups = 1; - taggroup.count = size; - while (cursor != endsentinel) - { - V v = mapper(cursor!.item); - ModifyCheck(stamp); - mcursor.next = new HashedLinkedList.Node(v, mcursor, null); - cursor = cursor.next!; - mcursor = mcursor.next; - retval.dict.Add(v, mcursor); - mcursor.taggroup = taggroup; - mcursor.tag = (int)(tagdelta * count++); - } + private IList Map(Func mapper, HashedLinkedList retval) + { + if (size == 0) + { + return retval; + } - taggroup.first = retval.startsentinel!.next!; - taggroup.last = mcursor; + int stamp = this.stamp; + Node cursor = startsentinel!.next!; + HashedLinkedList.Node mcursor = retval.startsentinel!; - retval.endsentinel!.prev = mcursor; - mcursor.next = retval.endsentinel; - retval.size = size; - return retval; + double tagdelta = int.MaxValue / (size + 1.0); + int count = 1; + HashedLinkedList.TagGroup taggroup = new(); + retval.taggroups = 1; + taggroup.count = size; + while (cursor != endsentinel) + { + V v = mapper(cursor!.item); + ModifyCheck(stamp); + mcursor.next = new HashedLinkedList.Node(v, mcursor, null); + cursor = cursor.next!; + mcursor = mcursor.next; + retval.dict.Add(v, mcursor); + mcursor.taggroup = taggroup; + mcursor.tag = (int)(tagdelta * count++); } - /// - /// Remove one item from the list: from the front if FIFO - /// is true, else from the back. - /// if this list is empty. - /// - /// The removed item. - public virtual T Remove() + taggroup.first = retval.startsentinel!.next!; + taggroup.last = mcursor; + + retval.endsentinel!.prev = mcursor; + mcursor.next = retval.endsentinel; + retval.size = size; + return retval; + } + + /// + /// Remove one item from the list: from the front if FIFO + /// is true, else from the back. + /// if this list is empty. + /// + /// The removed item. + public virtual T Remove() + { + UpdateCheck(); + if (size == 0) { - UpdateCheck(); - if (size == 0) - { - throw new NoSuchItemException("List is empty"); - } + throw new NoSuchItemException("List is empty"); + } - T item = fIFO ? Remove(startsentinel!.next!) : Remove(endsentinel!.prev!); - dict.Remove(item); - (underlying ?? this).RaiseForRemove(item); - return item; + T item = fIFO ? Remove(startsentinel!.next!) : Remove(endsentinel!.prev!); + dict.Remove(item); + (underlying ?? this).RaiseForRemove(item); + return item; + } + + /// + /// Remove one item from the front of the list. + /// if this list is empty. + /// + /// The removed item. + public virtual T RemoveFirst() + { + UpdateCheck(); + if (size == 0) + { + throw new NoSuchItemException("List is empty"); } - /// - /// Remove one item from the front of the list. - /// if this list is empty. - /// - /// The removed item. - public virtual T RemoveFirst() + T item = Remove(startsentinel!.next!); + dict.Remove(item); + if (ActiveEvents != EventType.None) { - UpdateCheck(); - if (size == 0) - { - throw new NoSuchItemException("List is empty"); - } + (underlying ?? this).RaiseForRemoveAt(Offset, item); + } - T item = Remove(startsentinel!.next!); - dict.Remove(item); - if (ActiveEvents != EventType.None) - { - (underlying ?? this).RaiseForRemoveAt(Offset, item); - } + return item; + } - return item; + /// + /// Remove one item from the back of the list. + /// if this list is empty. + /// + /// The removed item. + public virtual T RemoveLast() + { + UpdateCheck(); + if (size == 0) + { + throw new NoSuchItemException("List is empty"); } - /// - /// Remove one item from the back of the list. - /// if this list is empty. - /// - /// The removed item. - public virtual T RemoveLast() + T item = Remove(endsentinel!.prev!); + dict.Remove(item); + if (ActiveEvents != EventType.None) { - UpdateCheck(); - if (size == 0) - { - throw new NoSuchItemException("List is empty"); - } + (underlying ?? this).RaiseForRemoveAt(size + Offset, item); + } - T item = Remove(endsentinel!.prev!); - dict.Remove(item); - if (ActiveEvents != EventType.None) - { - (underlying ?? this).RaiseForRemoveAt(size + Offset, item); - } + return item; + } - return item; - } + /// + /// Create a list view on this list. + /// + /// if the start or count is negative + /// if the range does not fit within list. + /// The index in this list of the start of the view. + /// The size of the view. + /// The new list view. + public virtual IList? View(int start, int count) + { + CheckRange(start, count); + Validitycheck(); + views ??= new WeakViewList>(); + + HashedLinkedList retval = (HashedLinkedList)MemberwiseClone(); + retval.underlying = underlying ?? (this); + retval.offset = offset + start; + retval.size = count; + GetPair(start - 1, start + count, out retval.startsentinel, out retval.endsentinel, + [-1, size], [startsentinel!, endsentinel!]); + //retval.startsentinel = start == 0 ? startsentinel : get(start - 1); + //retval.endsentinel = start + count == size ? endsentinel : get(start + count); + + //TODO: for the purpose of Dispose, we need to retain a ref to the node + retval.myWeakReference = views.Add(retval); + return retval; + } - /// - /// Create a list view on this list. - /// - /// if the start or count is negative - /// if the range does not fit within list. - /// The index in this list of the start of the view. - /// The size of the view. - /// The new list view. - public virtual IList? View(int start, int count) + /// + /// Create a list view on this list containing the (first) occurrence of a particular item. + /// + /// if the item is not in this list. + /// The item to find. + /// The new list view. + public virtual IList? ViewOf(T item) + { + Validitycheck(); + if (!Contains(item, out Node n)) { - CheckRange(start, count); - Validitycheck(); - views ??= new WeakViewList>(); - - HashedLinkedList retval = (HashedLinkedList)MemberwiseClone(); - retval.underlying = underlying ?? (this); - retval.offset = offset + start; - retval.size = count; - GetPair(start - 1, start + count, out retval.startsentinel, out retval.endsentinel, - new int[] { -1, size }, new Node[] { startsentinel!, endsentinel! }); - //retval.startsentinel = start == 0 ? startsentinel : get(start - 1); - //retval.endsentinel = start + count == size ? endsentinel : get(start + count); - - //TODO: for the purpose of Dispose, we need to retain a ref to the node - retval.myWeakReference = views.Add(retval); - return retval; + return null; } - /// - /// Create a list view on this list containing the (first) occurrence of a particular item. - /// - /// if the item is not in this list. - /// The item to find. - /// The new list view. - public virtual IList? ViewOf(T item) + HashedLinkedList retval = (HashedLinkedList)MemberwiseClone(); + retval.underlying = underlying ?? (this); + retval.offset = null; + retval.startsentinel = n.prev; + retval.endsentinel = n.next; + retval.size = 1; + return retval; + + } + + /// + /// Create a list view on this list containing the last occurrence of a particular item. + /// if the item is not in this list. + /// + /// The item to find. + /// The new list view. + public virtual IList? LastViewOf(T item) + { + return ViewOf(item); + + } + + /// + /// Null if this list is not a view. + /// + /// Underlying list for view. + public virtual IList? Underlying { get { Validitycheck(); return underlying; } } + + /// + /// + /// + /// + public virtual bool IsValid => isValid; + + /// + /// + /// Offset for this list view or 0 for a underlying list. + public virtual int Offset + { + get { Validitycheck(); - if (!Contains(item, out Node n)) + + if (offset == null && underlying != null) { - return null; + //TODO: search from both ends simultaneously! + Node n = underlying.startsentinel!; + int i = 0; + while (n != startsentinel) { n = n.next!; i++; } + offset = i; } - HashedLinkedList retval = (HashedLinkedList)MemberwiseClone(); - retval.underlying = underlying ?? (this); - retval.offset = null; - retval.startsentinel = n.prev; - retval.endsentinel = n.next; - retval.size = 1; - return retval; - + return offset ?? 0; } + } - /// - /// Create a list view on this list containing the last occurrence of a particular item. - /// if the item is not in this list. - /// - /// The item to find. - /// The new list view. - public virtual IList? LastViewOf(T item) + /// + /// Slide this list view along the underlying list. + /// + /// if this list is not a view. + /// if the operation + /// would bring either end of the view outside the underlying list. + /// The signed amount to slide: positive to slide + /// towards the end. + public IList Slide(int offset) + { + if (!TrySlide(offset, size)) { - return ViewOf(item); + throw new ArgumentOutOfRangeException(nameof(offset)); + } + return this; + } + + //TODO: more test cases + /// + /// Slide this list view along the underlying list, perhaps changing its size. + /// + /// if this list is not a view. + /// if the operation + /// would bring either end of the view outside the underlying list. + /// The signed amount to slide: positive to slide + /// towards the end. + /// The new size of the view. + public IList Slide(int offset, int size) + { + if (!TrySlide(offset, size)) + { + throw new ArgumentOutOfRangeException(); } - /// - /// Null if this list is not a view. - /// - /// Underlying list for view. - public virtual IList? Underlying { get { Validitycheck(); return underlying; } } + return this; + } - /// - /// - /// - /// - public virtual bool IsValid => isValid; + /// + /// + /// + /// + /// + public virtual bool TrySlide(int offset) { return TrySlide(offset, size); } - /// - /// - /// Offset for this list view or 0 for a underlying list. - public virtual int Offset + /// + /// + /// + /// + /// + /// + public virtual bool TrySlide(int offset, int size) + { + UpdateCheck(); + if (underlying == null) { - get - { - Validitycheck(); - - if (offset == null && underlying != null) - { - //TODO: search from both ends simultaneously! - Node n = underlying.startsentinel!; - int i = 0; - while (n != startsentinel) { n = n.next!; i++; } - offset = i; - } + throw new NotAViewException("List not a view"); + } - return offset ?? 0; + if (this.offset == null) + { + try + { + GetPair(offset - 1, offset + size, out startsentinel, out endsentinel, + [-1, this.size], [startsentinel!, endsentinel!]); + //TODO: maybe-update offset field + } + catch (NullReferenceException) + { + return false; } } - - /// - /// Slide this list view along the underlying list. - /// - /// if this list is not a view. - /// if the operation - /// would bring either end of the view outside the underlying list. - /// The signed amount to slide: positive to slide - /// towards the end. - public IList Slide(int offset) + else { - if (!TrySlide(offset, size)) + if (offset + this.offset < 0 || offset + this.offset + size > underlying.size) { - throw new ArgumentOutOfRangeException(nameof(offset)); + return false; } - return this; + int oldoffset = (int)(this.offset); + GetPair(offset - 1, offset + size, out startsentinel, out endsentinel, + [-oldoffset - 1, -1, this.size, underlying.size - oldoffset], + [underlying.startsentinel!, startsentinel!, endsentinel!, underlying.endsentinel!]); } + this.size = size; + this.offset += offset; + return true; + } - //TODO: more test cases - /// - /// Slide this list view along the underlying list, perhaps changing its size. - /// - /// if this list is not a view. - /// if the operation - /// would bring either end of the view outside the underlying list. - /// The signed amount to slide: positive to slide - /// towards the end. - /// The new size of the view. - public IList Slide(int offset, int size) + + //TODO: improve the complexity of the implementation + /// + /// + /// Returns null if otherView is strictly to the left of this view + /// + /// + /// If otherView does not have the same underlying list as this + /// + public virtual IList? Span(IList otherView) + { + if ((otherView == null) || ((otherView.Underlying ?? otherView) != (underlying ?? this))) { - if (!TrySlide(offset, size)) - { - throw new ArgumentOutOfRangeException(); - } + throw new IncompatibleViewException(); + } - return this; + if (otherView.Offset + otherView.Count - Offset < 0) + { + return null; } - /// - /// - /// - /// - /// - public virtual bool TrySlide(int offset) { return TrySlide(offset, size); } + return (underlying ?? this).View(Offset, otherView.Offset + otherView.Count - Offset); + } - /// - /// - /// - /// - /// - /// - public virtual bool TrySlide(int offset, int size) + + //Question: should we swap items or move nodes around? + //The first seems much more efficient unless the items are value types + //with a large memory footprint. + //(Swapping will do count*3/2 T assignments, linking around will do + // 4*count ref assignments; note that ref assignments are more expensive + //than copying non-ref bits) + /// + /// Reverse the list so the items are in the opposite sequence order. + /// + public virtual void Reverse() + { + UpdateCheck(); + if (size == 0) { - UpdateCheck(); - if (underlying == null) - { - throw new NotAViewException("List not a view"); - } + return; + } - if (this.offset == null) + Position[]? positions = null; + int poslow = 0, poshigh = 0; + if (views != null) + { + CircularQueue? _positions = null; + foreach (HashedLinkedList view in views) { - try + if (view != this) { - GetPair(offset - 1, offset + size, out startsentinel, out endsentinel, - new int[] { -1, this.size }, new Node[] { startsentinel!, endsentinel! }); - //TODO: maybe-update offset field - } - catch (NullReferenceException) - { - return false; + switch (ViewPosition(view)) + { + case MutualViewPosition.ContainedIn: + (_positions ??= new CircularQueue()).Enqueue(new Position(view, true)); + _positions.Enqueue(new Position(view, false)); + break; + case MutualViewPosition.Overlapping: + view.Dispose(); + break; + case MutualViewPosition.Contains: + case MutualViewPosition.NonOverlapping: + break; + } } } - else + if (_positions != null) { - if (offset + this.offset < 0 || offset + this.offset + size > underlying.size) - { - return false; - } - - int oldoffset = (int)(this.offset); - GetPair(offset - 1, offset + size, out startsentinel, out endsentinel, - new int[] { -oldoffset - 1, -1, this.size, underlying.size - oldoffset }, - new Node[] { underlying.startsentinel!, startsentinel!, endsentinel!, underlying.endsentinel! }); + positions = _positions.ToArray(); + Sorting.IntroSort(positions, 0, positions.Length, PositionComparer.Default); + poshigh = positions.Length - 1; } - this.size = size; - this.offset += offset; - return true; } - - //TODO: improve the complexity of the implementation - /// - /// - /// Returns null if otherView is strictly to the left of this view - /// - /// - /// If otherView does not have the same underlying list as this - /// - public virtual IList? Span(IList otherView) + Node a = Get(0), b = Get(size - 1); + for (int i = 0; i < size / 2; i++) { - if ((otherView == null) || ((otherView.Underlying ?? otherView) != (underlying ?? this))) - { - throw new IncompatibleViewException(); - } + T swap; + swap = a.item; a.item = b.item; b.item = swap; + dict[a.item] = a; dict[b.item] = b; - if (otherView.Offset + otherView.Count - Offset < 0) + if (positions != null) { - return null; + MirrorViewSentinelsForReverse(positions, ref poslow, ref poshigh, a, b, i); } - return (underlying ?? this).View(Offset, otherView.Offset + otherView.Count - Offset); + a = a.next!; b = b.prev!; } + if (positions != null && size % 2 != 0) + { + MirrorViewSentinelsForReverse(positions, ref poslow, ref poshigh, a, b, size / 2); + } (underlying ?? this).RaiseCollectionChanged(); + } + private void MirrorViewSentinelsForReverse(Position[] positions, ref int poslow, ref int poshigh, Node a, Node b, int i) + { + int? aindex = offset + i, bindex = offset + size - 1 - i; - //Question: should we swap items or move nodes around? - //The first seems much more efficient unless the items are value types - //with a large memory footprint. - //(Swapping will do count*3/2 T assignments, linking around will do - // 4*count ref assignments; note that ref assignments are more expensive - //than copying non-ref bits) - /// - /// Reverse the list so the items are in the opposite sequence order. - /// - public virtual void Reverse() + Position pos; + + while (poslow <= poshigh && (pos = positions[poslow]).Endpoint == a) { - UpdateCheck(); - if (size == 0) + //TODO: Note: in the case og hashed linked list, if this.offset == null, but pos.View.offset!=null + //we may at this point compute this.offset and non-null values of aindex and bindex + if (pos.Left) { - return; + pos.View!.endsentinel = b.next; } - - Position[]? positions = null; - int poslow = 0, poshigh = 0; - if (views != null) + else { - CircularQueue? _positions = null; - foreach (HashedLinkedList view in views) - { - if (view != this) - { - switch (ViewPosition(view)) - { - case MutualViewPosition.ContainedIn: - (_positions ??= new CircularQueue()).Enqueue(new Position(view, true)); - _positions.Enqueue(new Position(view, false)); - break; - case MutualViewPosition.Overlapping: - view.Dispose(); - break; - case MutualViewPosition.Contains: - case MutualViewPosition.NonOverlapping: - break; - } - } - } - if (_positions != null) - { - positions = _positions.ToArray(); - Sorting.IntroSort(positions, 0, positions.Length, PositionComparer.Default); - poshigh = positions.Length - 1; - } + pos.View!.startsentinel = b.prev; + pos.View.offset = bindex; } - - Node a = Get(0), b = Get(size - 1); - for (int i = 0; i < size / 2; i++) + poslow++; + } + while (poslow < poshigh && (pos = positions[poshigh]).Endpoint == b) + { + if (pos.Left) { - T swap; - swap = a.item; a.item = b.item; b.item = swap; - dict[a.item] = a; dict[b.item] = b; - - if (positions != null) - { - MirrorViewSentinelsForReverse(positions, ref poslow, ref poshigh, a, b, i); - } - - a = a.next!; b = b.prev!; + pos.View!.endsentinel = a.next; } - if (positions != null && size % 2 != 0) + else { - MirrorViewSentinelsForReverse(positions, ref poslow, ref poshigh, a, b, size / 2); - } (underlying ?? this).RaiseCollectionChanged(); + pos.View!.startsentinel = a.prev; + pos.View.offset = aindex; + } + poshigh--; } + } + + /// + /// Check if this list is sorted according to the default sorting order + /// for the item type T, as defined by the class + /// + /// if T is not comparable + /// True if the list is sorted, else false. + public bool IsSorted() { return IsSorted(SCG.Comparer.Default); } - private void MirrorViewSentinelsForReverse(Position[] positions, ref int poslow, ref int poshigh, Node a, Node b, int i) + /// + /// Check if this list is sorted according to a specific sorting order. + /// + /// The comparer defining the sorting order. + /// True if the list is sorted, else false. + public virtual bool IsSorted(SCG.IComparer c) + { + Validitycheck(); + if (size <= 1) { - int? aindex = offset + i, bindex = offset + size - 1 - i; + return true; + } - Position pos; + Node node = startsentinel!.next!; + T prevItem = node.item; - while (poslow <= poshigh && (pos = positions[poslow]).Endpoint == a) + node = node.next!; + while (node != endsentinel) + { + if (c.Compare(prevItem, node!.item) > 0) { - //TODO: Note: in the case og hashed linked list, if this.offset == null, but pos.View.offset!=null - //we may at this point compute this.offset and non-null values of aindex and bindex - if (pos.Left) - { - pos.View!.endsentinel = b.next; - } - else - { - pos.View!.startsentinel = b.prev; - pos.View.offset = bindex; - } - poslow++; + return false; } - while (poslow < poshigh && (pos = positions[poshigh]).Endpoint == b) + else { - if (pos.Left) - { - pos.View!.endsentinel = a.next; - } - else - { - pos.View!.startsentinel = a.prev; - pos.View.offset = aindex; - } - poshigh--; + prevItem = node.item; + node = node.next!; } } - /// - /// Check if this list is sorted according to the default sorting order - /// for the item type T, as defined by the class - /// - /// if T is not comparable - /// True if the list is sorted, else false. - public bool IsSorted() { return IsSorted(SCG.Comparer.Default); } + return true; + } - /// - /// Check if this list is sorted according to a specific sorting order. - /// - /// The comparer defining the sorting order. - /// True if the list is sorted, else false. - public virtual bool IsSorted(SCG.IComparer c) + /// + /// Sort the items of the list according to the default sorting order + /// for the item type T, as defined by the Comparer[T] class. + /// (). + /// The sorting is stable. + /// + /// if T is not comparable + public virtual void Sort() { Sort(SCG.Comparer.Default); } + + // Sort the linked list using mergesort + /// + /// Sort the items of the list according to a specific sorting order. + /// The sorting is stable. + /// + /// The comparer defining the sorting order. + public virtual void Sort(SCG.IComparer c) + { + UpdateCheck(); + if (size == 0) { - Validitycheck(); - if (size <= 1) + return; + } + + DisposeOverlappingViews(false); + if (underlying != null) + { + Node cursor = startsentinel!.next!; + while (cursor != endsentinel) { - return true; + cursor.taggroup.count--; + cursor = cursor.next!; } + } + // Build a linked list of non-empty runs. + // The prev field in first node of a run points to next run's first node + Node runTail = startsentinel!.next!; + Node prevNode = startsentinel.next!; - Node node = startsentinel!.next!; - T prevItem = node.item; + endsentinel!.prev!.next = null; + while (prevNode != null) + { + Node node = prevNode.next!; - node = node.next!; - while (node != endsentinel) + while (node != null && c.Compare(prevNode.item, node.item) <= 0) + { + prevNode = node; + node = prevNode.next!; + } + + // Completed a run; prevNode is the last node of that run + prevNode.next = null; // Finish the run + runTail.prev = node; // Link it into the chain of runs + runTail = node!; + if (c.Compare(endsentinel.prev.item, prevNode.item) <= 0) { - if (c.Compare(prevItem, node!.item) > 0) + endsentinel.prev = prevNode; // Update last pointer to point to largest + } + + prevNode = node!; // Start a new run + } + + // Repeatedly merge runs two and two, until only one run remains + while (startsentinel.next!.prev != null) + { + Node run = startsentinel.next; + Node? newRunTail = null; + + while (run != null && run.prev != null) + { // At least two runs, merge + Node nextRun = run.prev.prev!; + Node newrun = MergeRuns(run, run.prev, c); + + if (newRunTail != null) { - return false; + newRunTail.prev = newrun; } else { - prevItem = node.item; - node = node.next!; + startsentinel.next = newrun; } + + newRunTail = newrun; + run = nextRun!; } - return true; + if (run != null) // Add the last run, if any + { + newRunTail!.prev = run; + } } - /// - /// Sort the items of the list according to the default sorting order - /// for the item type T, as defined by the Comparer[T] class. - /// (). - /// The sorting is stable. - /// - /// if T is not comparable - public virtual void Sort() { Sort(SCG.Comparer.Default); } + endsentinel.prev.next = endsentinel; + startsentinel.next.prev = startsentinel; - // Sort the linked list using mergesort - /// - /// Sort the items of the list according to a specific sorting order. - /// The sorting is stable. - /// - /// The comparer defining the sorting order. - public virtual void Sort(SCG.IComparer c) + //assert invariant(); + //assert isSorted(); { - UpdateCheck(); - if (size == 0) + Node cursor = startsentinel.next, end = endsentinel; + TagGroup t = GetTagGroup(startsentinel, endsentinel, out int tag, out int taglimit); + int tagdelta = taglimit / (size + 1) - tag / (size + 1); + tagdelta = tagdelta == 0 ? 1 : tagdelta; + if (underlying == null) { - return; + taggroups = 1; } - DisposeOverlappingViews(false); - if (underlying != null) + while (cursor != end) { - Node cursor = startsentinel!.next!; - while (cursor != endsentinel) - { - cursor.taggroup.count--; - cursor = cursor.next!; - } + tag = tag + tagdelta > taglimit ? taglimit : tag + tagdelta; + cursor.tag = tag; + t.count++; + cursor.taggroup = t; + cursor = cursor.next!; } - // Build a linked list of non-empty runs. - // The prev field in first node of a run points to next run's first node - Node runTail = startsentinel!.next!; - Node prevNode = startsentinel.next!; - - endsentinel!.prev!.next = null; - while (prevNode != null) + if (t != startsentinel.taggroup) { - Node node = prevNode.next!; - - while (node != null && c.Compare(prevNode.item, node.item) <= 0) - { - prevNode = node; - node = prevNode.next!; - } - - // Completed a run; prevNode is the last node of that run - prevNode.next = null; // Finish the run - runTail.prev = node; // Link it into the chain of runs - runTail = node!; - if (c.Compare(endsentinel.prev.item, prevNode.item) <= 0) - { - endsentinel.prev = prevNode; // Update last pointer to point to largest - } - - prevNode = node!; // Start a new run + t.first = startsentinel.next; } - // Repeatedly merge runs two and two, until only one run remains - while (startsentinel.next!.prev != null) + if (t != endsentinel.taggroup) { - Node run = startsentinel.next; - Node? newRunTail = null; - - while (run != null && run.prev != null) - { // At least two runs, merge - Node nextRun = run.prev.prev!; - Node newrun = MergeRuns(run, run.prev, c); - - if (newRunTail != null) - { - newRunTail.prev = newrun; - } - else - { - startsentinel.next = newrun; - } - - newRunTail = newrun; - run = nextRun!; - } + t.last = endsentinel.prev; + } - if (run != null) // Add the last run, if any - { - newRunTail!.prev = run; - } + if (tag == taglimit) + { + SplitTagGroup(t); } + } + (underlying ?? this).RaiseCollectionChanged(); + } - endsentinel.prev.next = endsentinel; - startsentinel.next.prev = startsentinel; + private static Node MergeRuns(Node run1, Node run2, SCG.IComparer c) + { + //assert run1 != null && run2 != null; + Node prev; + bool prev1; // is prev from run1? - //assert invariant(); - //assert isSorted(); - { - Node cursor = startsentinel.next, end = endsentinel; - TagGroup t = GetTagGroup(startsentinel, endsentinel, out int tag, out int taglimit); - int tagdelta = taglimit / (size + 1) - tag / (size + 1); - tagdelta = tagdelta == 0 ? 1 : tagdelta; - if (underlying == null) - { - taggroups = 1; - } + if (c.Compare(run1.item, run2.item) <= 0) + { + prev = run1; + prev1 = true; + run1 = run1.next!; + } + else + { + prev = run2; + prev1 = false; + run2 = run2.next!; + } - while (cursor != end) - { - tag = tag + tagdelta > taglimit ? taglimit : tag + tagdelta; - cursor.tag = tag; - t.count++; - cursor.taggroup = t; - cursor = cursor.next!; - } - if (t != startsentinel.taggroup) - { - t.first = startsentinel.next; - } + Node start = prev; - if (t != endsentinel.taggroup) + //assert start != null; + start.prev = null; + while (run1 != null && run2 != null) + { + if (prev1) + { + //assert prev.next == run1; + //Comparable run2item = (Comparable)run2.item; + while (run1 != null && c.Compare(run2.item, run1.item) >= 0) { - t.last = endsentinel.prev; + prev = run1; + run1 = prev.next!; } - if (tag == taglimit) - { - SplitTagGroup(t); + if (run1 != null) + { // prev.item <= run2.item < run1.item; insert run2 + prev.next = run2; + run2.prev = prev; + prev = run2; + run2 = prev.next!; + prev1 = false; } } - (underlying ?? this).RaiseCollectionChanged(); - } - - private static Node MergeRuns(Node run1, Node run2, SCG.IComparer c) - { - //assert run1 != null && run2 != null; - Node prev; - bool prev1; // is prev from run1? - - if (c.Compare(run1.item, run2.item) <= 0) - { - prev = run1; - prev1 = true; - run1 = run1.next!; - } else { - prev = run2; - prev1 = false; - run2 = run2.next!; - } - - Node start = prev; - - //assert start != null; - start.prev = null; - while (run1 != null && run2 != null) - { - if (prev1) + //assert prev.next == run2; + //Comparable run1item = (Comparable)run1.item; + while (run2 != null && c.Compare(run1.item, run2.item) > 0) { - //assert prev.next == run1; - //Comparable run2item = (Comparable)run2.item; - while (run1 != null && c.Compare(run2.item, run1.item) >= 0) - { - prev = run1; - run1 = prev.next!; - } - - if (run1 != null) - { // prev.item <= run2.item < run1.item; insert run2 - prev.next = run2; - run2.prev = prev; - prev = run2; - run2 = prev.next!; - prev1 = false; - } + prev = run2; + run2 = prev.next!; } - else - { - //assert prev.next == run2; - //Comparable run1item = (Comparable)run1.item; - while (run2 != null && c.Compare(run1.item, run2.item) > 0) - { - prev = run2; - run2 = prev.next!; - } - if (run2 != null) - { // prev.item < run1.item <= run2.item; insert run1 - prev.next = run1; - run1.prev = prev; - prev = run1; - run1 = prev.next!; - prev1 = true; - } + if (run2 != null) + { // prev.item < run1.item <= run2.item; insert run1 + prev.next = run1; + run1.prev = prev; + prev = run1; + run1 = prev.next!; + prev1 = true; } } + } - //assert !(run1 != null && prev1) && !(run2 != null && !prev1); - if (run1 != null) - { // last run2 < all of run1; attach run1 at end - prev.next = run1; - run1.prev = prev; - } - else if (run2 != null) - { // last run1 - prev.next = run2; - run2.prev = prev; - } - - return start; + //assert !(run1 != null && prev1) && !(run2 != null && !prev1); + if (run1 != null) + { // last run2 < all of run1; attach run1 at end + prev.next = run1; + run1.prev = prev; + } + else if (run2 != null) + { // last run1 + prev.next = run2; + run2.prev = prev; } - /// - /// Randomly shuffle the items of this list. - /// Will invalidate overlapping views??? - /// - public virtual void Shuffle() { Shuffle(new C5Random()); } + return start; + } + /// + /// Randomly shuffle the items of this list. + /// Will invalidate overlapping views??? + /// + public virtual void Shuffle() { Shuffle(new C5Random()); } - /// - /// Shuffle the items of this list according to a specific random source. - /// Will invalidate overlapping views??? - /// - /// The random source. - public virtual void Shuffle(Random rnd) + + /// + /// Shuffle the items of this list according to a specific random source. + /// Will invalidate overlapping views??? + /// + /// The random source. + public virtual void Shuffle(Random rnd) + { + UpdateCheck(); + if (size == 0) { - UpdateCheck(); - if (size == 0) - { - return; - } + return; + } - DisposeOverlappingViews(false); - ArrayList a = new ArrayList(); - a.AddAll(this); - a.Shuffle(rnd); - Node cursor = startsentinel!.next!; - int j = 0; - while (cursor != endsentinel) - { - cursor.item = a[j++]; - dict[cursor.item] = cursor; - cursor = cursor.next!; - } - (underlying ?? this).RaiseCollectionChanged(); + DisposeOverlappingViews(false); + ArrayList a = new(); + a.AddAll(this); + a.Shuffle(rnd); + Node cursor = startsentinel!.next!; + int j = 0; + while (cursor != endsentinel) + { + cursor.item = a[j++]; + dict[cursor.item] = cursor; + cursor = cursor.next!; } + (underlying ?? this).RaiseCollectionChanged(); + } - #endregion + #endregion - #region IIndexed Members + #region IIndexed Members - /// - /// . - /// - /// The directed collection of items in a specific index interval. - /// The low index of the interval (inclusive). - /// The size of the range. - public IDirectedCollectionValue this[int start, int count] + /// + /// . + /// + /// The directed collection of items in a specific index interval. + /// The low index of the interval (inclusive). + /// The size of the range. + public IDirectedCollectionValue this[int start, int count] + { + get { - get - { - Validitycheck(); - CheckRange(start, count); - return new Range(this, start, count, true); - } + Validitycheck(); + CheckRange(start, count); + return new Range(this, start, count, true); } + } - /// - /// Searches for an item in the list going forwards from the start. - /// - /// Item to search for. - /// Index of item from start. - public virtual int IndexOf(T item) + /// + /// Searches for an item in the list going forwards from the start. + /// + /// Item to search for. + /// Index of item from start. + public virtual int IndexOf(T item) + { + Validitycheck(); + if (!dict.Find(ref item, out Node node) || !InsideView(node)) { - Validitycheck(); - if (!dict.Find(ref item, out Node node) || !InsideView(node)) - { - return ~size; - } - - node = startsentinel!.next!; - int index = 0; - if (Find(item, ref node, ref index)) - { - return index; - } - else - { - return ~size; - } + return ~size; } - /// - /// Searches for an item in the list going backwards from the end. - /// - /// Item to search for. - /// Index of item from the end. - public virtual int LastIndexOf(T item) + node = startsentinel!.next!; + int index = 0; + if (Find(item, ref node, ref index)) { - return IndexOf(item); - + return index; } - - /// - /// Remove the item at a specific position of the list. - /// if i is negative or - /// >= the size of the collection. - /// - /// The index of the item to remove. - /// The removed item. - public virtual T RemoveAt(int i) + else { - UpdateCheck(); - T retval = Remove(Get(i)); - dict.Remove(retval); - if (ActiveEvents != EventType.None) - { - (underlying ?? this).RaiseForRemoveAt(Offset + i, retval); - } - - return retval; + return ~size; } + } - /// - /// Remove all items in an index interval. - /// ???. - /// - /// The index of the first item to remove. - /// The number of items to remove. - public virtual void RemoveInterval(int start, int count) + /// + /// Searches for an item in the list going backwards from the end. + /// + /// Item to search for. + /// Index of item from the end. + public virtual int LastIndexOf(T item) + { + return IndexOf(item); + + } + + /// + /// Remove the item at a specific position of the list. + /// if i is negative or + /// >= the size of the collection. + /// + /// The index of the item to remove. + /// The removed item. + public virtual T RemoveAt(int i) + { + UpdateCheck(); + T retval = Remove(Get(i)); + dict.Remove(retval); + if (ActiveEvents != EventType.None) { - UpdateCheck(); - CheckRange(start, count); - if (count == 0) - { - return; - } + (underlying ?? this).RaiseForRemoveAt(Offset + i, retval); + } - View(start, count)!.Clear(); + return retval; + } + /// + /// Remove all items in an index interval. + /// ???. + /// + /// The index of the first item to remove. + /// The number of items to remove. + public virtual void RemoveInterval(int start, int count) + { + UpdateCheck(); + CheckRange(start, count); + if (count == 0) + { + return; } - private void RaiseForRemoveInterval(int start, int count) + View(start, count)!.Clear(); + + } + + private void RaiseForRemoveInterval(int start, int count) + { + if (ActiveEvents != 0) { - if (ActiveEvents != 0) - { - RaiseCollectionCleared(size == 0, count, start); - RaiseCollectionChanged(); - } + RaiseCollectionCleared(size == 0, count, start); + RaiseCollectionChanged(); } - #endregion + } + #endregion - #region ISequenced Members + #region ISequenced Members - /// - /// - /// - /// - public override int GetSequencedHashCode() { Validitycheck(); return base.GetSequencedHashCode(); } + /// + /// + /// + /// + public override int GetSequencedHashCode() { Validitycheck(); return base.GetSequencedHashCode(); } - /// - /// - /// - /// - /// - public override bool SequencedEquals(ISequenced that) { Validitycheck(); return base.SequencedEquals(that); } + /// + /// + /// + /// + /// + public override bool SequencedEquals(ISequenced that) { Validitycheck(); return base.SequencedEquals(that); } - #endregion + #endregion - #region IDirectedCollection Members + #region IDirectedCollection Members - /// - /// Create a collection containing the same items as this collection, but - /// whose enumerator will enumerate the items backwards. The new collection - /// will become invalid if the original is modified. Method typically used as in - /// foreach (T x in coll.Backwards()) {...} - /// - /// The backwards collection. - public override IDirectedCollectionValue Backwards() - { return this[0, size].Backwards(); } + /// + /// Create a collection containing the same items as this collection, but + /// whose enumerator will enumerate the items backwards. The new collection + /// will become invalid if the original is modified. Method typically used as in + /// foreach (T x in coll.Backwards()) {...} + /// + /// The backwards collection. + public override IDirectedCollectionValue Backwards() + { return this[0, size].Backwards(); } - #endregion + #endregion - #region IDirectedEnumerable Members + #region IDirectedEnumerable Members - IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } + IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } - #endregion + #endregion - #region IEditableCollection Members + #region IEditableCollection Members - /// - /// The value is symbolic indicating the type of asymptotic complexity - /// in terms of the size of this collection (worst-case or amortized as - /// relevant). - /// - /// Speed.Linear - public virtual Speed ContainsSpeed => Speed.Constant; + /// + /// The value is symbolic indicating the type of asymptotic complexity + /// in terms of the size of this collection (worst-case or amortized as + /// relevant). + /// + /// Speed.Linear + public virtual Speed ContainsSpeed => Speed.Constant; - /// - /// Performs a check for view validity before calling base.GetUnsequencedHashCode() - /// - /// - public override int GetUnsequencedHashCode() - { Validitycheck(); return base.GetUnsequencedHashCode(); } + /// + /// Performs a check for view validity before calling base.GetUnsequencedHashCode() + /// + /// + public override int GetUnsequencedHashCode() + { Validitycheck(); return base.GetUnsequencedHashCode(); } - /// - /// - /// - /// - /// - public override bool UnsequencedEquals(ICollection that) - { Validitycheck(); return base.UnsequencedEquals(that); } + /// + /// + /// + /// + /// + public override bool UnsequencedEquals(ICollection that) + { Validitycheck(); return base.UnsequencedEquals(that); } - /// - /// Check if this collection contains (an item equivalent to according to the - /// itemequalityComparer) a particular value. - /// - /// The value to check for. - /// True if the items is in this collection. - public virtual bool Contains(T item) - { - Validitycheck(); - return Contains(item, out _); - } + /// + /// Check if this collection contains (an item equivalent to according to the + /// itemequalityComparer) a particular value. + /// + /// The value to check for. + /// True if the items is in this collection. + public virtual bool Contains(T item) + { + Validitycheck(); + return Contains(item, out _); + } - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, return in the ref argument (a - /// binary copy of) the actual value found. - /// - /// The value to look for. - /// True if the items is in this collection. - public virtual bool Find(ref T item) + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, return in the ref argument (a + /// binary copy of) the actual value found. + /// + /// The value to look for. + /// True if the items is in this collection. + public virtual bool Find(ref T item) + { + Validitycheck(); + if (Contains(item, out Node node)) { item = node.item; return true; } + return false; + } + + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// to with a binary copy of the supplied value. Will update a single item. + /// + /// Value to update. + /// True if the item was found and hence updated. + public virtual bool Update(T item) { return Update(item, out _); } + + /// + /// + /// + /// + /// + /// + public virtual bool Update(T item, out T olditem) + { + UpdateCheck(); + + if (Contains(item, out Node node)) { - Validitycheck(); - if (Contains(item, out Node node)) { item = node.item; return true; } - return false; + olditem = node.item; + node.item = item; + //Avoid clinging onto a reference to olditem via dict! + dict.Update(item, node); + (underlying ?? this).RaiseForUpdate(item, olditem); + return true; } - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// to with a binary copy of the supplied value. Will update a single item. - /// - /// Value to update. - /// True if the item was found and hence updated. - public virtual bool Update(T item) { return Update(item, out _); } + olditem = default; + return false; + } - /// - /// - /// - /// - /// - /// - public virtual bool Update(T item, out T olditem) + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, return in the ref argument (a + /// binary copy of) the actual value found. Else, add the item to the collection. + /// + /// The value to look for. + /// True if the item was found (hence not added). + public virtual bool FindOrAdd(ref T item) + { + UpdateCheck(); + //This is an extended myinsert: + Node node = new(item); + if (!dict.FindOrAdd(item, ref node)) { - UpdateCheck(); - - if (Contains(item, out Node node)) - { - olditem = node.item; - node.item = item; - //Avoid clinging onto a reference to olditem via dict! - dict.Update(item, node); - (underlying ?? this).RaiseForUpdate(item, olditem); - return true; - } - - olditem = default; + InsertNode(true, endsentinel!, node); + (underlying ?? this).RaiseForAdd(item); return false; } + if (!InsideView(node)) + { + throw new ArgumentException("Item alredy in indexed list but outside view"); + } - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, return in the ref argument (a - /// binary copy of) the actual value found. Else, add the item to the collection. - /// - /// The value to look for. - /// True if the item was found (hence not added). - public virtual bool FindOrAdd(ref T item) + item = node.item; + return true; + + } + + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// to with a binary copy of the supplied value; else add the value to the collection. + /// + /// Value to add or update. + /// True if the item was found and updated (hence not added). + public virtual bool UpdateOrAdd(T item) { return UpdateOrAdd(item, out _); } + + /// + /// + /// + /// + /// + /// + public virtual bool UpdateOrAdd(T item, out T olditem) + { + UpdateCheck(); + Node node = new(item); + //NOTE: it is hard to do this without double access to the dictionary + //in the update case + if (dict.FindOrAdd(item, ref node)) { - UpdateCheck(); - //This is an extended myinsert: - Node node = new Node(item); - if (!dict.FindOrAdd(item, ref node)) - { - InsertNode(true, endsentinel!, node); - (underlying ?? this).RaiseForAdd(item); - return false; - } if (!InsideView(node)) { - throw new ArgumentException("Item alredy in indexed list but outside view"); + throw new ArgumentException("Item in indexed list but outside view"); } - item = node.item; + olditem = node.item; + //Avoid clinging onto a reference to olditem via dict! + dict.Update(item, node); + node.item = item; + (underlying ?? this).RaiseForUpdate(item, olditem); return true; - } + InsertNode(true, endsentinel!, node); + (underlying ?? this).RaiseForAdd(item); - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// to with a binary copy of the supplied value; else add the value to the collection. - /// - /// Value to add or update. - /// True if the item was found and updated (hence not added). - public virtual bool UpdateOrAdd(T item) { return UpdateOrAdd(item, out _); } + olditem = default; + return false; + } - /// - /// - /// - /// - /// - /// - public virtual bool UpdateOrAdd(T item, out T olditem) + /// + /// Remove a particular item from this collection. Since the collection has bag + /// semantics only one copy equivalent to the supplied item is removed. + /// + /// The value to remove. + /// True if the item was found (and removed). + public virtual bool Remove(T item) + { + UpdateCheck(); + if (!DictRemove(item, out Node node)) { - UpdateCheck(); - Node node = new Node(item); - //NOTE: it is hard to do this without double access to the dictionary - //in the update case - if (dict.FindOrAdd(item, ref node)) - { - if (!InsideView(node)) - { - throw new ArgumentException("Item in indexed list but outside view"); - } + return false; + } - olditem = node.item; - //Avoid clinging onto a reference to olditem via dict! - dict.Update(item, node); - node.item = item; - (underlying ?? this).RaiseForUpdate(item, olditem); - return true; - } - InsertNode(true, endsentinel!, node); - (underlying ?? this).RaiseForAdd(item); + T removeditem = Remove(node); + (underlying ?? this).RaiseForRemove(removeditem); + return true; + } - olditem = default; + /// + /// Remove a particular item from this collection if found (only one copy). + /// If an item was removed, report a binary copy of the actual item removed in + /// the argument. + /// + /// The value to remove on input. + /// The value removed. + /// True if the item was found (and removed). + public virtual bool Remove(T item, out T removeditem) + { + UpdateCheck(); + + if (!DictRemove(item, out Node node)) + { + removeditem = default; return false; } + removeditem = node.item; + Remove(node); + (underlying ?? this).RaiseForRemove(removeditem); + return true; + } - /// - /// Remove a particular item from this collection. Since the collection has bag - /// semantics only one copy equivalent to the supplied item is removed. - /// - /// The value to remove. - /// True if the item was found (and removed). - public virtual bool Remove(T item) + /// + /// Remove all items in another collection from this one, taking multiplicities into account. + /// Always removes from the front of the list. + /// + /// The asymptotic running time complexity of this method is O(n+m+v*log(v)), + /// where n is the size of this list, m is the size of the + /// items collection and v is the number of views. + /// The method will temporarily allocate memory of size O(m+v). + /// + /// + /// The items to remove. + public virtual void RemoveAll(SCG.IEnumerable items) + { + UpdateCheck(); + if (size == 0) { - UpdateCheck(); - if (!DictRemove(item, out Node node)) - { - return false; - } - - T removeditem = Remove(node); - (underlying ?? this).RaiseForRemove(removeditem); - return true; + return; } - /// - /// Remove a particular item from this collection if found (only one copy). - /// If an item was removed, report a binary copy of the actual item removed in - /// the argument. - /// - /// The value to remove on input. - /// The value removed. - /// True if the item was found (and removed). - public virtual bool Remove(T item, out T removeditem) + RaiseForRemoveAllHandler raiseHandler = new(underlying ?? this); + bool mustFire = raiseHandler.MustFire; + foreach (T item in items) { - UpdateCheck(); - - if (!DictRemove(item, out Node node)) + if (DictRemove(item, out Node node)) { - removeditem = default; - return false; + if (mustFire) + { + raiseHandler.Remove(node.item); + } + + Remove(node); } - removeditem = node.item; - Remove(node); - (underlying ?? this).RaiseForRemove(removeditem); - return true; } - /// - /// Remove all items in another collection from this one, taking multiplicities into account. - /// Always removes from the front of the list. - /// - /// The asymptotic running time complexity of this method is O(n+m+v*log(v)), - /// where n is the size of this list, m is the size of the - /// items collection and v is the number of views. - /// The method will temporarily allocate memory of size O(m+v). - /// - /// - /// The items to remove. - public virtual void RemoveAll(SCG.IEnumerable items) + raiseHandler.Raise(); + } + + /* + /// + /// + /// + /// + void RemoveAll(Func predicate) + { + updatecheck(); + if (size == 0) + return; + RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); + bool mustFire = raiseHandler.MustFire; { - UpdateCheck(); - if (size == 0) - { - return; - } + Node n = startsentinel!.next!; - RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); - bool mustFire = raiseHandler.MustFire; - foreach (T item in items) + while (n != endsentinel) { - if (DictRemove(item, out Node node)) + bool removeIt = predicate(n!.item); + updatecheck(); + if (removeIt) { + dict.Remove(n.item); + remove(n); if (mustFire) - { - raiseHandler.Remove(node.item); - } - - Remove(node); + raiseHandler.Remove(n.item); } - } - raiseHandler.Raise(); + n = n.next!; + } } - /* - /// - /// - /// - /// - void RemoveAll(Func predicate) - { - updatecheck(); - if (size == 0) - return; - RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); - bool mustFire = raiseHandler.MustFire; - { - Node n = startsentinel!.next!; - - while (n != endsentinel) - { - bool removeIt = predicate(n!.item); - updatecheck(); - if (removeIt) - { - dict.Remove(n.item); - remove(n); - if (mustFire) - raiseHandler.Remove(n.item); - } - - n = n.next!; - } - } + raiseHandler.Raise(); + } + */ - raiseHandler.Raise(); + /// + /// Remove all items from this collection. + /// + public virtual void Clear() + { + UpdateCheck(); + if (size == 0) + { + return; } - */ - /// - /// Remove all items from this collection. - /// - public virtual void Clear() + int oldsize = size; + if (underlying == null) { - UpdateCheck(); - if (size == 0) + dict.Clear(); + } + else + { + foreach (T item in this) { - return; + dict.Remove(item); } + } - int oldsize = size; - if (underlying == null) - { - dict.Clear(); - } - else - { - foreach (T item in this) - { - dict.Remove(item); - } - } + ClearInnner(); + (underlying ?? this).RaiseForRemoveInterval(Offset, oldsize); + } - ClearInnner(); - (underlying ?? this).RaiseForRemoveInterval(Offset, oldsize); + private void ClearInnner() + { + if (size == 0) + { + return; } - private void ClearInnner() + //TODO: mix with tag maintenance to only run through list once? + ViewHandler viewHandler = new(this); + if (viewHandler.viewCount > 0) { - if (size == 0) + int removed = 0; + Node n = startsentinel!.next!; + viewHandler.SkipEndpoints(0, n); + while (n != endsentinel) { - return; + removed++; + n = n.next!; + viewHandler.UpdateViewSizesAndCounts(removed, n!); } - - //TODO: mix with tag maintenance to only run through list once? - ViewHandler viewHandler = new ViewHandler(this); - if (viewHandler.viewCount > 0) + viewHandler.UpdateSentinels(endsentinel!, startsentinel, endsentinel!); + if (underlying != null) { - int removed = 0; - Node n = startsentinel!.next!; - viewHandler.SkipEndpoints(0, n); - while (n != endsentinel) - { - removed++; - n = n.next!; - viewHandler.UpdateViewSizesAndCounts(removed, n!); - } - viewHandler.UpdateSentinels(endsentinel!, startsentinel, endsentinel!); - if (underlying != null) - { - viewHandler.UpdateViewSizesAndCounts(removed, underlying.endsentinel!); - } + viewHandler.UpdateViewSizesAndCounts(removed, underlying.endsentinel!); } + } - if (underlying != null) - { - Node n = startsentinel!.next!; + if (underlying != null) + { + Node n = startsentinel!.next!; - while (n != endsentinel) - { - n.next!.prev = startsentinel; - startsentinel.next = n.next; - RemoveFromTagGroup(n); - n = n.next; - } - } - else + while (n != endsentinel) { - taggroups = 0; + n.next!.prev = startsentinel; + startsentinel.next = n.next; + RemoveFromTagGroup(n); + n = n.next; } + } + else + { + taggroups = 0; + } - endsentinel!.prev = startsentinel; - startsentinel!.next = endsentinel; - if (underlying != null) - { - underlying.size -= size; - } + endsentinel!.prev = startsentinel; + startsentinel!.next = endsentinel; + if (underlying != null) + { + underlying.size -= size; + } + + size = 0; + } - size = 0; + /// + /// Remove all items not in some other collection from this one, taking multiplicities into account. + /// The asymptotic running time complexity of this method is O(n+m+v*log(v)), + /// where n is the size of this collection, m is the size of the + /// items collection and v is the number of views. + /// The method will temporarily allocate memory of size O(m+v). The stated complexity + /// holds under the assumption that the itemequalityComparer of this list is well-behaved. + /// + /// + /// The items to retain. + public virtual void RetainAll(SCG.IEnumerable items) + { + UpdateCheck(); + if (size == 0) + { + return; } - /// - /// Remove all items not in some other collection from this one, taking multiplicities into account. - /// The asymptotic running time complexity of this method is O(n+m+v*log(v)), - /// where n is the size of this collection, m is the size of the - /// items collection and v is the number of views. - /// The method will temporarily allocate memory of size O(m+v). The stated complexity - /// holds under the assumption that the itemequalityComparer of this list is well-behaved. - /// - /// - /// The items to retain. - public virtual void RetainAll(SCG.IEnumerable items) + RaiseForRemoveAllHandler raiseHandler = new(underlying ?? this); + bool mustFire = raiseHandler.MustFire; + /*if (underlying == null) { - UpdateCheck(); - if (size == 0) + HashDictionary newdict = new HashDictionary(itemequalityComparer); + foreach (T item in items) + { + Node node; + + if (dict.Remove(item, out node)) + newdict.Add(item, node); + } + foreach (System.Collections.Generic.KeyValuePair pair in dict) + { + Node n = pair.Value; + fixViewsBeforeSingleRemove(n, 117); + Node p = n.prev, s = n.next; s.prev = p; p.next = s; + removefromtaggroup(n); + } + dict = newdict; + size = dict.Count; + //For a small number of items to retain it might be faster to + //iterate through the list and splice out the chunks not needed + } + else*/ + { + HashSet toremove = new(itemEqualityComparer); + + foreach (T item in this) { - return; + toremove.Add(item); } - RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); - bool mustFire = raiseHandler.MustFire; - /*if (underlying == null) + foreach (T item in items) { - HashDictionary newdict = new HashDictionary(itemequalityComparer); - foreach (T item in items) - { - Node node; - - if (dict.Remove(item, out node)) - newdict.Add(item, node); - } - foreach (System.Collections.Generic.KeyValuePair pair in dict) - { - Node n = pair.Value; - fixViewsBeforeSingleRemove(n, 117); - Node p = n.prev, s = n.next; s.prev = p; p.next = s; - removefromtaggroup(n); - } - dict = newdict; - size = dict.Count; - //For a small number of items to retain it might be faster to - //iterate through the list and splice out the chunks not needed + toremove.Remove(item); } - else*/ - { - HashSet toremove = new HashSet(itemequalityComparer); - - foreach (T item in this) - { - toremove.Add(item); - } - foreach (T item in items) - { - toremove.Remove(item); - } + Node n = startsentinel!.next!; - Node n = startsentinel!.next!; - - while (n != endsentinel && toremove.Count > 0) + while (n != endsentinel && toremove.Count > 0) + { + if (toremove.Contains(n.item)) { - if (toremove.Contains(n.item)) + dict.Remove(n.item); + Remove(n); + if (mustFire) { - dict.Remove(n.item); - Remove(n); - if (mustFire) - { - raiseHandler.Remove(n.item); - } + raiseHandler.Remove(n.item); } - - n = n.next!; } - } - raiseHandler.Raise(); + n = n.next!; + } } - /* - /// - /// - /// - /// - void RetainAll(Func predicate) + raiseHandler.Raise(); + } + + /* + /// + /// + /// + /// + void RetainAll(Func predicate) + { + updatecheck(); + if (size == 0) + return; + RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); + bool mustFire = raiseHandler.MustFire; { - updatecheck(); - if (size == 0) - return; - RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); - bool mustFire = raiseHandler.MustFire; - { - Node n = startsentinel!.next!; + Node n = startsentinel!.next!; - while (n != endsentinel) + while (n != endsentinel) + { + bool removeIt = !predicate(n!.item); + updatecheck(); + if (removeIt) { - bool removeIt = !predicate(n!.item); - updatecheck(); - if (removeIt) - { - dict.Remove(n.item); - remove(n); - if (mustFire) - raiseHandler.Remove(n.item); - } - - n = n.next!; + dict.Remove(n.item); + remove(n); + if (mustFire) + raiseHandler.Remove(n.item); } + + n = n.next!; } + } - raiseHandler.Raise(); - } */ + raiseHandler.Raise(); + } */ - /// - /// Check if this collection contains all the values in another collection - /// with respect to multiplicities. - /// - /// The - /// True if all values in itemsis in this collection. - public virtual bool ContainsAll(SCG.IEnumerable items) + /// + /// Check if this collection contains all the values in another collection + /// with respect to multiplicities. + /// + /// The + /// True if all values in itemsis in this collection. + public virtual bool ContainsAll(SCG.IEnumerable items) + { + Validitycheck(); + foreach (T item in items) { - Validitycheck(); - foreach (T item in items) + if (!Contains(item, out _)) { - if (!Contains(item, out _)) - { - return false; - } + return false; } + } - return true; + return true; - } + } - /// - /// Create a new list consisting of the items of this list satisfying a - /// certain predicate. - /// - /// The filter delegate defining the predicate. - /// The new list. - public IList FindAll(Func filter) - { - Validitycheck(); - int stamp = this.stamp; - HashedLinkedList retval = new HashedLinkedList(); - Node cursor = startsentinel!.next!; - Node mcursor = retval.startsentinel!; - double tagdelta = int.MaxValue / (size + 1.0); - int count = 1; - TagGroup taggroup = new TagGroup(); - retval.taggroups = 1; - while (cursor != endsentinel) - { - bool found = filter(cursor.item); - ModifyCheck(stamp); - if (found) - { - mcursor.next = new Node(cursor.item, mcursor, null); - mcursor = mcursor.next; - retval.size++; - retval.dict.Add(cursor.item, mcursor); - mcursor.taggroup = taggroup; - mcursor.tag = (int)(tagdelta * count++); - } - cursor = cursor.next!; - } - if (retval.size > 0) - { - taggroup.count = retval.size; - taggroup.first = retval.startsentinel!.next!; - taggroup.last = mcursor!; + /// + /// Create a new list consisting of the items of this list satisfying a + /// certain predicate. + /// + /// The filter delegate defining the predicate. + /// The new list. + public IList FindAll(Func filter) + { + Validitycheck(); + int stamp = this.stamp; + HashedLinkedList retval = new(); + Node cursor = startsentinel!.next!; + Node mcursor = retval.startsentinel!; + double tagdelta = int.MaxValue / (size + 1.0); + int count = 1; + TagGroup taggroup = new(); + retval.taggroups = 1; + while (cursor != endsentinel) + { + bool found = filter(cursor.item); + ModifyCheck(stamp); + if (found) + { + mcursor.next = new Node(cursor.item, mcursor, null); + mcursor = mcursor.next; + retval.size++; + retval.dict.Add(cursor.item, mcursor); + mcursor.taggroup = taggroup; + mcursor.tag = (int)(tagdelta * count++); } - retval.endsentinel!.prev = mcursor; - mcursor.next = retval.endsentinel; - return retval; + cursor = cursor.next!; } + if (retval.size > 0) + { + taggroup.count = retval.size; + taggroup.first = retval.startsentinel!.next!; + taggroup.last = mcursor!; + } + retval.endsentinel!.prev = mcursor; + mcursor.next = retval.endsentinel; + return retval; + } - /// - /// Count the number of items of the collection equal to a particular value. - /// Returns 0 if and only if the value is not in the collection. - /// - /// The value to count. - /// The number of copies found. - public virtual int ContainsCount(T item) - { - return Contains(item) ? 1 : 0; + /// + /// Count the number of items of the collection equal to a particular value. + /// Returns 0 if and only if the value is not in the collection. + /// + /// The value to count. + /// The number of copies found. + public virtual int ContainsCount(T item) + { + return Contains(item) ? 1 : 0; - } + } - /// - /// - /// - /// - public virtual ICollectionValue UniqueItems() - { - return this; + /// + /// + /// + /// + public virtual ICollectionValue UniqueItems() + { + return this; - } + } - /// - /// - /// - /// - public virtual ICollectionValue> ItemMultiplicities() - { - return new MultiplicityOne(this); + /// + /// + /// + /// + public virtual ICollectionValue> ItemMultiplicities() + { + return new MultiplicityOne(this); - } + } - /// - /// Remove all items equivalent to a given value. - /// The asymptotic complexity of this method is O(n+v*log(v)), - /// where n is the size of the collection and v - /// is the number of views. - /// - /// - /// The value to remove. - public virtual void RemoveAllCopies(T item) - { - Remove(item); + /// + /// Remove all items equivalent to a given value. + /// The asymptotic complexity of this method is O(n+v*log(v)), + /// where n is the size of the collection and v + /// is the number of views. + /// + /// + /// The value to remove. + public virtual void RemoveAllCopies(T item) + { + Remove(item); - } + } - #endregion + #endregion - #region ICollectionValue Members + #region ICollectionValue Members - /// - /// - /// - /// The number of items in this collection - public override int Count { get { Validitycheck(); return size; } } + /// + /// + /// + /// The number of items in this collection + public override int Count { get { Validitycheck(); return size; } } - /// - /// Choose some item of this collection. - /// - /// if collection is empty. - /// - public override T Choose() { return First; } + /// + /// Choose some item of this collection. + /// + /// if collection is empty. + /// + public override T Choose() { return First; } - /// - /// Create an enumerable, enumerating the items of this collection that satisfies - /// a certain condition. - /// - /// The T->bool filter delegate defining the condition - /// The filtered enumerable - public override SCG.IEnumerable Filter(Func filter) { Validitycheck(); return base.Filter(filter); } + /// + /// Create an enumerable, enumerating the items of this collection that satisfies + /// a certain condition. + /// + /// The T->bool filter delegate defining the condition + /// The filtered enumerable + public override SCG.IEnumerable Filter(Func filter) { Validitycheck(); return base.Filter(filter); } - #endregion + #endregion - #region IEnumerable Members - /// - /// Create an enumerator for the collection - /// - /// The enumerator - public override SCG.IEnumerator GetEnumerator() - { - Validitycheck(); - Node cursor = startsentinel!.next!; - int enumeratorstamp = underlying != null ? underlying.stamp : stamp; + #region IEnumerable Members + /// + /// Create an enumerator for the collection + /// + /// The enumerator + public override SCG.IEnumerator GetEnumerator() + { + Validitycheck(); + Node cursor = startsentinel!.next!; + int enumeratorstamp = underlying != null ? underlying.stamp : stamp; - while (cursor != endsentinel) - { - ModifyCheck(enumeratorstamp); - yield return cursor!.item; - cursor = cursor.next!; - } + while (cursor != endsentinel) + { + ModifyCheck(enumeratorstamp); + yield return cursor!.item; + cursor = cursor.next!; } + } - #endregion + #endregion - #region IExtensible Members - /// - /// Add an item to this collection if possible. - /// - /// The item to add. - /// True. - public virtual bool Add(T item) + #region IExtensible Members + /// + /// Add an item to this collection if possible. + /// + /// The item to add. + /// True. + public virtual bool Add(T item) + { + UpdateCheck(); + Node node = new(item); + if (!dict.FindOrAdd(item, ref node)) { - UpdateCheck(); - Node node = new Node(item); - if (!dict.FindOrAdd(item, ref node)) - { - InsertNode(true, endsentinel!, node); - (underlying ?? this).RaiseForAdd(item); - return true; - } - return false; - + InsertNode(true, endsentinel!, node); + (underlying ?? this).RaiseForAdd(item); + return true; } + return false; - /// - /// - /// - /// True since this collection has bag semantics. - public virtual bool AllowsDuplicates => false; + } + + /// + /// + /// + /// True since this collection has bag semantics. + public virtual bool AllowsDuplicates => false; + + /// + /// By convention this is true for any collection with set semantics. + /// + /// True if only one representative of a group of equal items + /// is kept in the collection together with the total count. + public virtual bool DuplicatesByCounting => true; - /// - /// By convention this is true for any collection with set semantics. - /// - /// True if only one representative of a group of equal items - /// is kept in the collection together with the total count. - public virtual bool DuplicatesByCounting => true; + /// + /// Add the elements from another collection with a more specialized item type + /// to this collection. + /// + /// The items to add + public virtual void AddAll(SCG.IEnumerable items) + { - /// - /// Add the elements from another collection with a more specialized item type - /// to this collection. - /// - /// The items to add - public virtual void AddAll(SCG.IEnumerable items) + UpdateCheck(); + int added = 0; + Node pred = endsentinel!.prev!; + foreach (var item in items) { - - UpdateCheck(); - int added = 0; - Node pred = endsentinel!.prev!; - foreach (var item in items) - { - Node node = new Node(item); - if (!dict.FindOrAdd(item, ref node)) - { - InsertNode(false, endsentinel, node); - added++; - } - } - if (added > 0) + Node node = new(item); + if (!dict.FindOrAdd(item, ref node)) { - FixViewsAfterInsert(endsentinel, pred!, added); - RaiseForInsertAll(pred!, size - added, added, false); + InsertNode(false, endsentinel, node); + added++; } - + } + if (added > 0) + { + FixViewsAfterInsert(endsentinel, pred!, added); + RaiseForInsertAll(pred!, size - added, added, false); } - #endregion + } + + #endregion - #region Diagnostic + #region Diagnostic - private bool CheckViews() + private bool CheckViews() + { + if (underlying != null) { - if (underlying != null) + throw new InternalException("checkViews() called on a view"); + } + + if (views == null) + { + return true; + } + + bool retval = true; + + Node[] nodes = new Node[size + 2]; + int i = 0; + Node n = startsentinel!; + while (n != null) + { + nodes[i++] = n; + n = n.next!; + } + //Logger.Log("###"); + foreach (HashedLinkedList view in views) + { + if (!view.isValid) { - throw new InternalException("checkViews() called on a view"); + Logger.Log(string.Format("Invalid view(hash {0}, offset {1}, size {2})", + view.GetHashCode(), view.offset, view.size)); + retval = false; + continue; } - - if (views == null) + if (view.Offset > size || view.Offset < 0) { - return true; + Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), Offset > underlying.size ({3})", + view.GetHashCode(), view.offset, view.size, size)); + retval = false; } - - bool retval = true; - - Node[] nodes = new Node[size + 2]; - int i = 0; - Node n = startsentinel!; - while (n != null) + else if (view.startsentinel != nodes[view.Offset]) { - nodes[i++] = n; - n = n.next!; + Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), startsentinel {3} should be {4}", + view.GetHashCode(), view.offset, view.size, + view.startsentinel + " " + view.startsentinel!.GetHashCode(), + nodes[view.Offset] + " " + nodes[view.Offset].GetHashCode())); + retval = false; } - //Logger.Log("###"); - foreach (HashedLinkedList view in views) + if (view.Offset + view.size > size || view.Offset + view.size < 0) { - if (!view.isValid) - { - Logger.Log(string.Format("Invalid view(hash {0}, offset {1}, size {2})", - view.GetHashCode(), view.offset, view.size)); - retval = false; - continue; - } - if (view.Offset > size || view.Offset < 0) - { - Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), Offset > underlying.size ({3})", - view.GetHashCode(), view.offset, view.size, size)); - retval = false; - } - else if (view.startsentinel != nodes[view.Offset]) - { - Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), startsentinel {3} should be {4}", - view.GetHashCode(), view.offset, view.size, - view.startsentinel + " " + view.startsentinel!.GetHashCode(), - nodes[view.Offset] + " " + nodes[view.Offset].GetHashCode())); - retval = false; - } - if (view.Offset + view.size > size || view.Offset + view.size < 0) - { - Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), end index > underlying.size ({3})", - view.GetHashCode(), view.offset, view.size, size)); - retval = false; - } - else if (view.endsentinel != nodes[view.Offset + view.size + 1]) - { - Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), endsentinel {3} should be {4}", - view.GetHashCode(), view.offset, view.size, - view.endsentinel + " " + view.endsentinel!.GetHashCode(), - nodes[view.Offset + view.size + 1] + " " + nodes[view.Offset + view.size + 1].GetHashCode())); - retval = false; - } - if (view.views != views) - { - Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), wrong views list {3} <> {4}", - view.GetHashCode(), view.offset, view.size, view.views!.GetHashCode(), views.GetHashCode())); - retval = false; - } - if (view.underlying != this) - { - Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), wrong underlying {3} <> this {4}", - view.GetHashCode(), view.offset, view.size, view.underlying!.GetHashCode(), GetHashCode())); - retval = false; - } - if (view.stamp != stamp) - { - //Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), wrong stamp view:{2} underlying: {3}", view.GetHashCode(),view.offset, view.size, view.stamp, stamp)); - //retval = false; - } + Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), end index > underlying.size ({3})", + view.GetHashCode(), view.offset, view.size, size)); + retval = false; + } + else if (view.endsentinel != nodes[view.Offset + view.size + 1]) + { + Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), endsentinel {3} should be {4}", + view.GetHashCode(), view.offset, view.size, + view.endsentinel + " " + view.endsentinel!.GetHashCode(), + nodes[view.Offset + view.size + 1] + " " + nodes[view.Offset + view.size + 1].GetHashCode())); + retval = false; + } + if (view.views != views) + { + Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), wrong views list {3} <> {4}", + view.GetHashCode(), view.offset, view.size, view.views!.GetHashCode(), views.GetHashCode())); + retval = false; + } + if (view.underlying != this) + { + Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), wrong underlying {3} <> this {4}", + view.GetHashCode(), view.offset, view.size, view.underlying!.GetHashCode(), GetHashCode())); + retval = false; + } + if (view.stamp != stamp) + { + //Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), wrong stamp view:{2} underlying: {3}", view.GetHashCode(),view.offset, view.size, view.stamp, stamp)); + //retval = false; } - return retval; } + return retval; + } + + private string TheItem(Node node) + { + return node == null ? "(null node)" : node.item!.ToString(); + } + + /// + /// Check the sanity of this list + /// + /// true if sane + public virtual bool Check() + { + bool retval = true; + + /*if (underlying != null && underlying.stamp != stamp) + { + Logger.Log("underlying != null && underlying.stamp({0}) != stamp({1})", underlying.stamp, stamp); + retval = false; + }*/ - private string TheItem(Node node) + if (underlying != null) { - return node == null ? "(null node)" : node.item!.ToString(); + //TODO: check that this view is included in viewsEndpoints tree + return underlying.Check(); } - /// - /// Check the sanity of this list - /// - /// true if sane - public virtual bool Check() + if (startsentinel == null) { - bool retval = true; + Logger.Log("startsentinel == null"); + retval = false; + } - /*if (underlying != null && underlying.stamp != stamp) - { - Logger.Log("underlying != null && underlying.stamp({0}) != stamp({1})", underlying.stamp, stamp); - retval = false; - }*/ + if (endsentinel == null) + { + Logger.Log("endsentinel == null"); + retval = false; + } - if (underlying != null) + if (size == 0) + { + if (startsentinel != null && startsentinel.next != endsentinel) { - //TODO: check that this view is included in viewsEndpoints tree - return underlying.Check(); + Logger.Log("size == 0 but startsentinel.next != endsentinel"); + retval = false; } - if (startsentinel == null) + if (endsentinel != null && endsentinel.prev != startsentinel) { - Logger.Log("startsentinel == null"); + Logger.Log("size == 0 but endsentinel.prev != startsentinel"); retval = false; } + } + + if (startsentinel == null) + { + Logger.Log("NULL startsentinel"); + return retval; + } + + int count = 0; + Node node = startsentinel.next!, prev = startsentinel; + int taggroupsize = 0, oldtaggroupsize = losize + 1, seentaggroups = 0; + TagGroup? oldtg = null; + + if (underlying == null) + { + TagGroup tg = startsentinel.taggroup; - if (endsentinel == null) + if (tg.count != 0 || tg.first != null || tg.last != null || tg.tag != int.MinValue) { - Logger.Log("endsentinel == null"); + Logger.Log(string.Format("Bad startsentinel tag group: {0}", tg)); retval = false; } - if (size == 0) + tg = endsentinel!.taggroup; + if (tg.count != 0 || tg.first != null || tg.last != null || tg.tag != int.MaxValue) { - if (startsentinel != null && startsentinel.next != endsentinel) - { - Logger.Log("size == 0 but startsentinel.next != endsentinel"); - retval = false; - } - - if (endsentinel != null && endsentinel.prev != startsentinel) - { - Logger.Log("size == 0 but endsentinel.prev != startsentinel"); - retval = false; - } + Logger.Log(string.Format("Bad endsentinel tag group: {0}", tg)); + retval = false; } - - if (startsentinel == null) + } + while (node != endsentinel) + { + count++; + if (node.prev != prev) { - Logger.Log("NULL startsentinel"); - return retval; + Logger.Log(string.Format("Bad backpointer at node {0}", count)); + retval = false; } - - int count = 0; - Node node = startsentinel.next!, prev = startsentinel; - int taggroupsize = 0, oldtaggroupsize = losize + 1, seentaggroups = 0; - TagGroup? oldtg = null; - if (underlying == null) { - TagGroup tg = startsentinel.taggroup; - - if (tg.count != 0 || tg.first != null || tg.last != null || tg.tag != int.MinValue) + if (!node.prev!.Precedes(node)) { - Logger.Log(string.Format("Bad startsentinel tag group: {0}", tg)); + Logger.Log(string.Format("node.prev.tag ({0}, {1}) >= node.tag ({2}, {3}) at index={4} item={5} ", node.prev.taggroup.tag, node.prev.tag, node.taggroup.tag, node.tag, count, node.item)); retval = false; } - tg = endsentinel!.taggroup; - if (tg.count != 0 || tg.first != null || tg.last != null || tg.tag != int.MaxValue) - { - Logger.Log(string.Format("Bad endsentinel tag group: {0}", tg)); - retval = false; - } - } - while (node != endsentinel) - { - count++; - if (node.prev != prev) - { - Logger.Log(string.Format("Bad backpointer at node {0}", count)); - retval = false; - } - if (underlying == null) + if (node.taggroup != oldtg) { - if (!node.prev!.Precedes(node)) + + if (node.taggroup.first != node) { - Logger.Log(string.Format("node.prev.tag ({0}, {1}) >= node.tag ({2}, {3}) at index={4} item={5} ", node.prev.taggroup.tag, node.prev.tag, node.taggroup.tag, node.tag, count, node.item)); + string ntfi = TheItem(node.taggroup.first!); + Logger.Log(string.Format("Bad first pointer in taggroup: node.taggroup.first.item ({0}), node.item ({1}) at index={2} item={3}", ntfi, node.item, count, node.item)); retval = false; } - if (node.taggroup != oldtg) + if (oldtg != null) { - - if (node.taggroup.first != node) + if (oldtg.count != taggroupsize) { - string ntfi = TheItem(node.taggroup.first!); - Logger.Log(string.Format("Bad first pointer in taggroup: node.taggroup.first.item ({0}), node.item ({1}) at index={2} item={3}", ntfi, node.item, count, node.item)); + Logger.Log(string.Format("Bad taggroupsize: oldtg.count ({0}) != taggroupsize ({1}) at index={2} item={3}", oldtg.count, taggroupsize, count, node.item)); retval = false; } - if (oldtg != null) + if (oldtaggroupsize <= losize && taggroupsize <= losize) { - if (oldtg.count != taggroupsize) - { - Logger.Log(string.Format("Bad taggroupsize: oldtg.count ({0}) != taggroupsize ({1}) at index={2} item={3}", oldtg.count, taggroupsize, count, node.item)); - retval = false; - } - - if (oldtaggroupsize <= losize && taggroupsize <= losize) - { - Logger.Log(string.Format("Two small taggroups in a row: oldtaggroupsize ({0}), taggroupsize ({1}) at index={2} item={3}", oldtaggroupsize, taggroupsize, count, node.item)); - retval = false; - } - - if (node.taggroup.tag <= oldtg.tag) - { - Logger.Log(string.Format("Taggroup tags not strictly increasing: oldtaggrouptag ({0}), taggrouptag ({1}) at index={2} item={3}", oldtg.tag, node.taggroup.tag, count, node.item)); - retval = false; - } + Logger.Log(string.Format("Two small taggroups in a row: oldtaggroupsize ({0}), taggroupsize ({1}) at index={2} item={3}", oldtaggroupsize, taggroupsize, count, node.item)); + retval = false; + } - if (oldtg.last != node.prev) - { - Logger.Log(string.Format("Bad last pointer in taggroup: oldtg.last.item ({0}), node.prev.item ({1}) at index={2} item={3}", oldtg.last!.item, node.prev.item, count, node.item)); - retval = false; - } + if (node.taggroup.tag <= oldtg.tag) + { + Logger.Log(string.Format("Taggroup tags not strictly increasing: oldtaggrouptag ({0}), taggrouptag ({1}) at index={2} item={3}", oldtg.tag, node.taggroup.tag, count, node.item)); + retval = false; + } - oldtaggroupsize = taggroupsize; + if (oldtg.last != node.prev) + { + Logger.Log(string.Format("Bad last pointer in taggroup: oldtg.last.item ({0}), node.prev.item ({1}) at index={2} item={3}", oldtg.last!.item, node.prev.item, count, node.item)); + retval = false; } - seentaggroups++; - oldtg = node.taggroup; - taggroupsize = 1; - } - else - { - taggroupsize++; + oldtaggroupsize = taggroupsize; } - } - prev = node; - node = node.next!; - if (node == null) + seentaggroups++; + oldtg = node.taggroup; + taggroupsize = 1; + } + else { - Logger.Log(string.Format("Null next pointer at node {0}", count)); - return false; + taggroupsize++; } } - if (underlying == null && size == 0 && taggroups != 0) + prev = node; + node = node.next!; + if (node == null) { - Logger.Log(string.Format("Bad taggroups for empty list: size={0} taggroups={1}", size, taggroups)); - retval = false; + Logger.Log(string.Format("Null next pointer at node {0}", count)); + return false; } - if (underlying == null && size > 0) + } + + if (underlying == null && size == 0 && taggroups != 0) + { + Logger.Log(string.Format("Bad taggroups for empty list: size={0} taggroups={1}", size, taggroups)); + retval = false; + } + if (underlying == null && size > 0) + { + oldtg = node.prev!.taggroup; + if (oldtg != null) { - oldtg = node.prev!.taggroup; - if (oldtg != null) + if (oldtg.count != taggroupsize) { - if (oldtg.count != taggroupsize) - { - Logger.Log(string.Format("Bad taggroupsize: oldtg.count ({0}) != taggroupsize ({1}) at index={2} item={3}", oldtg.count, taggroupsize, count, node.item)); - retval = false; - } - - if (oldtaggroupsize <= losize && taggroupsize <= losize) - { - Logger.Log(string.Format("Two small taggroups in a row: oldtaggroupsize ({0}), taggroupsize ({1}) at index={2} item={3}", oldtaggroupsize, taggroupsize, count, node.item)); - retval = false; - } + Logger.Log(string.Format("Bad taggroupsize: oldtg.count ({0}) != taggroupsize ({1}) at index={2} item={3}", oldtg.count, taggroupsize, count, node.item)); + retval = false; + } - if (node.taggroup.tag <= oldtg.tag) - { - Logger.Log(string.Format("Taggroup tags not strictly increasing: oldtaggrouptag ({0}), taggrouptag ({1}) at index={2} item={3}", oldtg.tag, node.taggroup.tag, count, node.item)); - retval = false; - } + if (oldtaggroupsize <= losize && taggroupsize <= losize) + { + Logger.Log(string.Format("Two small taggroups in a row: oldtaggroupsize ({0}), taggroupsize ({1}) at index={2} item={3}", oldtaggroupsize, taggroupsize, count, node.item)); + retval = false; + } - if (oldtg.last != node.prev) - { - Logger.Log(string.Format("Bad last pointer in taggroup: oldtg.last.item ({0}), node.prev.item ({1}) at index={2} item={3}", TheItem(oldtg.last!), TheItem(node.prev), count, node.item)); - retval = false; - } + if (node.taggroup.tag <= oldtg.tag) + { + Logger.Log(string.Format("Taggroup tags not strictly increasing: oldtaggrouptag ({0}), taggrouptag ({1}) at index={2} item={3}", oldtg.tag, node.taggroup.tag, count, node.item)); + retval = false; } - if (seentaggroups != taggroups) + if (oldtg.last != node.prev) { - Logger.Log(string.Format("seentaggroups ({0}) != taggroups ({1}) (at size {2})", seentaggroups, taggroups, size)); + Logger.Log(string.Format("Bad last pointer in taggroup: oldtg.last.item ({0}), node.prev.item ({1}) at index={2} item={3}", TheItem(oldtg.last!), TheItem(node.prev), count, node.item)); retval = false; } } - if (count != size) + + if (seentaggroups != taggroups) { - Logger.Log(string.Format("size={0} but enumeration gives {1} nodes ", size, count)); + Logger.Log(string.Format("seentaggroups ({0}) != taggroups ({1}) (at size {2})", seentaggroups, taggroups, size)); retval = false; } + } + if (count != size) + { + Logger.Log(string.Format("size={0} but enumeration gives {1} nodes ", size, count)); + retval = false; + } + + retval = CheckViews() && retval; - retval = CheckViews() && retval; + if (!retval) + { + return false; + } - if (!retval) + if (underlying == null) + { + if (size != dict.Count) { - return false; + Logger.Log(string.Format("list.size ({0}) != dict.Count ({1})", size, dict.Count)); + retval = false; } - - if (underlying == null) + Node n = startsentinel.next!; + while (n != endsentinel) { - if (size != dict.Count) + if (!dict.Find(ref n!.item, out Node n2)) { - Logger.Log(string.Format("list.size ({0}) != dict.Count ({1})", size, dict.Count)); + Logger.Log(string.Format("Item in list but not dict: {0}", n.item)); retval = false; } - Node n = startsentinel.next!; - while (n != endsentinel) + else if (n != n2) { - if (!dict.Find(ref n!.item, out Node n2)) - { - Logger.Log(string.Format("Item in list but not dict: {0}", n.item)); - retval = false; - } - else if (n != n2) - { - Logger.Log(string.Format("Wrong node in dict for item: {0}", n.item)); - retval = false; - } - n = n.next!; + Logger.Log(string.Format("Wrong node in dict for item: {0}", n.item)); + retval = false; } + n = n.next!; } - return retval; } - #endregion + return retval; + } + #endregion - #region System.Collections.Generic.IList Members + #region System.Collections.Generic.IList Members - void System.Collections.Generic.IList.RemoveAt(int index) - { - RemoveAt(index); - } + void System.Collections.Generic.IList.RemoveAt(int index) + { + RemoveAt(index); + } - void System.Collections.Generic.ICollection.Add(T item) - { - Add(item); - } + void System.Collections.Generic.ICollection.Add(T item) + { + Add(item); + } - #endregion + #endregion - #region System.Collections.ICollection Members + #region System.Collections.ICollection Members - bool System.Collections.ICollection.IsSynchronized => false; + bool System.Collections.ICollection.IsSynchronized => false; - [Obsolete] - object System.Collections.ICollection.SyncRoot => underlying != null ? ((System.Collections.ICollection)underlying).SyncRoot! : startsentinel!; + [Obsolete] + object System.Collections.ICollection.SyncRoot => underlying != null ? ((System.Collections.ICollection)underlying).SyncRoot! : startsentinel!; - void System.Collections.ICollection.CopyTo(Array arr, int index) + void System.Collections.ICollection.CopyTo(Array arr, int index) + { + if (index < 0 || index + Count > arr.Length) { - if (index < 0 || index + Count > arr.Length) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } + throw new ArgumentOutOfRangeException(nameof(index)); + } - foreach (T item in this) - { - arr.SetValue(item, index++); - } + foreach (T item in this) + { + arr.SetValue(item, index++); } + } - #endregion + #endregion - #region System.Collections.IList Members + #region System.Collections.IList Members - Object System.Collections.IList.this[int index] + object? System.Collections.IList.this[int index] + { + get => this[index]!; + set { - get => this[index]!; - set => this[index] = (T)value; - } + if (value is null && default(T) is not null) throw new ArgumentNullException(nameof(value)); + if (value is not T) throw new ArgumentException("Wrong type", nameof(value)); - int System.Collections.IList.Add(Object o) - { - bool added = Add((T)o); - // What position to report if item not added? SC.IList.Add doesn't say - return added ? Count - 1 : -1; + this[index] = (T)value; } + } - bool System.Collections.IList.Contains(Object o) - { - return Contains((T)o); - } + int System.Collections.IList.Add(object? value) + { + if (value is null && default(T) is not null) throw new ArgumentNullException(nameof(value)); + if (value is not T) throw new ArgumentException("Wrong type", nameof(value)); - int System.Collections.IList.IndexOf(Object o) - { - return Math.Max(-1, IndexOf((T)o)); - } + bool added = Add((T)value); + // What position to report if item not added? SC.IList.Add doesn't say + return added ? Count - 1 : -1; + } - void System.Collections.IList.Insert(int index, Object o) - { - Insert(index, (T)o); - } + bool System.Collections.IList.Contains(object? value) + { + if (value is null && default(T) is not null) return false; + if (value is not T) return false; - void System.Collections.IList.Remove(Object o) - { - Remove((T)o); - } + return Contains((T)value); + } - void System.Collections.IList.RemoveAt(int index) - { - RemoveAt(index); - } + int System.Collections.IList.IndexOf(object? value) + { + if (value is null && default(T) is not null) return -1; + if (value is not T) return -1; - #endregion + return Math.Max(-1, IndexOf((T)value)); + } + + void System.Collections.IList.Insert(int index, object? value) + { + if (value is null && default(T) is not null) throw new ArgumentNullException(nameof(value)); + if (value is not T) throw new ArgumentException("Wrong type", nameof(value)); + + Insert(index, (T)value); } + + void System.Collections.IList.Remove(object? value) + { + if (value is null && default(T) is not null) return; + if (value is not T) return; + + Remove((T)value); + } + + void System.Collections.IList.RemoveAt(int index) + { + RemoveAt(index); + } + + #endregion } diff --git a/C5/LinkedLists/LinkedList.cs b/C5/LinkedLists/LinkedList.cs index 12dd6ed5..9b7d82b8 100644 --- a/C5/LinkedLists/LinkedList.cs +++ b/C5/LinkedLists/LinkedList.cs @@ -4,2959 +4,2974 @@ using System; using SCG = System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// A list collection class based on a doubly linked list data structure. +/// +public class LinkedList : SequencedBase, IList, IStack, IQueue { + #region Fields /// - /// A list collection class based on a doubly linked list data structure. + /// IExtensible.Add(T) always does AddLast(T), fIFO determines + /// if T Remove() does RemoveFirst() or RemoveLast() /// - public class LinkedList : SequencedBase, IList, IStack, IQueue - { - #region Fields - /// - /// IExtensible.Add(T) always does AddLast(T), fIFO determines - /// if T Remove() does RemoveFirst() or RemoveLast() - /// - private bool fIFO = true; + private bool fIFO = true; - #region Events + #region Events - /// - /// - /// - /// - public override EventType ListenableEvents => underlying == null ? EventType.All : EventType.None; + /// + /// + /// + /// + public override EventType ListenableEvents => underlying == null ? EventType.All : EventType.None; - #endregion + #endregion - //Invariant: startsentinel != null && endsentinel != null - //If size==0: startsentinel.next == endsentinel && endsentinel.prev == startsentinel - //Else: startsentinel.next == First && endsentinel.prev == Last) - /// - /// Node to the left of first node - /// - private Node? startsentinel; + //Invariant: startsentinel != null && endsentinel != null + //If size==0: startsentinel.next == endsentinel && endsentinel.prev == startsentinel + //Else: startsentinel.next == First && endsentinel.prev == Last) + /// + /// Node to the left of first node + /// + private Node? startsentinel; - /// - /// Node to the right of last node - /// - private Node? endsentinel; + /// + /// Node to the right of last node + /// + private Node? endsentinel; - /// - /// Offset of this view in underlying list - /// + /// + /// Offset of this view in underlying list + /// - private int offset; + private int offset; - /// - /// underlying list of this view (or null for the underlying list) - /// - private LinkedList? underlying; + /// + /// underlying list of this view (or null for the underlying list) + /// + private LinkedList? underlying; - //Note: all views will have the same views list since all view objects are created by MemberwiseClone() - private WeakViewList>? views; - private WeakViewList>.Node? myWeakReference; + //Note: all views will have the same views list since all view objects are created by MemberwiseClone() + private WeakViewList>? views; + private WeakViewList>.Node? myWeakReference; - /// - /// Has this list or view not been invalidated by some operation (by someone calling Dispose()) - /// - private bool isValid = true; + /// + /// Has this list or view not been invalidated by some operation (by someone calling Dispose()) + /// + private bool isValid = true; - #endregion + #endregion - #region Util + #region Util - private bool Equals(T i1, T i2) { return itemequalityComparer.Equals(i1, i2); } + private bool Equals(T i1, T i2) { return itemEqualityComparer.Equals(i1, i2); } - #region Check utilities - /// - /// Check if it is valid to perform updates and increment stamp of - /// underlying if this is a view. - /// This method should be called in every public modifying - /// methods before any modifications are performed. - /// - /// - /// if check fails. - protected override void UpdateCheck() + #region Check utilities + /// + /// Check if it is valid to perform updates and increment stamp of + /// underlying if this is a view. + /// This method should be called in every public modifying + /// methods before any modifications are performed. + /// + /// + /// if check fails. + protected override void UpdateCheck() + { + ValidityCheck(); + base.UpdateCheck(); + if (underlying != null) { - ValidityCheck(); - base.UpdateCheck(); - if (underlying != null) - { - underlying.stamp++; - } + underlying.stamp++; } + } - /// - /// Check if we are a view that the underlying list has only been updated through us. - ///
- /// This method should be called from enumerators etc to guard against - /// modification of the base collection. - ///
- /// if check fails. - private void ValidityCheck() + /// + /// Check if we are a view that the underlying list has only been updated through us. + ///
+ /// This method should be called from enumerators etc to guard against + /// modification of the base collection. + ///
+ /// if check fails. + private void ValidityCheck() + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException(); - } + throw new ViewDisposedException(); } + } - /// - /// Check that the list has not been updated since a particular time. - /// - /// The stamp indicating the time. - /// if check fails. - protected override void ModifyCheck(int stamp) + /// + /// Check that the list has not been updated since a particular time. + /// + /// The stamp indicating the time. + /// if check fails. + protected override void ModifyCheck(int stamp) + { + ValidityCheck(); + if ((underlying != null ? underlying.stamp : this.stamp) != stamp) { - ValidityCheck(); - if ((underlying != null ? underlying.stamp : this.stamp) != stamp) - { - throw new CollectionModifiedException(); - } + throw new CollectionModifiedException(); } - #endregion + } + #endregion - #region Searching - private bool Contains(T item, out Node node) - { + #region Searching + private bool Contains(T item, out Node node) + { - //TODO: search from both ends? Or search from the end selected by FIFO? - node = startsentinel!.next!; - while (node != endsentinel) + //TODO: search from both ends? Or search from the end selected by FIFO? + node = startsentinel!.next!; + while (node != endsentinel) + { + if (Equals(item, node.item)) { - if (Equals(item, node.item)) - { - return true; - } - - node = node.next!; + return true; } - return false; + node = node.next!; } - /// - /// Search forwards from a node for a node with a particular item. - /// - /// The item to look for - /// On input, the node to start at. If item was found, the node found on output. - /// If node was found, the value will be the number of links followed higher than - /// the value on input. If item was not found, the value on output is undefined. - /// True if node was found. - private bool Find(T item, ref Node node, ref int index) + return false; + } + + /// + /// Search forwards from a node for a node with a particular item. + /// + /// The item to look for + /// On input, the node to start at. If item was found, the node found on output. + /// If node was found, the value will be the number of links followed higher than + /// the value on input. If item was not found, the value on output is undefined. + /// True if node was found. + private bool Find(T item, ref Node node, ref int index) + { + while (node != endsentinel) { - while (node != endsentinel) + //if (item.Equals(node.item)) + if (itemEqualityComparer.Equals(item, node!.item)) { - //if (item.Equals(node.item)) - if (itemequalityComparer.Equals(item, node!.item)) - { - return true; - } - - index++; - node = node.next!; + return true; } - return false; + index++; + node = node.next!; } - private bool DnIf(T item, ref Node node, ref int index) + return false; + } + + private bool DnIf(T item, ref Node node, ref int index) + { + while (node != startsentinel) { - while (node != startsentinel) + //if (item.Equals(node.item)) + if (itemEqualityComparer.Equals(item, node!.item)) { - //if (item.Equals(node.item)) - if (itemequalityComparer.Equals(item, node!.item)) - { - return true; - } - - index--; - node = node.prev!; + return true; } - return false; + index--; + node = node.prev!; } + return false; + } - #endregion - - #region Indexing - /// - /// Return the node at position pos - /// - /// - /// - private Node Get(int pos) - { - if (pos < 0 || pos >= size) - { - throw new IndexOutOfRangeException(); - } - else if (pos < size / 2) - { // Closer to front - Node node = startsentinel!; - - for (int i = 0; i <= pos; i++) - { - node = node.next!; - } - - return node!; - } - else - { // Closer to end - Node node = endsentinel!; - for (int i = size; i > pos; i--) - { - node = node.prev!; - } + #endregion - return node; - } + #region Indexing + /// + /// Return the node at position pos + /// + /// + /// + private Node Get(int pos) + { + if (pos < 0 || pos >= size) + { + throw new IndexOutOfRangeException(); } + else if (pos < size / 2) + { // Closer to front + Node node = startsentinel!; - /// - /// Find the distance from pos to the set given by positions. Return the - /// signed distance as return value and as an out parameter, the - /// array index of the nearest position. This is used for up to length 5 of - /// positions, and we do not assume it is sorted. - /// - /// - /// - /// - /// - private int Dist(int pos, out int nearest, int[] positions) - { - nearest = -1; - int bestdist = int.MaxValue; - int signeddist = bestdist; - for (int i = 0; i < positions.Length; i++) + for (int i = 0; i <= pos; i++) { - int thisdist = positions[i] - pos; - if (thisdist >= 0 && thisdist < bestdist) { nearest = i; bestdist = thisdist; signeddist = thisdist; } - if (thisdist < 0 && -thisdist < bestdist) { nearest = i; bestdist = -thisdist; signeddist = thisdist; } + node = node.next!; } - return signeddist; + + return node!; } + else + { // Closer to end + Node node = endsentinel!; - /// - /// Find the node at position pos, given known positions of several nodes. - /// - /// - /// - /// - /// - private Node Get(int pos, int[] positions, Node[] nodes) - { - int delta = Dist(pos, out int nearest, positions); - Node node = nodes[nearest]; - if (delta > 0) - { - for (int i = 0; i < delta; i++) - { - node = node.prev!; - } - } - else + for (int i = size; i > pos; i--) { - for (int i = 0; i > delta; i--) - { - node = node.next!; - } + node = node.prev!; } return node; } + } - /// - /// Get nodes at positions p1 and p2, given nodes at several positions. - /// - /// - /// - /// - /// - /// - /// - private void GetPair(int p1, int p2, out Node n1, out Node n2, int[] positions, Node[] nodes) + /// + /// Find the distance from pos to the set given by positions. Return the + /// signed distance as return value and as an out parameter, the + /// array index of the nearest position. This is used for up to length 5 of + /// positions, and we do not assume it is sorted. + /// + /// + /// + /// + /// + private int Dist(int pos, out int nearest, int[] positions) + { + nearest = -1; + int bestdist = int.MaxValue; + int signeddist = bestdist; + for (int i = 0; i < positions.Length; i++) { - int delta1 = Dist(p1, out int nearest1, positions), d1 = delta1 < 0 ? -delta1 : delta1; - int delta2 = Dist(p2, out int nearest2, positions), d2 = delta2 < 0 ? -delta2 : delta2; + int thisdist = positions[i] - pos; + if (thisdist >= 0 && thisdist < bestdist) { nearest = i; bestdist = thisdist; signeddist = thisdist; } + if (thisdist < 0 && -thisdist < bestdist) { nearest = i; bestdist = -thisdist; signeddist = thisdist; } + } + return signeddist; + } - if (d1 < d2) + /// + /// Find the node at position pos, given known positions of several nodes. + /// + /// + /// + /// + /// + private Node Get(int pos, int[] positions, Node[] nodes) + { + int delta = Dist(pos, out int nearest, positions); + Node node = nodes[nearest]; + if (delta > 0) + { + for (int i = 0; i < delta; i++) { - n1 = Get(p1, positions, nodes); - n2 = Get(p2, new int[] { positions[nearest2], p1 }, new Node[] { nodes[nearest2], n1 }); + node = node.prev!; } - else + } + else + { + for (int i = 0; i > delta; i--) { - n2 = Get(p2, positions, nodes); - n1 = Get(p1, new int[] { positions[nearest1], p2 }, new Node[] { nodes[nearest1], n2 }); + node = node.next!; } } - #endregion - #region Insertion + return node; + } - /// - /// - /// - /// The index in this view - /// - /// - /// - private Node Insert(int index, Node succ, T item) - { - Node newnode = new Node(item, succ.prev, succ); - succ.prev!.next = newnode; - succ.prev = newnode; - size++; - if (underlying != null) - { - underlying.size++; - } + /// + /// Get nodes at positions p1 and p2, given nodes at several positions. + /// + /// + /// + /// + /// + /// + /// + private void GetPair(int p1, int p2, out Node n1, out Node n2, int[] positions, Node[] nodes) + { + int delta1 = Dist(p1, out int nearest1, positions), d1 = delta1 < 0 ? -delta1 : delta1; + int delta2 = Dist(p2, out int nearest2, positions), d2 = delta2 < 0 ? -delta2 : delta2; - FixViewsAfterInsert(succ, newnode.prev!, 1, Offset + index); - return newnode; + if (d1 < d2) + { + n1 = Get(p1, positions, nodes); + n2 = Get(p2, [positions[nearest2], p1], [nodes[nearest2], n1]); + } + else + { + n2 = Get(p2, positions, nodes); + n1 = Get(p1, [positions[nearest1], p2], [nodes[nearest1], n2]); } + } + #endregion - #endregion + #region Insertion - #region Removal - private T Remove(Node node, int index) + /// + /// + /// + /// The index in this view + /// + /// + /// + private Node Insert(int index, Node succ, T item) + { + Node newnode = new(item, succ.prev, succ); + succ.prev!.next = newnode; + succ.prev = newnode; + size++; + if (underlying != null) { - FixViewsBeforeSingleRemove(node, Offset + index); - node.prev!.next = node.next; - node.next!.prev = node.prev; - size--; - if (underlying != null) - { - underlying.size--; - } - - return node.item; + underlying.size++; } + FixViewsAfterInsert(succ, newnode.prev!, 1, Offset + index); + return newnode; + } - #endregion + #endregion - #region fixView utilities - /// - /// - /// - /// The successor of the added nodes - /// The predecessor of the inserted nodes - /// The actual number of inserted nodes - /// - private void FixViewsAfterInsert(Node succ, Node pred, int added, int realInsertionIndex) + #region Removal + private T Remove(Node node, int index) + { + FixViewsBeforeSingleRemove(node, Offset + index); + node.prev!.next = node.next; + node.next!.prev = node.prev; + size--; + if (underlying != null) { - if (views != null) - { - foreach (LinkedList view in views) - { - if (view != this) - { - - if (view.Offset == realInsertionIndex && view.size > 0) - { - view.startsentinel = succ.prev; - } + underlying.size--; + } - if (view.Offset + view.size == realInsertionIndex) - { - view.endsentinel = pred.next!; - } + return node.item; + } - if (view.Offset < realInsertionIndex && view.Offset + view.size > realInsertionIndex) - { - view.size += added; - } - if (view.Offset > realInsertionIndex || (view.Offset == realInsertionIndex && view.size > 0)) - { - view.offset += added; - } - } - } - } - } + #endregion - private void FixViewsBeforeSingleRemove(Node node, int realRemovalIndex) + #region fixView utilities + /// + /// + /// + /// The successor of the added nodes + /// The predecessor of the inserted nodes + /// The actual number of inserted nodes + /// + private void FixViewsAfterInsert(Node succ, Node pred, int added, int realInsertionIndex) + { + if (views != null) { - if (views != null) + foreach (LinkedList view in views) { - foreach (LinkedList view in views) + if (view != this) { - if (view != this) - { - if (view.offset - 1 == realRemovalIndex) - { - view.startsentinel = node.prev; - } + if (view.Offset == realInsertionIndex && view.size > 0) + { + view.startsentinel = succ.prev; + } - if (view.offset + view.size == realRemovalIndex) - { - view.endsentinel = node.next!; - } + if (view.Offset + view.size == realInsertionIndex) + { + view.endsentinel = pred.next!; + } - if (view.offset <= realRemovalIndex && view.offset + view.size > realRemovalIndex) - { - view.size--; - } + if (view.Offset < realInsertionIndex && view.Offset + view.size > realInsertionIndex) + { + view.size += added; + } - if (view.offset > realRemovalIndex) - { - view.offset--; - } + if (view.Offset > realInsertionIndex || (view.Offset == realInsertionIndex && view.size > 0)) + { + view.offset += added; } } } } + } - private void FixViewsBeforeRemove(int start, int count, Node first, Node last) + private void FixViewsBeforeSingleRemove(Node node, int realRemovalIndex) + { + if (views != null) { - int clearend = start + count - 1; - if (views != null) + foreach (LinkedList view in views) { - foreach (LinkedList view in views) + if (view != this) { - if (view == this) - { - continue; - } - int viewoffset = view.Offset, viewend = viewoffset + view.size - 1; - //sentinels - if (start < viewoffset && viewoffset - 1 <= clearend) + if (view.offset - 1 == realRemovalIndex) { - view.startsentinel = first.prev; + view.startsentinel = node.prev; } - if (start <= viewend + 1 && viewend < clearend) + if (view.offset + view.size == realRemovalIndex) { - view.endsentinel = last.next!; + view.endsentinel = node.next!; } - //offsets and sizes - if (start < viewoffset) + + if (view.offset <= realRemovalIndex && view.offset + view.size > realRemovalIndex) { - if (clearend < viewoffset) - { - view.offset = viewoffset - count; - } - else - { - view.offset = start; - view.size = clearend < viewend ? viewend - clearend : 0; - } + view.size--; } - else if (start <= viewend) + + if (view.offset > realRemovalIndex) { - view.size = clearend <= viewend ? view.size - count : start - viewoffset; + view.offset--; } } } } + } - /// - /// - /// - /// - /// The position of View(otherOffset, otherSize) wrt. this view - private MutualViewPosition ViewPosition(LinkedList otherView) + private void FixViewsBeforeRemove(int start, int count, Node first, Node last) + { + int clearend = start + count - 1; + if (views != null) { - - int end = offset + size, otherOffset = otherView.offset, otherSize = otherView.size, otherEnd = otherOffset + otherSize; - if (otherOffset >= end || otherEnd <= offset) - { - return MutualViewPosition.NonOverlapping; - } - - if (size == 0 || (otherOffset <= offset && end <= otherEnd)) - { - return MutualViewPosition.Contains; - } - - if (otherSize == 0 || (offset <= otherOffset && otherEnd <= end)) + foreach (LinkedList view in views) { - return MutualViewPosition.ContainedIn; - } + if (view == this) + { + continue; + } - return MutualViewPosition.Overlapping; - } + int viewoffset = view.Offset, viewend = viewoffset + view.size - 1; + //sentinels + if (start < viewoffset && viewoffset - 1 <= clearend) + { + view.startsentinel = first.prev; + } - private void DisposeOverlappingViews(bool reverse) - { - if (views != null) - { - foreach (LinkedList view in views) + if (start <= viewend + 1 && viewend < clearend) + { + view.endsentinel = last.next!; + } + //offsets and sizes + if (start < viewoffset) { - if (view != this) + if (clearend < viewoffset) { - switch (ViewPosition(view)) - { - case MutualViewPosition.ContainedIn: - if (reverse) - { } - else - { - view.Dispose(); - } - - break; - case MutualViewPosition.Overlapping: - view.Dispose(); - break; - case MutualViewPosition.Contains: - case MutualViewPosition.NonOverlapping: - break; - } + view.offset = viewoffset - count; + } + else + { + view.offset = start; + view.size = clearend < viewend ? viewend - clearend : 0; } } + else if (start <= viewend) + { + view.size = clearend <= viewend ? view.size - count : start - viewoffset; + } } } + } - #endregion - - #endregion + /// + /// + /// + /// + /// The position of View(otherOffset, otherSize) wrt. this view + private MutualViewPosition ViewPosition(LinkedList otherView) + { - #region Constructors + int end = offset + size, otherOffset = otherView.offset, otherSize = otherView.size, otherEnd = otherOffset + otherSize; + if (otherOffset >= end || otherEnd <= offset) + { + return MutualViewPosition.NonOverlapping; + } - /// - /// Create a linked list with en external item equalityComparer - /// - /// The external equalitySCG.Comparer - public LinkedList(SCG.IEqualityComparer itemequalityComparer) - : base(itemequalityComparer) + if (size == 0 || (otherOffset <= offset && end <= otherEnd)) { - offset = 0; - size = stamp = 0; - startsentinel = new Node(default); - endsentinel = new Node(default); - startsentinel.next = endsentinel; - endsentinel.prev = startsentinel; + return MutualViewPosition.Contains; + } + if (otherSize == 0 || (offset <= otherOffset && otherEnd <= end)) + { + return MutualViewPosition.ContainedIn; } - /// - /// Create a linked list with the natural item equalityComparer - /// - public LinkedList() : this(EqualityComparer.Default) { } + return MutualViewPosition.Overlapping; + } - #endregion + private void DisposeOverlappingViews(bool reverse) + { + if (views != null) + { + foreach (LinkedList view in views) + { + if (view != this) + { + switch (ViewPosition(view)) + { + case MutualViewPosition.ContainedIn: + if (reverse) + { } + else + { + view.Dispose(); + } - #region Node nested class + break; + case MutualViewPosition.Overlapping: + view.Dispose(); + break; + case MutualViewPosition.Contains: + case MutualViewPosition.NonOverlapping: + break; + } + } + } + } + } - /// - /// An individual cell in the linked list - /// - private class Node - { - public Node? prev; + #endregion - public Node? next; + #endregion - public T item; + #region Constructors - #region Tag support + /// + /// Create a linked list with en external item equalityComparer + /// + /// The external equalitySCG.Comparer + public LinkedList(SCG.IEqualityComparer itemequalityComparer) + : base(itemequalityComparer) + { + offset = 0; + size = stamp = 0; + startsentinel = new Node(default); + endsentinel = new Node(default); + startsentinel.next = endsentinel; + endsentinel.prev = startsentinel; - #endregion + } - internal Node(T item) { this.item = item; } + /// + /// Create a linked list with the natural item equalityComparer + /// + public LinkedList() : this(EqualityComparer.Default) { } - internal Node(T item, Node? prev, Node? next) - { - this.item = item; this.prev = prev; this.next = next; - } + #endregion - public override string ToString() - { + #region Node nested class - return string.Format("Node(item={0})", item); - } - } + /// + /// An individual cell in the linked list + /// + private class Node + { + public Node? prev; - #endregion + public Node? next; - #region Taggroup nested class and tag maintenance utilities + public T item; + #region Tag support #endregion - #region Position, PositionComparer and ViewHandler nested types - private class PositionComparer : SCG.IComparer + internal Node(T item) { this.item = item; } + + internal Node(T item, Node? prev, Node? next) { - private static PositionComparer _default; + this.item = item; this.prev = prev; this.next = next; + } - private PositionComparer() { } - public static PositionComparer Default => _default ??= new PositionComparer(); - public int Compare(Position a, Position b) - { + public override string ToString() + { - return a.Index.CompareTo(b.Index); - } + return string.Format("Node(item={0})", item); } + } - /// - /// During RemoveAll, we need to cache the original endpoint indices of views - /// - private struct Position + #endregion + + #region Taggroup nested class and tag maintenance utilities + + + #endregion + + #region Position, PositionComparer and ViewHandler nested types + private class PositionComparer : SCG.IComparer + { + private static readonly PositionComparer _default = new(); + private PositionComparer() { } + public static PositionComparer Default => _default; + public int Compare(Position a, Position b) => a.Index.CompareTo(b.Index); + } + + /// + /// During RemoveAll, we need to cache the original endpoint indices of views + /// + private struct Position + { + public LinkedList? View { get; } + + public bool Left { get; private set; } + + public int Index { get; } + + public Position(LinkedList view, bool left) { - public LinkedList? View { get; } + View = view; + Left = left; - public bool Left { get; private set; } + Index = left ? view.Offset : view.Offset + view.size - 1; + } - public int Index { get; } + public Position(int index) + { + Index = index; + View = null; + Left = false; + } + } - public Position(LinkedList view, bool left) + //TODO: merge the two implementations using Position values as arguments + /// + /// Handle the update of (other) views during a multi-remove operation. + /// + private struct ViewHandler + { + private readonly ArrayList? leftEnds; + private readonly ArrayList? rightEnds; + private int leftEndIndex, rightEndIndex, leftEndIndex2, rightEndIndex2; + internal readonly int viewCount; + internal ViewHandler(LinkedList list) + { + leftEndIndex = rightEndIndex = leftEndIndex2 = rightEndIndex2 = viewCount = 0; + leftEnds = rightEnds = null; + if (list.views != null) { - View = view; - Left = left; - - Index = left ? view.Offset : view.Offset + view.size - 1; + foreach (LinkedList v in list.views) + { + if (v != list) + { + if (leftEnds == null || rightEnds == null) + { + leftEnds = new ArrayList(); + rightEnds = new ArrayList(); + } + leftEnds.Add(new Position(v, true)); + rightEnds.Add(new Position(v, false)); + } + } } - public Position(int index) + if (leftEnds == null || rightEnds == null) { - Index = index; - View = null; - Left = false; + return; } + + viewCount = leftEnds.Count; + leftEnds.Sort(PositionComparer.Default); + rightEnds.Sort(PositionComparer.Default); } - //TODO: merge the two implementations using Position values as arguments /// - /// Handle the update of (other) views during a multi-remove operation. + /// This is to be called with realindex pointing to the first node to be removed after a (stretch of) node that was not removed /// - private struct ViewHandler + /// + /// + internal void SkipEndpoints(int removed, int realindex) { - private readonly ArrayList? leftEnds; - private readonly ArrayList? rightEnds; - private int leftEndIndex, rightEndIndex, leftEndIndex2, rightEndIndex2; - internal readonly int viewCount; - internal ViewHandler(LinkedList list) + if (viewCount > 0) { - leftEndIndex = rightEndIndex = leftEndIndex2 = rightEndIndex2 = viewCount = 0; - leftEnds = rightEnds = null; - if (list.views != null) + Position endpoint; + while (leftEndIndex < viewCount && (endpoint = leftEnds![leftEndIndex]).Index <= realindex) { - foreach (LinkedList v in list.views) - { - if (v != list) - { - if (leftEnds == null || rightEnds == null) - { - leftEnds = new ArrayList(); - rightEnds = new ArrayList(); - } - leftEnds.Add(new Position(v, true)); - rightEnds.Add(new Position(v, false)); - } - } + LinkedList view = endpoint.View!; + view.offset -= removed; + view.size += removed; + leftEndIndex++; } - - if (leftEnds == null || rightEnds == null) + while (rightEndIndex < viewCount && (endpoint = rightEnds![rightEndIndex]).Index < realindex) { - return; + LinkedList view = endpoint.View!; + view.size -= removed; + rightEndIndex++; } - - viewCount = leftEnds.Count; - leftEnds.Sort(PositionComparer.Default); - rightEnds.Sort(PositionComparer.Default); } - - /// - /// This is to be called with realindex pointing to the first node to be removed after a (stretch of) node that was not removed - /// - /// - /// - internal void SkipEndpoints(int removed, int realindex) + if (viewCount > 0) { - if (viewCount > 0) + while (leftEndIndex2 < viewCount && (_ = leftEnds![leftEndIndex2]).Index <= realindex) { - Position endpoint; - while (leftEndIndex < viewCount && (endpoint = leftEnds![leftEndIndex]).Index <= realindex) - { - LinkedList view = endpoint.View!; - view.offset -= removed; - view.size += removed; - leftEndIndex++; - } - while (rightEndIndex < viewCount && (endpoint = rightEnds![rightEndIndex]).Index < realindex) - { - LinkedList view = endpoint.View!; - view.size -= removed; - rightEndIndex++; - } + leftEndIndex2++; } - if (viewCount > 0) - { - while (leftEndIndex2 < viewCount && (_ = leftEnds![leftEndIndex2]).Index <= realindex) - { - leftEndIndex2++; - } - while (rightEndIndex2 < viewCount && (_ = rightEnds![rightEndIndex2]).Index < realindex - 1) - { - rightEndIndex2++; - } + while (rightEndIndex2 < viewCount && (_ = rightEnds![rightEndIndex2]).Index < realindex - 1) + { + rightEndIndex2++; } } - internal void UpdateViewSizesAndCounts(int removed, int realindex) + } + internal void UpdateViewSizesAndCounts(int removed, int realindex) + { + if (viewCount > 0) { - if (viewCount > 0) + Position endpoint; + while (leftEndIndex < viewCount && (endpoint = leftEnds![leftEndIndex]).Index <= realindex) { - Position endpoint; - while (leftEndIndex < viewCount && (endpoint = leftEnds![leftEndIndex]).Index <= realindex) - { - LinkedList view = endpoint.View!; - view.offset = view.Offset - removed; - view.size += removed; - leftEndIndex++; - } - while (rightEndIndex < viewCount && (endpoint = rightEnds![rightEndIndex]).Index < realindex) - { - LinkedList view = endpoint.View!; - view.size -= removed; - rightEndIndex++; - } + LinkedList view = endpoint.View!; + view.offset = view.Offset - removed; + view.size += removed; + leftEndIndex++; + } + while (rightEndIndex < viewCount && (endpoint = rightEnds![rightEndIndex]).Index < realindex) + { + LinkedList view = endpoint.View!; + view.size -= removed; + rightEndIndex++; } } - internal void UpdateSentinels(int realindex, Node newstart, Node newend) + } + internal void UpdateSentinels(int realindex, Node newstart, Node newend) + { + if (viewCount > 0) { - if (viewCount > 0) + Position endpoint; + while (leftEndIndex2 < viewCount && (endpoint = leftEnds![leftEndIndex2]).Index <= realindex) { - Position endpoint; - while (leftEndIndex2 < viewCount && (endpoint = leftEnds![leftEndIndex2]).Index <= realindex) - { - LinkedList view = endpoint.View!; - view.startsentinel = newstart; - leftEndIndex2++; - } - while (rightEndIndex2 < viewCount && (endpoint = rightEnds![rightEndIndex2]).Index < realindex - 1) - { - LinkedList view = endpoint.View!; - view.endsentinel = newend; - rightEndIndex2++; - } + LinkedList view = endpoint.View!; + view.startsentinel = newstart; + leftEndIndex2++; + } + while (rightEndIndex2 < viewCount && (endpoint = rightEnds![rightEndIndex2]).Index < realindex - 1) + { + LinkedList view = endpoint.View!; + view.endsentinel = newend; + rightEndIndex2++; } } - } - #endregion - #region Range nested class + } + #endregion - private class Range : DirectedCollectionValueBase, IDirectedCollectionValue - { - // int start; - private readonly int count, rangestamp; - private readonly Node? startnode, endnode; - private readonly LinkedList list; - private bool forwards; + #region Range nested class - internal Range(LinkedList list, int start, int count, bool forwards) + private class Range : DirectedCollectionValueBase, IDirectedCollectionValue + { + // int start; + private readonly int count, rangestamp; + private readonly Node? startnode, endnode; + private readonly LinkedList list; + private bool forwards; + + internal Range(LinkedList list, int start, int count, bool forwards) + { + this.list = list; + rangestamp = list.underlying != null ? list.underlying.stamp : list.stamp; + // this.start = start; + this.count = count; + this.forwards = forwards; + if (count > 0) { - this.list = list; - rangestamp = list.underlying != null ? list.underlying.stamp : list.stamp; - // this.start = start; - this.count = count; - this.forwards = forwards; - if (count > 0) - { - startnode = list.Get(start); - endnode = list.Get(start + count - 1); - } + startnode = list.Get(start); + endnode = list.Get(start + count - 1); } + } - public override bool IsEmpty { get { list.ModifyCheck(rangestamp); return count == 0; } } + public override bool IsEmpty { get { list.ModifyCheck(rangestamp); return count == 0; } } - public override int Count { get { list.ModifyCheck(rangestamp); return count; } } + public override int Count { get { list.ModifyCheck(rangestamp); return count; } } - public override Speed CountSpeed { get { list.ModifyCheck(rangestamp); return Speed.Constant; } } + public override Speed CountSpeed { get { list.ModifyCheck(rangestamp); return Speed.Constant; } } - public override T Choose() + public override T Choose() + { + list.ModifyCheck(rangestamp); + if (count > 0) { - list.ModifyCheck(rangestamp); - if (count > 0) - { - return startnode!.item; - } - - throw new NoSuchItemException(); + return startnode!.item; } - public override SCG.IEnumerator GetEnumerator() - { - int togo = count; - - list.ModifyCheck(rangestamp); - if (togo == 0) - { - yield break; - } + throw new NoSuchItemException(); + } - Node cursor = (forwards ? startnode : endnode)!; + public override SCG.IEnumerator GetEnumerator() + { + int togo = count; - yield return cursor.item; - while (--togo > 0) - { - cursor = (forwards ? cursor.next : cursor.prev)!; - list.ModifyCheck(rangestamp); - yield return cursor.item; - } + list.ModifyCheck(rangestamp); + if (togo == 0) + { + yield break; } + Node cursor = (forwards ? startnode : endnode)!; - public override IDirectedCollectionValue Backwards() + yield return cursor.item; + while (--togo > 0) { + cursor = (forwards ? cursor.next : cursor.prev)!; list.ModifyCheck(rangestamp); - - Range b = (Range)MemberwiseClone(); - - b.forwards = !forwards; - return b; + yield return cursor.item; } + } - IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } + public override IDirectedCollectionValue Backwards() + { + list.ModifyCheck(rangestamp); + Range b = (Range)MemberwiseClone(); - public override Direction Direction => forwards ? Direction.Forwards : Direction.Backwards; + b.forwards = !forwards; + return b; } - #endregion + IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } - #region IDisposable Members - /// - /// Invalidate this list. If a view, just invalidate the view. - /// If not a view, invalidate the list and all views on it. - /// - public virtual void Dispose() - { - Dispose(false); - } + public override Direction Direction => forwards ? Direction.Forwards : Direction.Backwards; + } - private void Dispose(bool disposingUnderlying) - { - if (isValid) - { - if (underlying != null) - { - isValid = false; - if (!disposingUnderlying && views != null) - { - views.Remove(myWeakReference!); - } - endsentinel = null; - startsentinel = null; - underlying = null; - views = null; - myWeakReference = null; - } - else - { - //isValid = false; - //endsentinel = null; - //startsentinel = null; - if (views != null) - { - foreach (LinkedList view in views) - { - view.Dispose(true); - } - } - //views = null; - Clear(); - } - } - } + #endregion - #endregion IDisposable stuff + #region IDisposable Members - #region IList Members + /// + /// Invalidate this list. If a view, just invalidate the view. + /// If not a view, invalidate the list and all views on it. + /// + public virtual void Dispose() + { + Dispose(false); + } - /// - /// - /// if this list is empty. - /// The first item in this list. - public virtual T First + private void Dispose(bool disposingUnderlying) + { + if (isValid) { - get + if (underlying != null) { - ValidityCheck(); - if (size == 0) + isValid = false; + if (!disposingUnderlying && views != null) { - throw new NoSuchItemException(); + views.Remove(myWeakReference!); } - return startsentinel!.next!.item; + endsentinel = null; + startsentinel = null; + underlying = null; + views = null; + myWeakReference = null; } - } - - - /// - /// - /// if this list is empty. - /// The last item in this list. - public virtual T Last - { - get + else { - ValidityCheck(); - if (size == 0) + //isValid = false; + //endsentinel = null; + //startsentinel = null; + if (views != null) { - throw new NoSuchItemException(); + foreach (LinkedList view in views) + { + view.Dispose(true); + } } - - return endsentinel!.prev!.item; + //views = null; + Clear(); } } + } - /// - /// Since Add(T item) always add at the end of the list, - /// this describes if list has FIFO or LIFO semantics. - /// - /// True if the Remove() operation removes from the - /// start of the list, false if it removes from the end. THe default for a new linked list is true. - public virtual bool FIFO - { - get { ValidityCheck(); return fIFO; } - set { UpdateCheck(); fIFO = value; } - } + #endregion IDisposable stuff - /// - /// - /// - public virtual bool IsFixedSize - { - get { ValidityCheck(); return false; } - } + #region IList Members - /// - /// On this list, this indexer is read/write. - /// if i is negative or - /// >= the size of the collection. - /// - /// The i'th item of this list. - /// The index of the item to fetch or store. - public virtual T this[int index] + /// + /// + /// if this list is empty. + /// The first item in this list. + public virtual T First + { + get { - get { ValidityCheck(); return Get(index).item; } - set + ValidityCheck(); + if (size == 0) { - UpdateCheck(); - Node n = Get(index); - // - T item = n.item; - - n.item = value; - (underlying ?? this).RaiseForSetThis(index, value, item); + throw new NoSuchItemException(); } + + return startsentinel!.next!.item; } + } - /// - /// - /// - /// - public virtual Speed IndexingSpeed => Speed.Linear; - /// - /// Insert an item at a specific index location in this list. - /// if i is negative or - /// > the size of the collection. - /// The index at which to insert. - /// The item to insert. - public virtual void Insert(int i, T item) + /// + /// + /// if this list is empty. + /// The last item in this list. + public virtual T Last + { + get { - UpdateCheck(); - Insert(i, (i == size ? endsentinel : Get(i))!, item); - if (ActiveEvents != EventType.None) + ValidityCheck(); + if (size == 0) { - (underlying ?? this).RaiseForInsert(i + Offset, item); + throw new NoSuchItemException(); } + + return endsentinel!.prev!.item; } + } - /// - /// Insert an item at the end of a compatible view, used as a pointer. - /// The pointer must be a view on the same list as - /// this and the endpoint of pointer must be - /// a valid insertion point of this - /// - /// If pointer - /// is not a view on the same list as this - /// ?????? if the endpoint of - /// pointer is not inside this - /// if the list has - /// AllowsDuplicates==false and the item is - /// already in the list. - /// - /// - public void Insert(IList pointer, T item) + /// + /// Since Add(T item) always add at the end of the list, + /// this describes if list has FIFO or LIFO semantics. + /// + /// True if the Remove() operation removes from the + /// start of the list, false if it removes from the end. THe default for a new linked list is true. + public virtual bool FIFO + { + get { ValidityCheck(); return fIFO; } + set { UpdateCheck(); fIFO = value; } + } + + /// + /// + /// + public virtual bool IsFixedSize + { + get { ValidityCheck(); return false; } + } + + /// + /// On this list, this indexer is read/write. + /// if i is negative or + /// >= the size of the collection. + /// + /// The i'th item of this list. + /// The index of the item to fetch or store. + public virtual T this[int index] + { + get { ValidityCheck(); return Get(index).item; } + set { UpdateCheck(); - if ((pointer == null) || ((pointer.Underlying ?? pointer) != (underlying ?? this))) - { - throw new IncompatibleViewException(); - } -#warning INEFFICIENT - //TODO: make this efficient (the whole point of the method: - //Do NOT use Insert, but insert the node at pointer.endsentinel, checking - //via the ordering that this is a valid insertion point - Insert(pointer.Offset + pointer.Count - Offset, item); + Node n = Get(index); + // + T item = n.item; + + n.item = value; + (underlying ?? this).RaiseForSetThis(index, value, item); } + } - /// - /// Insert into this list all items from an enumerable collection starting - /// at a particular index. - /// if i is negative or - /// > the size of the collection. - /// - /// Index to start inserting at - /// Items to insert - public virtual void InsertAll(int i, SCG.IEnumerable items) + /// + /// + /// + /// + public virtual Speed IndexingSpeed => Speed.Linear; + + /// + /// Insert an item at a specific index location in this list. + /// if i is negative or + /// > the size of the collection. + /// The index at which to insert. + /// The item to insert. + public virtual void Insert(int i, T item) + { + UpdateCheck(); + Insert(i, (i == size ? endsentinel : Get(i))!, item); + if (ActiveEvents != EventType.None) { - InsertAll(i, items, true); + (underlying ?? this).RaiseForInsert(i + Offset, item); } + } - private void InsertAll(int i, SCG.IEnumerable items, bool insertion) + /// + /// Insert an item at the end of a compatible view, used as a pointer. + /// The pointer must be a view on the same list as + /// this and the endpoint of pointer must be + /// a valid insertion point of this + /// + /// If pointer + /// is not a view on the same list as this + /// ?????? if the endpoint of + /// pointer is not inside this + /// if the list has + /// AllowsDuplicates==false and the item is + /// already in the list. + /// + /// + public void Insert(IList pointer, T item) + { + UpdateCheck(); + if ((pointer == null) || ((pointer.Underlying ?? pointer) != (underlying ?? this))) { - UpdateCheck(); - Node succ, node, pred; - int count = 0; - succ = (i == size ? endsentinel : Get(i))!; - pred = node = succ.prev!; + throw new IncompatibleViewException(); + } +#warning INEFFICIENT + //TODO: make this efficient (the whole point of the method: + //Do NOT use Insert, but insert the node at pointer.endsentinel, checking + //via the ordering that this is a valid insertion point + Insert(pointer.Offset + pointer.Count - Offset, item); + } - foreach (T item in items) - { - Node tmp = new Node(item, node, null); - node.next = tmp; - count++; - node = tmp; - } - if (count == 0) - { - return; - } + /// + /// Insert into this list all items from an enumerable collection starting + /// at a particular index. + /// if i is negative or + /// > the size of the collection. + /// + /// Index to start inserting at + /// Items to insert + public virtual void InsertAll(int i, SCG.IEnumerable items) + { + InsertAll(i, items, true); + } - succ.prev = node; - node.next = succ; - size += count; - if (underlying != null) - { - underlying.size += count; - } + private void InsertAll(int i, SCG.IEnumerable items, bool insertion) + { + UpdateCheck(); + Node succ, node, pred; + int count = 0; + succ = (i == size ? endsentinel : Get(i))!; + pred = node = succ.prev!; - if (count > 0) - { - FixViewsAfterInsert(succ, pred, count, offset + i); - RaiseForInsertAll(pred, i, count, insertion); - } + foreach (T item in items) + { + Node tmp = new(item, node, null); + node.next = tmp; + count++; + node = tmp; + } + if (count == 0) + { + return; + } + + succ.prev = node; + node.next = succ; + size += count; + if (underlying != null) + { + underlying.size += count; + } + + if (count > 0) + { + FixViewsAfterInsert(succ, pred, count, offset + i); + RaiseForInsertAll(pred, i, count, insertion); } + } - private void RaiseForInsertAll(Node node, int i, int added, bool insertion) + private void RaiseForInsertAll(Node node, int i, int added, bool insertion) + { + if (ActiveEvents != 0) { - if (ActiveEvents != 0) + int index = Offset + i; + if ((ActiveEvents & (EventType.Added | EventType.Inserted)) != 0) { - int index = Offset + i; - if ((ActiveEvents & (EventType.Added | EventType.Inserted)) != 0) + for (int j = index; j < index + added; j++) { - for (int j = index; j < index + added; j++) - { #warning must we check stamps here? - node = node.next!; - T item = node!.item; - if (insertion) - { - RaiseItemInserted(item, j); - } - - RaiseItemsAdded(item, 1); + node = node.next!; + T item = node!.item; + if (insertion) + { + RaiseItemInserted(item, j); } - } - RaiseCollectionChanged(); + RaiseItemsAdded(item, 1); + } } + + RaiseCollectionChanged(); } + } - /// - /// Insert an item at the front of this list. - /// - /// The item to insert. - public virtual void InsertFirst(T item) + /// + /// Insert an item at the front of this list. + /// + /// The item to insert. + public virtual void InsertFirst(T item) + { + UpdateCheck(); + Insert(0, startsentinel!.next!, item); + if (ActiveEvents != EventType.None) { - UpdateCheck(); - Insert(0, startsentinel!.next!, item); - if (ActiveEvents != EventType.None) - { - (underlying ?? this).RaiseForInsert(0 + Offset, item); - } + (underlying ?? this).RaiseForInsert(0 + Offset, item); } + } - /// - /// Insert an item at the back of this list. - /// - /// The item to insert. - public virtual void InsertLast(T item) + /// + /// Insert an item at the back of this list. + /// + /// The item to insert. + public virtual void InsertLast(T item) + { + UpdateCheck(); + Insert(size, endsentinel!, item); + if (ActiveEvents != EventType.None) { - UpdateCheck(); - Insert(size, endsentinel!, item); - if (ActiveEvents != EventType.None) - { - (underlying ?? this).RaiseForInsert(size - 1 + Offset, item); - } + (underlying ?? this).RaiseForInsert(size - 1 + Offset, item); } + } - /// - /// Create a new list consisting of the results of mapping all items of this - /// list. - /// - /// The delegate defining the map. - /// The new list. - public IList Map(Func mapper) - { - ValidityCheck(); + /// + /// Create a new list consisting of the results of mapping all items of this + /// list. + /// + /// The delegate defining the map. + /// The new list. + public IList Map(Func mapper) + { + ValidityCheck(); - LinkedList retval = new LinkedList(); - return Map(mapper, retval); - } + LinkedList retval = new(); + return Map(mapper, retval); + } - /// - /// Create a new list consisting of the results of mapping all items of this - /// list. The new list will use a specified equalityComparer for the item type. - /// - /// The type of items of the new list - /// The delegate defining the map. - /// The equalityComparer to use for the new list - /// The new list. - public IList Map(Func mapper, SCG.IEqualityComparer equalityComparer) - { - ValidityCheck(); + /// + /// Create a new list consisting of the results of mapping all items of this + /// list. The new list will use a specified equalityComparer for the item type. + /// + /// The type of items of the new list + /// The delegate defining the map. + /// The equalityComparer to use for the new list + /// The new list. + public IList Map(Func mapper, SCG.IEqualityComparer equalityComparer) + { + ValidityCheck(); + + LinkedList retval = new(equalityComparer); + return Map(mapper, retval); + } - LinkedList retval = new LinkedList(equalityComparer); - return Map(mapper, retval); + private IList Map(Func mapper, LinkedList retval) + { + if (size == 0) + { + return retval; } - private IList Map(Func mapper, LinkedList retval) + int stamp = this.stamp; + Node cursor = startsentinel!.next!; + LinkedList.Node mcursor = retval.startsentinel!; + + + while (cursor != endsentinel) { - if (size == 0) - { - return retval; - } + V v = mapper(cursor!.item); + ModifyCheck(stamp); + mcursor.next = new LinkedList.Node(v, mcursor, null); + cursor = cursor.next!; + mcursor = mcursor.next; - int stamp = this.stamp; - Node cursor = startsentinel!.next!; - LinkedList.Node mcursor = retval.startsentinel!; + } - while (cursor != endsentinel) - { - V v = mapper(cursor!.item); - ModifyCheck(stamp); - mcursor.next = new LinkedList.Node(v, mcursor, null); - cursor = cursor.next!; - mcursor = mcursor.next; + retval.endsentinel!.prev = mcursor; + mcursor.next = retval.endsentinel; + retval.size = size; + return retval; + } - } + /// + /// Remove one item from the list: from the front if FIFO + /// is true, else from the back. + /// if this list is empty. + /// + /// The removed item. + public virtual T Remove() + { + UpdateCheck(); + if (size == 0) + { + throw new NoSuchItemException("List is empty"); + } + T item = fIFO ? Remove(startsentinel!.next!, 0) : Remove(endsentinel!.prev!, size - 1); - retval.endsentinel!.prev = mcursor; - mcursor.next = retval.endsentinel; - retval.size = size; - return retval; + (underlying ?? this).RaiseForRemove(item); + return item; + } + + /// + /// Remove one item from the front of the list. + /// if this list is empty. + /// + /// The removed item. + public virtual T RemoveFirst() + { + UpdateCheck(); + if (size == 0) + { + throw new NoSuchItemException("List is empty"); } - /// - /// Remove one item from the list: from the front if FIFO - /// is true, else from the back. - /// if this list is empty. - /// - /// The removed item. - public virtual T Remove() + T item = Remove(startsentinel!.next!, 0); + + if (ActiveEvents != EventType.None) { - UpdateCheck(); - if (size == 0) - { - throw new NoSuchItemException("List is empty"); - } + (underlying ?? this).RaiseForRemoveAt(Offset, item); + } - T item = fIFO ? Remove(startsentinel!.next!, 0) : Remove(endsentinel!.prev!, size - 1); + return item; + } - (underlying ?? this).RaiseForRemove(item); - return item; + /// + /// Remove one item from the back of the list. + /// if this list is empty. + /// + /// The removed item. + public virtual T RemoveLast() + { + UpdateCheck(); + if (size == 0) + { + throw new NoSuchItemException("List is empty"); } - /// - /// Remove one item from the front of the list. - /// if this list is empty. - /// - /// The removed item. - public virtual T RemoveFirst() + T item = Remove(endsentinel!.prev!, size - 1); + + if (ActiveEvents != EventType.None) { - UpdateCheck(); - if (size == 0) - { - throw new NoSuchItemException("List is empty"); - } + (underlying ?? this).RaiseForRemoveAt(size + Offset, item); + } - T item = Remove(startsentinel!.next!, 0); + return item; + } - if (ActiveEvents != EventType.None) - { - (underlying ?? this).RaiseForRemoveAt(Offset, item); - } + /// + /// Create a list view on this list. + /// + /// if the start or count is negative + /// if the range does not fit within list. + /// The index in this list of the start of the view. + /// The size of the view. + /// The new list view. + public virtual IList? View(int start, int count) + { + CheckRange(start, count); + ValidityCheck(); + views ??= new WeakViewList>(); + + LinkedList retval = (LinkedList)MemberwiseClone(); + retval.underlying = underlying ?? (this); + retval.offset = offset + start; + retval.size = count; + GetPair(start - 1, start + count, out retval.startsentinel, out retval.endsentinel, + [-1, size], [startsentinel!, endsentinel!]); + //retval.startsentinel = start == 0 ? startsentinel : get(start - 1); + //retval.endsentinel = start + count == size ? endsentinel : get(start + count); + + //TODO: for the purpose of Dispose, we need to retain a ref to the node + retval.myWeakReference = views.Add(retval); + return retval; + } + + /// + /// Create a list view on this list containing the (first) occurrence of a particular item. + /// + /// if the item is not in this list. + /// The item to find. + /// The new list view. + public virtual IList? ViewOf(T item) + { - return item; + int index = 0; + Node n = startsentinel!.next!; + if (!Find(item, ref n, ref index)) + { + return null; } + //TODO: optimize with getpair! + return View(index, 1); + } - /// - /// Remove one item from the back of the list. - /// if this list is empty. - /// - /// The removed item. - public virtual T RemoveLast() + /// + /// Create a list view on this list containing the last occurrence of a particular item. + /// if the item is not in this list. + /// + /// The item to find. + /// The new list view. + public virtual IList? LastViewOf(T item) + { + + int index = size - 1; + Node n = endsentinel!.prev!; + if (!DnIf(item, ref n, ref index)) { - UpdateCheck(); - if (size == 0) - { - throw new NoSuchItemException("List is empty"); - } + return null; + } - T item = Remove(endsentinel!.prev!, size - 1); + return View(index, 1); + } - if (ActiveEvents != EventType.None) - { - (underlying ?? this).RaiseForRemoveAt(size + Offset, item); - } + /// + /// Null if this list is not a view. + /// + /// Underlying list for view. + public virtual IList? Underlying { get { ValidityCheck(); return underlying; } } - return item; - } + /// + /// + /// + /// + public virtual bool IsValid => isValid; - /// - /// Create a list view on this list. - /// - /// if the start or count is negative - /// if the range does not fit within list. - /// The index in this list of the start of the view. - /// The size of the view. - /// The new list view. - public virtual IList? View(int start, int count) + /// + /// + /// Offset for this list view or 0 for a underlying list. + public virtual int Offset + { + get { - CheckRange(start, count); ValidityCheck(); - views ??= new WeakViewList>(); - - LinkedList retval = (LinkedList)MemberwiseClone(); - retval.underlying = underlying ?? (this); - retval.offset = offset + start; - retval.size = count; - GetPair(start - 1, start + count, out retval.startsentinel, out retval.endsentinel, - new int[] { -1, size }, new Node[] { startsentinel!, endsentinel! }); - //retval.startsentinel = start == 0 ? startsentinel : get(start - 1); - //retval.endsentinel = start + count == size ? endsentinel : get(start + count); - - //TODO: for the purpose of Dispose, we need to retain a ref to the node - retval.myWeakReference = views.Add(retval); - return retval; + + return offset; } + } - /// - /// Create a list view on this list containing the (first) occurrence of a particular item. - /// - /// if the item is not in this list. - /// The item to find. - /// The new list view. - public virtual IList? ViewOf(T item) + /// + /// Slide this list view along the underlying list. + /// + /// if this list is not a view. + /// if the operation + /// would bring either end of the view outside the underlying list. + /// The signed amount to slide: positive to slide + /// towards the end. + public IList Slide(int offset) + { + if (!TrySlide(offset, size)) { - - int index = 0; - Node n = startsentinel!.next!; - if (!Find(item, ref n, ref index)) - { - return null; - } - //TODO: optimize with getpair! - return View(index, 1); + throw new ArgumentOutOfRangeException(nameof(offset)); } - /// - /// Create a list view on this list containing the last occurrence of a particular item. - /// if the item is not in this list. - /// - /// The item to find. - /// The new list view. - public virtual IList? LastViewOf(T item) + return this; + } + + //TODO: more test cases + /// + /// Slide this list view along the underlying list, perhaps changing its size. + /// + /// if this list is not a view. + /// if the operation + /// would bring either end of the view outside the underlying list. + /// The signed amount to slide: positive to slide + /// towards the end. + /// The new size of the view. + public IList Slide(int offset, int size) + { + if (!TrySlide(offset, size)) { + throw new ArgumentOutOfRangeException(); + } - int index = size - 1; - Node n = endsentinel!.prev!; - if (!DnIf(item, ref n, ref index)) - { - return null; - } + return this; + } + + /// + /// + /// + /// + /// + public virtual bool TrySlide(int offset) { return TrySlide(offset, size); } + + /// + /// + /// + /// + /// + /// + public virtual bool TrySlide(int offset, int size) + { + UpdateCheck(); + if (underlying == null) + { + throw new NotAViewException("List not a view"); + } - return View(index, 1); + if (offset + this.offset < 0 || offset + this.offset + size > underlying.size) + { + return false; } - /// - /// Null if this list is not a view. - /// - /// Underlying list for view. - public virtual IList? Underlying { get { ValidityCheck(); return underlying; } } + int oldoffset = this.offset; + GetPair(offset - 1, offset + size, out startsentinel, out endsentinel, + [-oldoffset - 1, -1, this.size, underlying.size - oldoffset], + [underlying.startsentinel!, startsentinel!, endsentinel!, underlying.endsentinel!]); - /// - /// - /// - /// - public virtual bool IsValid => isValid; + this.size = size; + this.offset += offset; + return true; + } - /// - /// - /// Offset for this list view or 0 for a underlying list. - public virtual int Offset + + //TODO: improve the complexity of the implementation + /// + /// + /// Returns null if otherView is strictly to the left of this view + /// + /// + /// If otherView does not have the same underlying list as this + /// + public virtual IList? Span(IList otherView) + { + if ((otherView == null) || ((otherView.Underlying ?? otherView) != (underlying ?? this))) { - get - { - ValidityCheck(); + throw new IncompatibleViewException(); + } - return offset; - } + if (otherView.Offset + otherView.Count - Offset < 0) + { + return null; } - /// - /// Slide this list view along the underlying list. - /// - /// if this list is not a view. - /// if the operation - /// would bring either end of the view outside the underlying list. - /// The signed amount to slide: positive to slide - /// towards the end. - public IList Slide(int offset) + return (underlying ?? this).View(Offset, otherView.Offset + otherView.Count - Offset); + } + + + //Question: should we swap items or move nodes around? + //The first seems much more efficient unless the items are value types + //with a large memory footprint. + //(Swapping will do count*3/2 T assignments, linking around will do + // 4*count ref assignments; note that ref assignments are more expensive + //than copying non-ref bits) + /// + /// Reverse the list so the items are in the opposite sequence order. + /// + public virtual void Reverse() + { + UpdateCheck(); + if (size == 0) { - if (!TrySlide(offset, size)) + return; + } + + Position[]? positions = null; + int poslow = 0, poshigh = 0; + if (views != null) + { + CircularQueue? _positions = null; + foreach (LinkedList view in views) { - throw new ArgumentOutOfRangeException(nameof(offset)); + if (view != this) + { + switch (ViewPosition(view)) + { + case MutualViewPosition.ContainedIn: + (_positions ??= new CircularQueue()).Enqueue(new Position(view, true)); + _positions.Enqueue(new Position(view, false)); + break; + case MutualViewPosition.Overlapping: + view.Dispose(); + break; + case MutualViewPosition.Contains: + case MutualViewPosition.NonOverlapping: + break; + } + } + } + if (_positions != null) + { + positions = _positions.ToArray(); + Sorting.IntroSort(positions, 0, positions.Length, PositionComparer.Default); + poshigh = positions.Length - 1; } - - return this; } - //TODO: more test cases - /// - /// Slide this list view along the underlying list, perhaps changing its size. - /// - /// if this list is not a view. - /// if the operation - /// would bring either end of the view outside the underlying list. - /// The signed amount to slide: positive to slide - /// towards the end. - /// The new size of the view. - public IList Slide(int offset, int size) + Node a = Get(0), b = Get(size - 1); + for (int i = 0; i < size / 2; i++) { - if (!TrySlide(offset, size)) + T swap; + swap = a.item; a.item = b.item; b.item = swap; + + if (positions != null) { - throw new ArgumentOutOfRangeException(); + MirrorViewSentinelsForReverse(positions, ref poslow, ref poshigh, a, b, i); } - return this; + a = a.next!; b = b.prev!; + } + if (positions != null && size % 2 != 0) + { + MirrorViewSentinelsForReverse(positions, ref poslow, ref poshigh, a, b, size / 2); } + (underlying ?? this).RaiseCollectionChanged(); + } - /// - /// - /// - /// - /// - public virtual bool TrySlide(int offset) { return TrySlide(offset, size); } + private void MirrorViewSentinelsForReverse(Position[] positions, ref int poslow, ref int poshigh, Node a, Node b, int i) + { - /// - /// - /// - /// - /// - /// - public virtual bool TrySlide(int offset, int size) + int aindex = offset + i, bindex = offset + size - 1 - i; + Position pos; + + while (poslow <= poshigh && (pos = positions[poslow]).Index == aindex) { - UpdateCheck(); - if (underlying == null) + //TODO: Note: in the case og hashed linked list, if this.offset == null, but pos.View.offset!=null + //we may at this point compute this.offset and non-null values of aindex and bindex + if (pos.Left) { - throw new NotAViewException("List not a view"); + pos.View!.endsentinel = b.next!; } - - if (offset + this.offset < 0 || offset + this.offset + size > underlying.size) + else { - return false; + pos.View!.startsentinel = b.prev; + pos.View.offset = bindex; } - - int oldoffset = this.offset; - GetPair(offset - 1, offset + size, out startsentinel, out endsentinel, - new int[] { -oldoffset - 1, -1, this.size, underlying.size - oldoffset }, - new Node[] { underlying.startsentinel!, startsentinel!, endsentinel!, underlying.endsentinel! }); - - this.size = size; - this.offset += offset; - return true; + poslow++; } - - //TODO: improve the complexity of the implementation - /// - /// - /// Returns null if otherView is strictly to the left of this view - /// - /// - /// If otherView does not have the same underlying list as this - /// - public virtual IList? Span(IList otherView) + while (poslow < poshigh && (pos = positions[poshigh]).Index == bindex) { - if ((otherView == null) || ((otherView.Underlying ?? otherView) != (underlying ?? this))) + if (pos.Left) { - throw new IncompatibleViewException(); + pos.View!.endsentinel = a.next!; } - - if (otherView.Offset + otherView.Count - Offset < 0) + else { - return null; + pos.View!.startsentinel = a.prev; + pos.View.offset = aindex; } - - return (underlying ?? this).View(Offset, otherView.Offset + otherView.Count - Offset); + poshigh--; } + } + /// + /// Check if this list is sorted according to the default sorting order + /// for the item type T, as defined by the class + /// + /// if T is not comparable + /// True if the list is sorted, else false. + public bool IsSorted() { return IsSorted(SCG.Comparer.Default); } - //Question: should we swap items or move nodes around? - //The first seems much more efficient unless the items are value types - //with a large memory footprint. - //(Swapping will do count*3/2 T assignments, linking around will do - // 4*count ref assignments; note that ref assignments are more expensive - //than copying non-ref bits) - /// - /// Reverse the list so the items are in the opposite sequence order. - /// - public virtual void Reverse() + /// + /// Check if this list is sorted according to a specific sorting order. + /// + /// The comparer defining the sorting order. + /// True if the list is sorted, else false. + public virtual bool IsSorted(SCG.IComparer c) + { + ValidityCheck(); + if (size <= 1) { - UpdateCheck(); - if (size == 0) - { - return; - } + return true; + } - Position[]? positions = null; - int poslow = 0, poshigh = 0; - if (views != null) - { - CircularQueue? _positions = null; - foreach (LinkedList view in views) - { - if (view != this) - { - switch (ViewPosition(view)) - { - case MutualViewPosition.ContainedIn: - (_positions ??= new CircularQueue()).Enqueue(new Position(view, true)); - _positions.Enqueue(new Position(view, false)); - break; - case MutualViewPosition.Overlapping: - view.Dispose(); - break; - case MutualViewPosition.Contains: - case MutualViewPosition.NonOverlapping: - break; - } - } - } - if (_positions != null) - { - positions = _positions.ToArray(); - Sorting.IntroSort(positions, 0, positions.Length, PositionComparer.Default); - poshigh = positions.Length - 1; - } - } + Node node = startsentinel!.next!; + T prevItem = node!.item; - Node a = Get(0), b = Get(size - 1); - for (int i = 0; i < size / 2; i++) + node = node.next!; + while (node != endsentinel) + { + if (c.Compare(prevItem, node!.item) > 0) { - T swap; - swap = a.item; a.item = b.item; b.item = swap; - - if (positions != null) - { - MirrorViewSentinelsForReverse(positions, ref poslow, ref poshigh, a, b, i); - } - - a = a.next!; b = b.prev!; + return false; } - if (positions != null && size % 2 != 0) + else { - MirrorViewSentinelsForReverse(positions, ref poslow, ref poshigh, a, b, size / 2); + prevItem = node.item; + node = node.next!; } - (underlying ?? this).RaiseCollectionChanged(); } - private void MirrorViewSentinelsForReverse(Position[] positions, ref int poslow, ref int poshigh, Node a, Node b, int i) - { - - int aindex = offset + i, bindex = offset + size - 1 - i; - Position pos; + return true; + } - while (poslow <= poshigh && (pos = positions[poslow]).Index == aindex) - { - //TODO: Note: in the case og hashed linked list, if this.offset == null, but pos.View.offset!=null - //we may at this point compute this.offset and non-null values of aindex and bindex - if (pos.Left) - { - pos.View!.endsentinel = b.next!; - } - else - { - pos.View!.startsentinel = b.prev; - pos.View.offset = bindex; - } - poslow++; - } + /// + /// Sort the items of the list according to the default sorting order + /// for the item type T, as defined by the Comparer[T] class. + /// (). + /// The sorting is stable. + /// + /// if T is not comparable + public virtual void Sort() { Sort(SCG.Comparer.Default); } - while (poslow < poshigh && (pos = positions[poshigh]).Index == bindex) - { - if (pos.Left) - { - pos.View!.endsentinel = a.next!; - } - else - { - pos.View!.startsentinel = a.prev; - pos.View.offset = aindex; - } - poshigh--; - } + // Sort the linked list using mergesort + /// + /// Sort the items of the list according to a specific sorting order. + /// The sorting is stable. + /// + /// The comparer defining the sorting order. + public virtual void Sort(SCG.IComparer c) + { + UpdateCheck(); + if (size == 0) + { + return; } - /// - /// Check if this list is sorted according to the default sorting order - /// for the item type T, as defined by the class - /// - /// if T is not comparable - /// True if the list is sorted, else false. - public bool IsSorted() { return IsSorted(SCG.Comparer.Default); } + DisposeOverlappingViews(false); - /// - /// Check if this list is sorted according to a specific sorting order. - /// - /// The comparer defining the sorting order. - /// True if the list is sorted, else false. - public virtual bool IsSorted(SCG.IComparer c) + // Build a linked list of non-empty runs. + // The prev field in first node of a run points to next run's first node + Node runTail = startsentinel!.next!; + Node prevNode = startsentinel.next!; + + endsentinel!.prev!.next = null; + while (prevNode != null) { - ValidityCheck(); - if (size <= 1) + Node node = prevNode.next!; + + while (node != null && c.Compare(prevNode.item, node.item) <= 0) { - return true; + prevNode = node; + node = prevNode.next!; } - Node node = startsentinel!.next!; - T prevItem = node!.item; - - node = node.next!; - while (node != endsentinel) + // Completed a run; prevNode is the last node of that run + prevNode.next = null; // Finish the run + runTail!.prev = node!; // Link it into the chain of runs + runTail = node!; + if (c.Compare(endsentinel.prev.item, prevNode.item) <= 0) { - if (c.Compare(prevItem, node!.item) > 0) - { - return false; - } - else - { - prevItem = node.item; - node = node.next!; - } + endsentinel.prev = prevNode; // Update last pointer to point to largest } - return true; + prevNode = node!; // Start a new run } - /// - /// Sort the items of the list according to the default sorting order - /// for the item type T, as defined by the Comparer[T] class. - /// (). - /// The sorting is stable. - /// - /// if T is not comparable - public virtual void Sort() { Sort(SCG.Comparer.Default); } - - // Sort the linked list using mergesort - /// - /// Sort the items of the list according to a specific sorting order. - /// The sorting is stable. - /// - /// The comparer defining the sorting order. - public virtual void Sort(SCG.IComparer c) + // Repeatedly merge runs two and two, until only one run remains + while (startsentinel.next!.prev != null) { - UpdateCheck(); - if (size == 0) - { - return; - } + Node run = startsentinel.next; + Node? newRunTail = null; - DisposeOverlappingViews(false); + while (run != null && run.prev != null) + { // At least two runs, merge + Node nextRun = run.prev.prev!; + Node newrun = MergeRuns(run, run.prev, c); - // Build a linked list of non-empty runs. - // The prev field in first node of a run points to next run's first node - Node runTail = startsentinel!.next!; - Node prevNode = startsentinel.next!; - - endsentinel!.prev!.next = null; - while (prevNode != null) - { - Node node = prevNode.next!; - - while (node != null && c.Compare(prevNode.item, node.item) <= 0) + if (newRunTail != null) { - prevNode = node; - node = prevNode.next!; + newRunTail.prev = newrun; } - - // Completed a run; prevNode is the last node of that run - prevNode.next = null; // Finish the run - runTail!.prev = node!; // Link it into the chain of runs - runTail = node!; - if (c.Compare(endsentinel.prev.item, prevNode.item) <= 0) + else { - endsentinel.prev = prevNode; // Update last pointer to point to largest + startsentinel.next = newrun; } - prevNode = node!; // Start a new run + newRunTail = newrun; + run = nextRun; } - // Repeatedly merge runs two and two, until only one run remains - while (startsentinel.next!.prev != null) + if (run != null) // Add the last run, if any { - Node run = startsentinel.next; - Node? newRunTail = null; - - while (run != null && run.prev != null) - { // At least two runs, merge - Node nextRun = run.prev.prev!; - Node newrun = MergeRuns(run, run.prev, c); - - if (newRunTail != null) - { - newRunTail.prev = newrun; - } - else - { - startsentinel.next = newrun; - } + newRunTail!.prev = run; + } + } - newRunTail = newrun; - run = nextRun; - } + endsentinel.prev.next = endsentinel; + startsentinel.next.prev = startsentinel; - if (run != null) // Add the last run, if any - { - newRunTail!.prev = run; - } - } + //assert invariant(); + //assert isSorted(); - endsentinel.prev.next = endsentinel; - startsentinel.next.prev = startsentinel; + (underlying ?? this).RaiseCollectionChanged(); + } - //assert invariant(); - //assert isSorted(); + private static Node MergeRuns(Node run1, Node run2, SCG.IComparer c) + { + //assert run1 != null && run2 != null; + Node prev; + bool prev1; // is prev from run1? - (underlying ?? this).RaiseCollectionChanged(); + if (c.Compare(run1.item, run2.item) <= 0) + { + prev = run1; + prev1 = true; + run1 = run1.next!; } - - private static Node MergeRuns(Node run1, Node run2, SCG.IComparer c) + else { - //assert run1 != null && run2 != null; - Node prev; - bool prev1; // is prev from run1? - - if (c.Compare(run1.item, run2.item) <= 0) - { - prev = run1; - prev1 = true; - run1 = run1.next!; - } - else - { - prev = run2; - prev1 = false; - run2 = run2.next!; - } + prev = run2; + prev1 = false; + run2 = run2.next!; + } - Node start = prev; + Node start = prev; - //assert start != null; - start.prev = null; - while (run1 != null && run2 != null) + //assert start != null; + start.prev = null; + while (run1 != null && run2 != null) + { + if (prev1) { - if (prev1) + //assert prev.next == run1; + //Comparable run2item = (Comparable)run2.item; + while (run1 != null && c.Compare(run2.item, run1.item) >= 0) { - //assert prev.next == run1; - //Comparable run2item = (Comparable)run2.item; - while (run1 != null && c.Compare(run2.item, run1.item) >= 0) - { - prev = run1; - run1 = prev.next!; - } - - if (run1 != null) - { // prev.item <= run2.item < run1.item; insert run2 - prev.next = run2; - run2.prev = prev; - prev = run2; - run2 = prev.next!; - prev1 = false; - } + prev = run1; + run1 = prev.next!; } - else - { - //assert prev.next == run2; - //Comparable run1item = (Comparable)run1.item; - while (run2 != null && c.Compare(run1.item, run2.item) > 0) - { - prev = run2; - run2 = prev.next!; - } - if (run2 != null) - { // prev.item < run1.item <= run2.item; insert run1 - prev.next = run1; - run1.prev = prev; - prev = run1; - run1 = prev.next!; - prev1 = true; - } + if (run1 != null) + { // prev.item <= run2.item < run1.item; insert run2 + prev.next = run2; + run2.prev = prev; + prev = run2; + run2 = prev.next!; + prev1 = false; } } + else + { + //assert prev.next == run2; + //Comparable run1item = (Comparable)run1.item; + while (run2 != null && c.Compare(run1.item, run2.item) > 0) + { + prev = run2; + run2 = prev.next!; + } - //assert !(run1 != null && prev1) && !(run2 != null && !prev1); - if (run1 != null) - { // last run2 < all of run1; attach run1 at end - prev.next = run1; - run1.prev = prev; - } - else if (run2 != null) - { // last run1 - prev.next = run2; - run2.prev = prev; + if (run2 != null) + { // prev.item < run1.item <= run2.item; insert run1 + prev.next = run1; + run1.prev = prev; + prev = run1; + run1 = prev.next!; + prev1 = true; + } } + } - return start; + //assert !(run1 != null && prev1) && !(run2 != null && !prev1); + if (run1 != null) + { // last run2 < all of run1; attach run1 at end + prev.next = run1; + run1.prev = prev; + } + else if (run2 != null) + { // last run1 + prev.next = run2; + run2.prev = prev; } - /// - /// Randomly shuffle the items of this list. - /// Will invalidate overlapping views??? - /// - public virtual void Shuffle() { Shuffle(new C5Random()); } + return start; + } + + /// + /// Randomly shuffle the items of this list. + /// Will invalidate overlapping views??? + /// + public virtual void Shuffle() { Shuffle(new C5Random()); } - /// - /// Shuffle the items of this list according to a specific random source. - /// Will invalidate overlapping views??? - /// - /// The random source. - public virtual void Shuffle(Random rnd) + /// + /// Shuffle the items of this list according to a specific random source. + /// Will invalidate overlapping views??? + /// + /// The random source. + public virtual void Shuffle(Random rnd) + { + UpdateCheck(); + if (size == 0) { - UpdateCheck(); - if (size == 0) - { - return; - } + return; + } - DisposeOverlappingViews(false); - ArrayList a = new ArrayList(); - a.AddAll(this); - a.Shuffle(rnd); - Node cursor = startsentinel!.next!; - int j = 0; - while (cursor != endsentinel) - { - cursor!.item = a[j++]; + DisposeOverlappingViews(false); + ArrayList a = new(); + a.AddAll(this); + a.Shuffle(rnd); + Node cursor = startsentinel!.next!; + int j = 0; + while (cursor != endsentinel) + { + cursor!.item = a[j++]; - cursor = cursor.next!; - } - (underlying ?? this).RaiseCollectionChanged(); + cursor = cursor.next!; } + (underlying ?? this).RaiseCollectionChanged(); + } - #endregion + #endregion - #region IIndexed Members + #region IIndexed Members - /// - /// . - /// - /// The directed collection of items in a specific index interval. - /// The low index of the interval (inclusive). - /// The size of the range. - public IDirectedCollectionValue this[int start, int count] + /// + /// . + /// + /// The directed collection of items in a specific index interval. + /// The low index of the interval (inclusive). + /// The size of the range. + public IDirectedCollectionValue this[int start, int count] + { + get { - get - { - ValidityCheck(); - CheckRange(start, count); - return new Range(this, start, count, true); - } + ValidityCheck(); + CheckRange(start, count); + return new Range(this, start, count, true); } + } - /// - /// Searches for an item in the list going forwards from the start. - /// - /// Item to search for. - /// Index of item from start. - public virtual int IndexOf(T item) - { - ValidityCheck(); - Node node; + /// + /// Searches for an item in the list going forwards from the start. + /// + /// Item to search for. + /// Index of item from start. + public virtual int IndexOf(T item) + { + ValidityCheck(); + Node node; - node = startsentinel!.next!; - int index = 0; - if (Find(item, ref node, ref index)) - { - return index; - } - else - { - return ~size; - } + node = startsentinel!.next!; + int index = 0; + if (Find(item, ref node, ref index)) + { + return index; } - - /// - /// Searches for an item in the list going backwards from the end. - /// - /// Item to search for. - /// Index of item from the end. - public virtual int LastIndexOf(T item) + else { + return ~size; + } + } - ValidityCheck(); + /// + /// Searches for an item in the list going backwards from the end. + /// + /// Item to search for. + /// Index of item from the end. + public virtual int LastIndexOf(T item) + { - Node node = endsentinel!.prev!; - int index = size - 1; + ValidityCheck(); - if (DnIf(item, ref node, ref index)) - { - return index; - } - else - { - return ~size; - } - } + Node node = endsentinel!.prev!; + int index = size - 1; - /// - /// Remove the item at a specific position of the list. - /// if i is negative or - /// >= the size of the collection. - /// - /// The index of the item to remove. - /// The removed item. - public virtual T RemoveAt(int i) + if (DnIf(item, ref node, ref index)) { - UpdateCheck(); - T retval = Remove(Get(i), i); + return index; + } + else + { + return ~size; + } + } - if (ActiveEvents != EventType.None) - { - (underlying ?? this).RaiseForRemoveAt(Offset + i, retval); - } + /// + /// Remove the item at a specific position of the list. + /// if i is negative or + /// >= the size of the collection. + /// + /// The index of the item to remove. + /// The removed item. + public virtual T RemoveAt(int i) + { + UpdateCheck(); + T retval = Remove(Get(i), i); - return retval; + if (ActiveEvents != EventType.None) + { + (underlying ?? this).RaiseForRemoveAt(Offset + i, retval); } - /// - /// Remove all items in an index interval. - /// ???. - /// - /// The index of the first item to remove. - /// The number of items to remove. - public virtual void RemoveInterval(int start, int count) - { + return retval; + } - //Note: this is really almost equaivalent to Clear on a view - UpdateCheck(); - CheckRange(start, count); - if (count == 0) - { - return; - } + /// + /// Remove all items in an index interval. + /// ???. + /// + /// The index of the first item to remove. + /// The number of items to remove. + public virtual void RemoveInterval(int start, int count) + { - //for small count: optimize - //use an optimal get(int i, int j, ref Node ni, ref Node nj)? - Node a = Get(start), b = Get(start + count - 1); - FixViewsBeforeRemove(start, count, a, b); - a.prev!.next = b.next; - b.next!.prev = a.prev; - if (underlying != null) - { - underlying.size -= count; - } + //Note: this is really almost equaivalent to Clear on a view + UpdateCheck(); + CheckRange(start, count); + if (count == 0) + { + return; + } - size -= count; - if (ActiveEvents != EventType.None) - { - (underlying ?? this).RaiseForRemoveInterval(start + Offset, count); - } + //for small count: optimize + //use an optimal get(int i, int j, ref Node ni, ref Node nj)? + Node a = Get(start), b = Get(start + count - 1); + FixViewsBeforeRemove(start, count, a, b); + a.prev!.next = b.next; + b.next!.prev = a.prev; + if (underlying != null) + { + underlying.size -= count; } - private void RaiseForRemoveInterval(int start, int count) + size -= count; + if (ActiveEvents != EventType.None) { - if (ActiveEvents != 0) - { - RaiseCollectionCleared(size == 0, count, start); - RaiseCollectionChanged(); - } + (underlying ?? this).RaiseForRemoveInterval(start + Offset, count); } - #endregion + } - #region ISequenced Members + private void RaiseForRemoveInterval(int start, int count) + { + if (ActiveEvents != 0) + { + RaiseCollectionCleared(size == 0, count, start); + RaiseCollectionChanged(); + } + } + #endregion - /// - /// - /// - /// - public override int GetSequencedHashCode() { ValidityCheck(); return base.GetSequencedHashCode(); } + #region ISequenced Members - /// - /// - /// - /// - /// - public override bool SequencedEquals(ISequenced that) { ValidityCheck(); return base.SequencedEquals(that); } + /// + /// + /// + /// + public override int GetSequencedHashCode() { ValidityCheck(); return base.GetSequencedHashCode(); } - #endregion + /// + /// + /// + /// + /// + public override bool SequencedEquals(ISequenced that) { ValidityCheck(); return base.SequencedEquals(that); } - #region IDirectedCollection Members + #endregion - /// - /// Create a collection containing the same items as this collection, but - /// whose enumerator will enumerate the items backwards. The new collection - /// will become invalid if the original is modified. Method typically used as in - /// foreach (T x in coll.Backwards()) {...} - /// - /// The backwards collection. - public override IDirectedCollectionValue Backwards() - { return this[0, size].Backwards(); } + #region IDirectedCollection Members - #endregion + /// + /// Create a collection containing the same items as this collection, but + /// whose enumerator will enumerate the items backwards. The new collection + /// will become invalid if the original is modified. Method typically used as in + /// foreach (T x in coll.Backwards()) {...} + /// + /// The backwards collection. + public override IDirectedCollectionValue Backwards() + { return this[0, size].Backwards(); } - #region IDirectedEnumerable Members + #endregion - IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } + #region IDirectedEnumerable Members - #endregion + IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } - #region IEditableCollection Members + #endregion - /// - /// The value is symbolic indicating the type of asymptotic complexity - /// in terms of the size of this collection (worst-case or amortized as - /// relevant). - /// - /// Speed.Linear - public virtual Speed ContainsSpeed => Speed.Linear; + #region IEditableCollection Members - /// - /// Performs a check for view validity before calling base.GetUnsequencedHashCode() - /// - /// - public override int GetUnsequencedHashCode() - { ValidityCheck(); return base.GetUnsequencedHashCode(); } + /// + /// The value is symbolic indicating the type of asymptotic complexity + /// in terms of the size of this collection (worst-case or amortized as + /// relevant). + /// + /// Speed.Linear + public virtual Speed ContainsSpeed => Speed.Linear; - /// - /// - /// - /// - /// - public override bool UnsequencedEquals(ICollection that) - { ValidityCheck(); return base.UnsequencedEquals(that); } + /// + /// Performs a check for view validity before calling base.GetUnsequencedHashCode() + /// + /// + public override int GetUnsequencedHashCode() + { ValidityCheck(); return base.GetUnsequencedHashCode(); } - /// - /// Check if this collection contains (an item equivalent to according to the - /// itemequalityComparer) a particular value. - /// - /// The value to check for. - /// True if the items is in this collection. - public virtual bool Contains(T item) - { - ValidityCheck(); - return Contains(item, out _); - } + /// + /// + /// + /// + /// + public override bool UnsequencedEquals(ICollection that) + { ValidityCheck(); return base.UnsequencedEquals(that); } - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, return in the ref argument (a - /// binary copy of) the actual value found. - /// - /// The value to look for. - /// True if the items is in this collection. - public virtual bool Find(ref T item) - { - ValidityCheck(); - if (Contains(item, out Node node)) { item = node.item; return true; } - return false; - } + /// + /// Check if this collection contains (an item equivalent to according to the + /// itemequalityComparer) a particular value. + /// + /// The value to check for. + /// True if the items is in this collection. + public virtual bool Contains(T item) + { + ValidityCheck(); + return Contains(item, out _); + } - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// to with a binary copy of the supplied value. Will update a single item. - /// - /// Value to update. - /// True if the item was found and hence updated. - public virtual bool Update(T item) { return Update(item, out _); } + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, return in the ref argument (a + /// binary copy of) the actual value found. + /// + /// The value to look for. + /// True if the items is in this collection. + public virtual bool Find(ref T item) + { + ValidityCheck(); + if (Contains(item, out Node node)) { item = node.item; return true; } + return false; + } - /// - /// - /// - /// - /// - /// - public virtual bool Update(T item, out T olditem) - { - UpdateCheck(); + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// to with a binary copy of the supplied value. Will update a single item. + /// + /// Value to update. + /// True if the item was found and hence updated. + public virtual bool Update(T item) { return Update(item, out _); } - if (Contains(item, out Node node)) - { - olditem = node.item; - node.item = item; + /// + /// + /// + /// + /// + /// + public virtual bool Update(T item, out T olditem) + { + UpdateCheck(); - (underlying ?? this).RaiseForUpdate(item, olditem); - return true; - } + if (Contains(item, out Node node)) + { + olditem = node.item; + node.item = item; - olditem = default; - return false; + (underlying ?? this).RaiseForUpdate(item, olditem); + return true; } - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, return in the ref argument (a - /// binary copy of) the actual value found. Else, add the item to the collection. - /// - /// The value to look for. - /// True if the item was found (hence not added). - public virtual bool FindOrAdd(ref T item) - { - UpdateCheck(); + olditem = default; + return false; + } - if (Find(ref item)) - { - return true; - } + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, return in the ref argument (a + /// binary copy of) the actual value found. Else, add the item to the collection. + /// + /// The value to look for. + /// True if the item was found (hence not added). + public virtual bool FindOrAdd(ref T item) + { + UpdateCheck(); - Add(item); - return false; + if (Find(ref item)) + { + return true; } - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// to with a binary copy of the supplied value; else add the value to the collection. - /// - /// Value to add or update. - /// True if the item was found and updated (hence not added). - public virtual bool UpdateOrAdd(T item) { return UpdateOrAdd(item, out _); } + Add(item); + return false; + } - /// - /// - /// - /// - /// - /// - public virtual bool UpdateOrAdd(T item, out T olditem) + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// to with a binary copy of the supplied value; else add the value to the collection. + /// + /// Value to add or update. + /// True if the item was found and updated (hence not added). + public virtual bool UpdateOrAdd(T item) { return UpdateOrAdd(item, out _); } + + /// + /// + /// + /// + /// + /// + public virtual bool UpdateOrAdd(T item, out T olditem) + { + UpdateCheck(); + + if (Update(item, out olditem)) { - UpdateCheck(); + return true; + } - if (Update(item, out olditem)) - { - return true; - } + Add(item); + olditem = default; + return false; + } - Add(item); - olditem = default; + /// + /// Remove a particular item from this collection. Since the collection has bag + /// semantics only one copy equivalent to the supplied item is removed. + /// + /// The value to remove. + /// True if the item was found (and removed). + public virtual bool Remove(T item) + { + UpdateCheck(); + int i = 0; + Node node; + + node = (fIFO ? startsentinel!.next : endsentinel!.prev)!; + if (!(fIFO ? Find(item, ref node!, ref i) : DnIf(item, ref node!, ref i))) + { return false; } - /// - /// Remove a particular item from this collection. Since the collection has bag - /// semantics only one copy equivalent to the supplied item is removed. - /// - /// The value to remove. - /// True if the item was found (and removed). - public virtual bool Remove(T item) - { - UpdateCheck(); - int i = 0; - Node node; + T removeditem = Remove(node, i); + (underlying ?? this).RaiseForRemove(removeditem); + return true; + } - node = (fIFO ? startsentinel!.next : endsentinel!.prev)!; - if (!(fIFO ? Find(item, ref node!, ref i) : DnIf(item, ref node!, ref i))) - { - return false; - } + /// + /// Remove a particular item from this collection if found (only one copy). + /// If an item was removed, report a binary copy of the actual item removed in + /// the argument. + /// + /// The value to remove on input. + /// The value removed. + /// True if the item was found (and removed). + public virtual bool Remove(T item, out T removeditem) + { + UpdateCheck(); + int i = 0; + Node node; - T removeditem = Remove(node, i); - (underlying ?? this).RaiseForRemove(removeditem); - return true; + node = (fIFO ? startsentinel!.next : endsentinel!.prev)!; + if (!(fIFO ? Find(item, ref node, ref i) : DnIf(item, ref node, ref i))) + { + removeditem = default; + return false; } + removeditem = node.item; + Remove(node, i); + (underlying ?? this).RaiseForRemove(removeditem); + return true; + } - /// - /// Remove a particular item from this collection if found (only one copy). - /// If an item was removed, report a binary copy of the actual item removed in - /// the argument. - /// - /// The value to remove on input. - /// The value removed. - /// True if the item was found (and removed). - public virtual bool Remove(T item, out T removeditem) + /// + /// Remove all items in another collection from this one, taking multiplicities into account. + /// Always removes from the front of the list. + /// + /// The asymptotic running time complexity of this method is O(n+m+v*log(v)), + /// where n is the size of this list, m is the size of the + /// items collection and v is the number of views. + /// The method will temporarily allocate memory of size O(m+v). + /// + /// + /// The items to remove. + public virtual void RemoveAll(SCG.IEnumerable items) + { + UpdateCheck(); + if (size == 0) { - UpdateCheck(); - int i = 0; - Node node; - - node = (fIFO ? startsentinel!.next : endsentinel!.prev)!; - if (!(fIFO ? Find(item, ref node, ref i) : DnIf(item, ref node, ref i))) - { - removeditem = default; - return false; - } - removeditem = node.item; - Remove(node, i); - (underlying ?? this).RaiseForRemove(removeditem); - return true; + return; } - /// - /// Remove all items in another collection from this one, taking multiplicities into account. - /// Always removes from the front of the list. - /// - /// The asymptotic running time complexity of this method is O(n+m+v*log(v)), - /// where n is the size of this list, m is the size of the - /// items collection and v is the number of views. - /// The method will temporarily allocate memory of size O(m+v). - /// - /// - /// The items to remove. - public virtual void RemoveAll(SCG.IEnumerable items) + RaiseForRemoveAllHandler raiseHandler = new(underlying ?? this); + bool mustFire = raiseHandler.MustFire; + + HashBag toremove = new(itemEqualityComparer); + toremove.AddAll(items); + ViewHandler viewHandler = new(this); + int index = 0, removed = 0, myoffset = Offset; + Node node = startsentinel!.next!; + while (node != endsentinel) { - UpdateCheck(); - if (size == 0) + //pass by a stretch of nodes + while (node != endsentinel && !toremove.Contains(node!.item)) { - return; + node = node.next!; + index++; } - - RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); - bool mustFire = raiseHandler.MustFire; - - HashBag toremove = new HashBag(itemequalityComparer); - toremove.AddAll(items); - ViewHandler viewHandler = new ViewHandler(this); - int index = 0, removed = 0, myoffset = Offset; - Node node = startsentinel!.next!; - while (node != endsentinel) + viewHandler.SkipEndpoints(removed, myoffset + index); + //Remove a stretch of nodes + Node localend = node.prev!; //Latest node not to be removed + while (node != endsentinel && toremove.Remove(node.item)) { - //pass by a stretch of nodes - while (node != endsentinel && !toremove.Contains(node!.item)) + if (mustFire) { - node = node.next!; - index++; + raiseHandler.Remove(node.item); } - viewHandler.SkipEndpoints(removed, myoffset + index); - //Remove a stretch of nodes - Node localend = node.prev!; //Latest node not to be removed - while (node != endsentinel && toremove.Remove(node.item)) - { - if (mustFire) - { - raiseHandler.Remove(node.item); - } - removed++; - node = node.next!; - index++; - viewHandler.UpdateViewSizesAndCounts(removed, myoffset + index); - } - viewHandler.UpdateSentinels(myoffset + index, localend!, node); - localend.next = node; - node.prev = localend; - } - index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset; - viewHandler.UpdateViewSizesAndCounts(removed, myoffset + index); - size -= removed; - if (underlying != null) - { - underlying.size -= removed; + removed++; + node = node.next!; + index++; + viewHandler.UpdateViewSizesAndCounts(removed, myoffset + index); } - - raiseHandler.Raise(); + viewHandler.UpdateSentinels(myoffset + index, localend!, node); + localend.next = node; + node.prev = localend; } - - /* - /// - /// - /// - /// - void RemoveAll(Func predicate) + index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset; + viewHandler.UpdateViewSizesAndCounts(removed, myoffset + index); + size -= removed; + if (underlying != null) { - updatecheck(); - if (size == 0) - return; - RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); - bool mustFire = raiseHandler.MustFire; + underlying.size -= removed; + } + + raiseHandler.Raise(); + } + + /* + /// + /// + /// + /// + void RemoveAll(Func predicate) + { + updatecheck(); + if (size == 0) + return; + RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); + bool mustFire = raiseHandler.MustFire; - ViewHandler viewHandler = new ViewHandler(this); - int index = 0, removed = 0, myoffset = Offset; - Node node = startsentinel!.next!; - while (node != endsentinel) + ViewHandler viewHandler = new ViewHandler(this); + int index = 0, removed = 0, myoffset = Offset; + Node node = startsentinel!.next!; + while (node != endsentinel) + { + //pass by a stretch of nodes + while (node != endsentinel && !predicate(node!.item)) { - //pass by a stretch of nodes - while (node != endsentinel && !predicate(node!.item)) - { - updatecheck(); - node = node.next!; - index++; - } updatecheck(); - viewHandler.skipEndpoints(removed, myoffset + index); - //Remove a stretch of nodes - Node localend = node!.prev!; //Latest node not to be removed - while (node != endsentinel && predicate(node.item)) - { - updatecheck(); - if (mustFire) - raiseHandler.Remove(node.item); - removed++; - node = node.next!; - index++; - viewHandler.updateViewSizesAndCounts(removed, myoffset + index); - } + node = node.next!; + index++; + } + updatecheck(); + viewHandler.skipEndpoints(removed, myoffset + index); + //Remove a stretch of nodes + Node localend = node!.prev!; //Latest node not to be removed + while (node != endsentinel && predicate(node.item)) + { updatecheck(); - viewHandler.updateSentinels(myoffset + index, localend!, node!); - localend.next = node; - node.prev = localend; + if (mustFire) + raiseHandler.Remove(node.item); + removed++; + node = node.next!; + index++; + viewHandler.updateViewSizesAndCounts(removed, myoffset + index); } - index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset; - viewHandler.updateViewSizesAndCounts(removed, myoffset + index); - size -= removed; - if (underlying != null) - underlying.size -= removed; - raiseHandler.Raise(); - } */ + updatecheck(); + viewHandler.updateSentinels(myoffset + index, localend!, node!); + localend.next = node; + node.prev = localend; + } + index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset; + viewHandler.updateViewSizesAndCounts(removed, myoffset + index); + size -= removed; + if (underlying != null) + underlying.size -= removed; + raiseHandler.Raise(); + } */ - /// - /// Remove all items from this collection. - /// - public virtual void Clear() + /// + /// Remove all items from this collection. + /// + public virtual void Clear() + { + UpdateCheck(); + if (size == 0) { - UpdateCheck(); - if (size == 0) - { - return; - } + return; + } - int oldsize = size; + int oldsize = size; - ClearInner(); - (underlying ?? this).RaiseForRemoveInterval(Offset, oldsize); - } + ClearInner(); + (underlying ?? this).RaiseForRemoveInterval(Offset, oldsize); + } - private void ClearInner() + private void ClearInner() + { + if (size == 0) { - if (size == 0) - { - return; - } + return; + } - FixViewsBeforeRemove(Offset, size, startsentinel!.next!, endsentinel!.prev!); + FixViewsBeforeRemove(Offset, size, startsentinel!.next!, endsentinel!.prev!); - endsentinel.prev = startsentinel; - startsentinel.next = endsentinel; - if (underlying != null) - { - underlying.size -= size; - } + endsentinel.prev = startsentinel; + startsentinel.next = endsentinel; + if (underlying != null) + { + underlying.size -= size; + } + + size = 0; + } - size = 0; + /// + /// Remove all items not in some other collection from this one, taking multiplicities into account. + /// The asymptotic running time complexity of this method is O(n+m+v*log(v)), + /// where n is the size of this collection, m is the size of the + /// items collection and v is the number of views. + /// The method will temporarily allocate memory of size O(m+v). The stated complexity + /// holds under the assumption that the itemequalityComparer of this list is well-behaved. + /// + /// + /// The items to retain. + public virtual void RetainAll(SCG.IEnumerable items) + { + UpdateCheck(); + if (size == 0) + { + return; } - /// - /// Remove all items not in some other collection from this one, taking multiplicities into account. - /// The asymptotic running time complexity of this method is O(n+m+v*log(v)), - /// where n is the size of this collection, m is the size of the - /// items collection and v is the number of views. - /// The method will temporarily allocate memory of size O(m+v). The stated complexity - /// holds under the assumption that the itemequalityComparer of this list is well-behaved. - /// - /// - /// The items to retain. - public virtual void RetainAll(SCG.IEnumerable items) + RaiseForRemoveAllHandler raiseHandler = new(underlying ?? this); + bool mustFire = raiseHandler.MustFire; + + HashBag toretain = new(itemEqualityComparer); + toretain.AddAll(items); + ViewHandler viewHandler = new(this); + int index = 0, removed = 0, myoffset = Offset; + Node node = startsentinel!.next!; + while (node != endsentinel) { - UpdateCheck(); - if (size == 0) + //Skip a stretch of nodes + while (node != endsentinel && toretain.Remove(node!.item)) { - return; + node = node.next!; + index++; } - - RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); - bool mustFire = raiseHandler.MustFire; - - HashBag toretain = new HashBag(itemequalityComparer); - toretain.AddAll(items); - ViewHandler viewHandler = new ViewHandler(this); - int index = 0, removed = 0, myoffset = Offset; - Node node = startsentinel!.next!; - while (node != endsentinel) + viewHandler.SkipEndpoints(removed, myoffset + index); + //Remove a stretch of nodes + Node localend = node!.prev!; //Latest node not to be removed + while (node != endsentinel && !toretain.Contains(node.item)) { - //Skip a stretch of nodes - while (node != endsentinel && toretain.Remove(node!.item)) + if (mustFire) { - node = node.next!; - index++; + raiseHandler.Remove(node.item); } - viewHandler.SkipEndpoints(removed, myoffset + index); - //Remove a stretch of nodes - Node localend = node!.prev!; //Latest node not to be removed - while (node != endsentinel && !toretain.Contains(node.item)) - { - if (mustFire) - { - raiseHandler.Remove(node.item); - } - removed++; - node = node.next!; - index++; - viewHandler.UpdateViewSizesAndCounts(removed, myoffset + index); - } - viewHandler.UpdateSentinels(myoffset + index, localend!, node); - localend.next = node; - node.prev = localend; - } - index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset; - viewHandler.UpdateViewSizesAndCounts(removed, myoffset + index); - size -= removed; - if (underlying != null) - { - underlying.size -= removed; + removed++; + node = node.next!; + index++; + viewHandler.UpdateViewSizesAndCounts(removed, myoffset + index); } - - raiseHandler.Raise(); + viewHandler.UpdateSentinels(myoffset + index, localend!, node); + localend.next = node; + node.prev = localend; } - - /* - /// - /// - /// - /// - void RetainAll(Func predicate) + index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset; + viewHandler.UpdateViewSizesAndCounts(removed, myoffset + index); + size -= removed; + if (underlying != null) { - updatecheck(); - if (size == 0) - return; - RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); - bool mustFire = raiseHandler.MustFire; - - ViewHandler viewHandler = new ViewHandler(this); - int index = 0, removed = 0, myoffset = Offset; - Node node = startsentinel!.next!; - while (node != endsentinel) - { - //Skip a stretch of nodes - while (node != endsentinel && predicate(node.item)) - { - updatecheck(); - node = node.next!; - index++; - } - updatecheck(); - viewHandler.skipEndpoints(removed, myoffset + index); - //Remove a stretch of nodes - Node localend = node.prev!; //Latest node not to be removed - while (node != endsentinel && !predicate(node!.item)) - { - updatecheck(); - if (mustFire) - raiseHandler.Remove(node.item); - removed++; - node = node.next!; - index++; - viewHandler.updateViewSizesAndCounts(removed, myoffset + index); - } - updatecheck(); - viewHandler.updateSentinels(myoffset + index, localend!, node); - localend.next = node; - node.prev = localend; - } - index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset; - viewHandler.updateViewSizesAndCounts(removed, myoffset + index); - size -= removed; - if (underlying != null) - underlying.size -= removed; - raiseHandler.Raise(); + underlying.size -= removed; } - */ - /// - /// Check if this collection contains all the values in another collection - /// with respect to multiplicities. - /// - /// The - /// True if all values in itemsis in this collection. - public virtual bool ContainsAll(SCG.IEnumerable items) - { - ValidityCheck(); + raiseHandler.Raise(); + } - HashBag tocheck = new HashBag(itemequalityComparer); - tocheck.AddAll(items); - if (tocheck.Count > size) + /* + /// + /// + /// + /// + void RetainAll(Func predicate) + { + updatecheck(); + if (size == 0) + return; + RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); + bool mustFire = raiseHandler.MustFire; + + ViewHandler viewHandler = new ViewHandler(this); + int index = 0, removed = 0, myoffset = Offset; + Node node = startsentinel!.next!; + while (node != endsentinel) + { + //Skip a stretch of nodes + while (node != endsentinel && predicate(node.item)) { - return false; + updatecheck(); + node = node.next!; + index++; } - - Node node = startsentinel!.next!; - while (node != endsentinel) + updatecheck(); + viewHandler.skipEndpoints(removed, myoffset + index); + //Remove a stretch of nodes + Node localend = node.prev!; //Latest node not to be removed + while (node != endsentinel && !predicate(node!.item)) { - tocheck.Remove(node.item); + updatecheck(); + if (mustFire) + raiseHandler.Remove(node.item); + removed++; node = node.next!; + index++; + viewHandler.updateViewSizesAndCounts(removed, myoffset + index); } - return tocheck.IsEmpty; - } + updatecheck(); + viewHandler.updateSentinels(myoffset + index, localend!, node); + localend.next = node; + node.prev = localend; + } + index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset; + viewHandler.updateViewSizesAndCounts(removed, myoffset + index); + size -= removed; + if (underlying != null) + underlying.size -= removed; + raiseHandler.Raise(); + } + */ + /// + /// Check if this collection contains all the values in another collection + /// with respect to multiplicities. + /// + /// The + /// True if all values in itemsis in this collection. + public virtual bool ContainsAll(SCG.IEnumerable items) + { + ValidityCheck(); - /// - /// Create a new list consisting of the items of this list satisfying a - /// certain predicate. - /// - /// The filter delegate defining the predicate. - /// The new list. - public IList FindAll(Func filter) + HashBag tocheck = new(itemEqualityComparer); + tocheck.AddAll(items); + if (tocheck.Count > size) { - ValidityCheck(); - int stamp = this.stamp; - LinkedList retval = new LinkedList(); - Node cursor = startsentinel!.next!; - Node mcursor = retval.startsentinel!; - - while (cursor != endsentinel) - { - bool found = filter(cursor!.item); - ModifyCheck(stamp); - if (found) - { - mcursor.next = new Node(cursor.item, mcursor, null); - mcursor = mcursor.next; - retval.size++; - - } - cursor = cursor.next!; - } + return false; + } - retval.endsentinel!.prev = mcursor; - mcursor.next = retval.endsentinel; - return retval; + Node node = startsentinel!.next!; + while (node != endsentinel) + { + tocheck.Remove(node.item); + node = node.next!; } + return tocheck.IsEmpty; + } - /// - /// Count the number of items of the collection equal to a particular value. - /// Returns 0 if and only if the value is not in the collection. - /// - /// The value to count. - /// The number of copies found. - public virtual int ContainsCount(T item) - { + /// + /// Create a new list consisting of the items of this list satisfying a + /// certain predicate. + /// + /// The filter delegate defining the predicate. + /// The new list. + public IList FindAll(Func filter) + { + ValidityCheck(); + int stamp = this.stamp; + LinkedList retval = new(); + Node cursor = startsentinel!.next!; + Node mcursor = retval.startsentinel!; - ValidityCheck(); - int retval = 0; - Node node = startsentinel!.next!; - while (node != endsentinel) + while (cursor != endsentinel) + { + bool found = filter(cursor!.item); + ModifyCheck(stamp); + if (found) { - if (itemequalityComparer.Equals(node!.item, item)) - { - retval++; - } + mcursor.next = new Node(cursor.item, mcursor, null); + mcursor = mcursor.next; + retval.size++; - node = node.next!; } - return retval; + cursor = cursor.next!; } - /// - /// - /// - /// - public virtual ICollectionValue UniqueItems() + retval.endsentinel!.prev = mcursor; + mcursor.next = retval.endsentinel; + return retval; + } + + + /// + /// Count the number of items of the collection equal to a particular value. + /// Returns 0 if and only if the value is not in the collection. + /// + /// The value to count. + /// The number of copies found. + public virtual int ContainsCount(T item) + { + + ValidityCheck(); + int retval = 0; + Node node = startsentinel!.next!; + while (node != endsentinel) { + if (itemEqualityComparer.Equals(node!.item, item)) + { + retval++; + } - HashBag hashbag = new HashBag(itemequalityComparer); - hashbag.AddAll(this); - return hashbag.UniqueItems(); + node = node.next!; } + return retval; + } - /// - /// - /// - /// - public virtual ICollectionValue> ItemMultiplicities() - { + /// + /// + /// + /// + public virtual ICollectionValue UniqueItems() + { + + HashBag hashbag = new(itemEqualityComparer); + hashbag.AddAll(this); + return hashbag.UniqueItems(); + } + + /// + /// + /// + /// + public virtual ICollectionValue> ItemMultiplicities() + { + + HashBag hashbag = new(itemEqualityComparer); + hashbag.AddAll(this); + return hashbag.ItemMultiplicities(); + } + + /// + /// Remove all items equivalent to a given value. + /// The asymptotic complexity of this method is O(n+v*log(v)), + /// where n is the size of the collection and v + /// is the number of views. + /// + /// + /// The value to remove. + public virtual void RemoveAllCopies(T item) + { - HashBag hashbag = new HashBag(itemequalityComparer); - hashbag.AddAll(this); - return hashbag.ItemMultiplicities(); + UpdateCheck(); + if (size == 0) + { + return; } - /// - /// Remove all items equivalent to a given value. - /// The asymptotic complexity of this method is O(n+v*log(v)), - /// where n is the size of the collection and v - /// is the number of views. - /// - /// - /// The value to remove. - public virtual void RemoveAllCopies(T item) + RaiseForRemoveAllHandler raiseHandler = new(underlying ?? this); + bool mustFire = raiseHandler.MustFire; + ViewHandler viewHandler = new(this); + int index = 0, removed = 0, myoffset = Offset; + // + Node node = startsentinel!.next!; + while (node != endsentinel) { - - UpdateCheck(); - if (size == 0) + //pass by a stretch of nodes + while (node != endsentinel && !itemEqualityComparer.Equals(node!.item, item)) { - return; + node = node.next!; + index++; } - - RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this); - bool mustFire = raiseHandler.MustFire; - ViewHandler viewHandler = new ViewHandler(this); - int index = 0, removed = 0, myoffset = Offset; - // - Node node = startsentinel!.next!; - while (node != endsentinel) + viewHandler.SkipEndpoints(removed, myoffset + index); + //Remove a stretch of nodes + Node localend = node.prev!; //Latest node not to be removed + while (node != endsentinel && itemEqualityComparer.Equals(node!.item, item)) { - //pass by a stretch of nodes - while (node != endsentinel && !itemequalityComparer.Equals(node!.item, item)) + if (mustFire) { - node = node.next!; - index++; + raiseHandler.Remove(node.item); } - viewHandler.SkipEndpoints(removed, myoffset + index); - //Remove a stretch of nodes - Node localend = node.prev!; //Latest node not to be removed - while (node != endsentinel && itemequalityComparer.Equals(node!.item, item)) - { - if (mustFire) - { - raiseHandler.Remove(node.item); - } - removed++; - node = node.next!; - index++; - viewHandler.UpdateViewSizesAndCounts(removed, myoffset + index); - } - viewHandler.UpdateSentinels(myoffset + index, localend!, node!); - localend.next = node; - node.prev = localend; - } - index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset; - viewHandler.UpdateViewSizesAndCounts(removed, myoffset + index); - size -= removed; - if (underlying != null) - { - underlying.size -= removed; + removed++; + node = node.next!; + index++; + viewHandler.UpdateViewSizesAndCounts(removed, myoffset + index); } - - raiseHandler.Raise(); + viewHandler.UpdateSentinels(myoffset + index, localend!, node!); + localend.next = node; + node.prev = localend; + } + index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset; + viewHandler.UpdateViewSizesAndCounts(removed, myoffset + index); + size -= removed; + if (underlying != null) + { + underlying.size -= removed; } - #endregion + raiseHandler.Raise(); + } - #region ICollectionValue Members + #endregion - /// - /// - /// - /// The number of items in this collection - public override int Count { get { ValidityCheck(); return size; } } + #region ICollectionValue Members - /// - /// Choose some item of this collection. - /// - /// if collection is empty. - /// - public override T Choose() { return First; } + /// + /// + /// + /// The number of items in this collection + public override int Count { get { ValidityCheck(); return size; } } - /// - /// Create an enumerable, enumerating the items of this collection that satisfies - /// a certain condition. - /// - /// The T->bool filter delegate defining the condition - /// The filtered enumerable - public override SCG.IEnumerable Filter(Func filter) { ValidityCheck(); return base.Filter(filter); } + /// + /// Choose some item of this collection. + /// + /// if collection is empty. + /// + public override T Choose() { return First; } - #endregion + /// + /// Create an enumerable, enumerating the items of this collection that satisfies + /// a certain condition. + /// + /// The T->bool filter delegate defining the condition + /// The filtered enumerable + public override SCG.IEnumerable Filter(Func filter) { ValidityCheck(); return base.Filter(filter); } - #region IEnumerable Members - /// - /// Create an enumerator for the collection - /// - /// The enumerator - public override SCG.IEnumerator GetEnumerator() - { - ValidityCheck(); - Node cursor = startsentinel!.next!; - int enumeratorstamp = underlying != null ? underlying.stamp : stamp; + #endregion - while (cursor != endsentinel) - { - ModifyCheck(enumeratorstamp); - yield return cursor!.item; - cursor = cursor.next!; - } + #region IEnumerable Members + /// + /// Create an enumerator for the collection + /// + /// The enumerator + public override SCG.IEnumerator GetEnumerator() + { + ValidityCheck(); + Node cursor = startsentinel!.next!; + int enumeratorstamp = underlying != null ? underlying.stamp : stamp; + + while (cursor != endsentinel) + { + ModifyCheck(enumeratorstamp); + yield return cursor!.item; + cursor = cursor.next!; } + } - #endregion + #endregion - #region IExtensible Members - /// - /// Add an item to this collection if possible. - /// - /// The item to add. - /// True. - public virtual bool Add(T item) - { - UpdateCheck(); + #region IExtensible Members + /// + /// Add an item to this collection if possible. + /// + /// The item to add. + /// True. + public virtual bool Add(T item) + { + UpdateCheck(); - Insert(size, endsentinel!, item); - (underlying ?? this).RaiseForAdd(item); - return true; + Insert(size, endsentinel!, item); + (underlying ?? this).RaiseForAdd(item); + return true; - } + } - /// - /// - /// - /// True since this collection has bag semantics. - public virtual bool AllowsDuplicates => true; + /// + /// + /// + /// True since this collection has bag semantics. + public virtual bool AllowsDuplicates => true; - /// - /// By convention this is true for any collection with set semantics. - /// - /// True if only one representative of a group of equal items - /// is kept in the collection together with the total count. - public virtual bool DuplicatesByCounting => false; + /// + /// By convention this is true for any collection with set semantics. + /// + /// True if only one representative of a group of equal items + /// is kept in the collection together with the total count. + public virtual bool DuplicatesByCounting => false; - /// - /// Add the elements from another collection with a more specialized item type - /// to this collection. - /// - /// The items to add - public virtual void AddAll(SCG.IEnumerable items) - { + /// + /// Add the elements from another collection with a more specialized item type + /// to this collection. + /// + /// The items to add + public virtual void AddAll(SCG.IEnumerable items) + { - InsertAll(size, items, false); - } + InsertAll(size, items, false); + } - #endregion + #endregion - #region IStack Members + #region IStack Members - /// - /// Push an item to the top of the stack. - /// - /// The item - public void Push(T item) - { - InsertLast(item); - } + /// + /// Push an item to the top of the stack. + /// + /// The item + public void Push(T item) + { + InsertLast(item); + } - /// - /// Pop the item at the top of the stack from the stack. - /// - /// The popped item. - public T Pop() - { - return RemoveLast(); - } + /// + /// Pop the item at the top of the stack from the stack. + /// + /// The popped item. + public T Pop() + { + return RemoveLast(); + } - #endregion + #endregion - #region IQueue Members + #region IQueue Members - /// - /// Enqueue an item at the back of the queue. - /// - /// The item - public virtual void Enqueue(T item) + /// + /// Enqueue an item at the back of the queue. + /// + /// The item + public virtual void Enqueue(T item) + { + InsertLast(item); + } + + /// + /// Dequeue an item from the front of the queue. + /// + /// The item + public virtual T Dequeue() + { + return RemoveFirst(); + } + #endregion + + #region Diagnostic + + private bool CheckViews() + { + if (underlying != null) { - InsertLast(item); + throw new InternalException("checkViews() called on a view"); } - /// - /// Dequeue an item from the front of the queue. - /// - /// The item - public virtual T Dequeue() + if (views == null) { - return RemoveFirst(); + return true; } - #endregion - #region Diagnostic + bool retval = true; - private bool CheckViews() + Node[] nodes = new Node[size + 2]; + int i = 0; + Node n = startsentinel!; + while (n != null) { - if (underlying != null) + nodes[i++] = n; + n = n.next!; + } + //Logger.Log("###"); + foreach (LinkedList view in views) + { + if (!view.isValid) { - throw new InternalException("checkViews() called on a view"); + Logger.Log(string.Format("Invalid view(hash {0}, offset {1}, size {2})", + view.GetHashCode(), view.offset, view.size)); + retval = false; + continue; } - - if (views == null) + if (view.Offset > size || view.Offset < 0) { - return true; + Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), Offset > underlying.size ({3})", + view.GetHashCode(), view.offset, view.size, size)); + retval = false; } - - bool retval = true; - - Node[] nodes = new Node[size + 2]; - int i = 0; - Node n = startsentinel!; - while (n != null) + else if (view.startsentinel != nodes[view.Offset]) { - nodes[i++] = n; - n = n.next!; + Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), startsentinel {3} should be {4}", + view.GetHashCode(), view.offset, view.size, + view.startsentinel + " " + view.startsentinel!.GetHashCode(), + nodes[view.Offset] + " " + nodes[view.Offset].GetHashCode())); + retval = false; } - //Logger.Log("###"); - foreach (LinkedList view in views) + if (view.Offset + view.size > size || view.Offset + view.size < 0) { - if (!view.isValid) - { - Logger.Log(string.Format("Invalid view(hash {0}, offset {1}, size {2})", - view.GetHashCode(), view.offset, view.size)); - retval = false; - continue; - } - if (view.Offset > size || view.Offset < 0) - { - Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), Offset > underlying.size ({3})", - view.GetHashCode(), view.offset, view.size, size)); - retval = false; - } - else if (view.startsentinel != nodes[view.Offset]) - { - Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), startsentinel {3} should be {4}", - view.GetHashCode(), view.offset, view.size, - view.startsentinel + " " + view.startsentinel!.GetHashCode(), - nodes[view.Offset] + " " + nodes[view.Offset].GetHashCode())); - retval = false; - } - if (view.Offset + view.size > size || view.Offset + view.size < 0) - { - Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), end index > underlying.size ({3})", - view.GetHashCode(), view.offset, view.size, size)); - retval = false; - } - else if (view.endsentinel != nodes[view.Offset + view.size + 1]) - { - Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), endsentinel {3} should be {4}", - view.GetHashCode(), view.offset, view.size, - view.endsentinel + " " + view.endsentinel!.GetHashCode(), - nodes[view.Offset + view.size + 1] + " " + nodes[view.Offset + view.size + 1].GetHashCode())); - retval = false; - } - if (view.views != views) - { - Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), wrong views list {3} <> {4}", - view.GetHashCode(), view.offset, view.size, view.views!.GetHashCode(), views.GetHashCode())); - retval = false; - } - if (view.underlying != this) - { - Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), wrong underlying {3} <> this {4}", - view.GetHashCode(), view.offset, view.size, view.underlying!.GetHashCode(), GetHashCode())); - retval = false; - } - if (view.stamp != stamp) - { - //Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), wrong stamp view:{2} underlying: {3}", view.GetHashCode(),view.offset, view.size, view.stamp, stamp)); - //retval = false; - } + Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), end index > underlying.size ({3})", + view.GetHashCode(), view.offset, view.size, size)); + retval = false; } - return retval; - } - - /* string zeitem(Node node) - { - return node == null ? "(null node)" : node.item!.ToString(); - } */ - - /// - /// Check the sanity of this list - /// - /// true if sane - public virtual bool Check() - { - bool retval = true; - - /*if (underlying != null && underlying.stamp != stamp) - { - Logger.Log("underlying != null && underlying.stamp({0}) != stamp({1})", underlying.stamp, stamp); - retval = false; - }*/ - - if (underlying != null) + else if (view.endsentinel != nodes[view.Offset + view.size + 1]) { - //TODO: check that this view is included in viewsEndpoints tree - return underlying.Check(); + Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), endsentinel {3} should be {4}", + view.GetHashCode(), view.offset, view.size, + view.endsentinel + " " + view.endsentinel!.GetHashCode(), + nodes[view.Offset + view.size + 1] + " " + nodes[view.Offset + view.size + 1].GetHashCode())); + retval = false; } - - if (startsentinel == null) + if (view.views != views) { - Logger.Log("startsentinel == null"); + Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), wrong views list {3} <> {4}", + view.GetHashCode(), view.offset, view.size, view.views!.GetHashCode(), views.GetHashCode())); retval = false; } - - if (endsentinel == null) + if (view.underlying != this) { - Logger.Log("endsentinel == null"); + Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), wrong underlying {3} <> this {4}", + view.GetHashCode(), view.offset, view.size, view.underlying!.GetHashCode(), GetHashCode())); retval = false; } - - if (size == 0) + if (view.stamp != stamp) { - if (startsentinel != null && startsentinel.next != endsentinel) - { - Logger.Log("size == 0 but startsentinel.next != endsentinel"); - retval = false; - } - - if (endsentinel != null && endsentinel.prev != startsentinel) - { - Logger.Log("size == 0 but endsentinel.prev != startsentinel"); - retval = false; - } + //Logger.Log(string.Format("Bad view(hash {0}, offset {1}, size {2}), wrong stamp view:{2} underlying: {3}", view.GetHashCode(),view.offset, view.size, view.stamp, stamp)); + //retval = false; } + } + return retval; + } - if (startsentinel == null) - { - Logger.Log("NULL startsentinel"); - return retval; - } + /* string zeitem(Node node) + { + return node == null ? "(null node)" : node.item!.ToString(); + } */ - int count = 0; - Node node = startsentinel!.next!, prev = startsentinel; + /// + /// Check the sanity of this list + /// + /// true if sane + public virtual bool Check() + { + bool retval = true; - while (node != endsentinel) - { - count++; - if (node.prev != prev) - { - Logger.Log(string.Format("Bad backpointer at node {0}", count)); - retval = false; - } + /*if (underlying != null && underlying.stamp != stamp) + { + Logger.Log("underlying != null && underlying.stamp({0}) != stamp({1})", underlying.stamp, stamp); + retval = false; + }*/ - prev = node; - node = node.next!; - if (node == null) - { - Logger.Log(string.Format("Null next pointer at node {0}", count)); - return false; - } - } + if (underlying != null) + { + //TODO: check that this view is included in viewsEndpoints tree + return underlying.Check(); + } + + if (startsentinel == null) + { + Logger.Log("startsentinel == null"); + retval = false; + } - if (count != size) + if (endsentinel == null) + { + Logger.Log("endsentinel == null"); + retval = false; + } + + if (size == 0) + { + if (startsentinel != null && startsentinel.next != endsentinel) { - Logger.Log(string.Format("size={0} but enumeration gives {1} nodes ", size, count)); + Logger.Log("size == 0 but startsentinel.next != endsentinel"); retval = false; } - retval = CheckViews() && retval; - + if (endsentinel != null && endsentinel.prev != startsentinel) + { + Logger.Log("size == 0 but endsentinel.prev != startsentinel"); + retval = false; + } + } + if (startsentinel == null) + { + Logger.Log("NULL startsentinel"); return retval; } - #endregion - #region System.Collections.Generic.IList Members + int count = 0; + Node node = startsentinel!.next!, prev = startsentinel; - void System.Collections.Generic.IList.RemoveAt(int index) + while (node != endsentinel) { - RemoveAt(index); + count++; + if (node.prev != prev) + { + Logger.Log(string.Format("Bad backpointer at node {0}", count)); + retval = false; + } + + prev = node; + node = node.next!; + if (node == null) + { + Logger.Log(string.Format("Null next pointer at node {0}", count)); + return false; + } } - void System.Collections.Generic.ICollection.Add(T item) + if (count != size) { - Add(item); + Logger.Log(string.Format("size={0} but enumeration gives {1} nodes ", size, count)); + retval = false; } - #endregion + retval = CheckViews() && retval; - #region System.Collections.ICollection Members - bool System.Collections.ICollection.IsSynchronized => false; + return retval; + } + #endregion - [Obsolete] - object System.Collections.ICollection.SyncRoot => (underlying != null ? ((System.Collections.ICollection)underlying).SyncRoot : startsentinel)!; + #region System.Collections.Generic.IList Members - void System.Collections.ICollection.CopyTo(Array arr, int index) - { - if (index < 0 || index + Count > arr.Length) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } + void System.Collections.Generic.IList.RemoveAt(int index) + { + RemoveAt(index); + } - foreach (T item in this) - { - arr.SetValue(item, index++); - } - } + void System.Collections.Generic.ICollection.Add(T item) + { + Add(item); + } - #endregion + #endregion - #region System.Collections.IList Members + #region System.Collections.ICollection Members - Object System.Collections.IList.this[int index] - { - get => this[index]!; - set => this[index] = (T)value; - } + bool System.Collections.ICollection.IsSynchronized => false; - int System.Collections.IList.Add(Object o) - { - bool added = Add((T)o); - // What position to report if item not added? SC.IList.Add doesn't say - return added ? Count - 1 : -1; - } + [Obsolete] + object System.Collections.ICollection.SyncRoot => (underlying != null ? ((System.Collections.ICollection)underlying).SyncRoot : startsentinel)!; - bool System.Collections.IList.Contains(Object o) + void System.Collections.ICollection.CopyTo(Array arr, int index) + { + if (index < 0 || index + Count > arr.Length) { - return Contains((T)o); + throw new ArgumentOutOfRangeException(nameof(index)); } - int System.Collections.IList.IndexOf(Object o) + foreach (T item in this) { - return Math.Max(-1, IndexOf((T)o)); + arr.SetValue(item, index++); } + } - void System.Collections.IList.Insert(int index, Object o) - { - Insert(index, (T)o); - } + #endregion - void System.Collections.IList.Remove(Object o) - { - Remove((T)o); - } + #region System.Collections.IList Members - void System.Collections.IList.RemoveAt(int index) + object? System.Collections.IList.this[int index] + { + get => this[index]!; + set { - RemoveAt(index); + if (value is null && default(T) is not null) throw new ArgumentNullException(nameof(value)); + if (value is not T) throw new ArgumentException("Wrong type", nameof(value)); + + this[index] = (T)value; } + } - #endregion + int System.Collections.IList.Add(object? value) + { + if (value is null && default(T) is not null) throw new ArgumentNullException(nameof(value)); + if (value is not T) throw new ArgumentException("Wrong type", nameof(value)); + + bool added = Add((T)value); + // What position to report if item not added? SC.IList.Add doesn't say + return added ? Count - 1 : -1; + } + + bool System.Collections.IList.Contains(object? value) + { + if (value is null && default(T) is not null) return false; + if (value is not T) return false; + + return Contains((T)value); } + + int System.Collections.IList.IndexOf(object? value) + { + if (value is null && default(T) is not null) return -1; + if (value is not T) return -1; + + return Math.Max(-1, IndexOf((T)value)); + } + + void System.Collections.IList.Insert(int index, object? value) + { + if (value is null && default(T) is not null) throw new ArgumentNullException(nameof(value)); + if (value is not T) throw new ArgumentException("Wrong type", nameof(value)); + + Insert(index, (T)value); + } + + void System.Collections.IList.Remove(object? value) + { + if (value is null && default(T) is not null) return; + if (value is not T) return; + + Remove((T)value); + } + + void System.Collections.IList.RemoveAt(int index) + { + RemoveAt(index); + } + + #endregion } \ No newline at end of file diff --git a/C5/Logger.cs b/C5/Logger.cs index 415de840..fc042dfa 100644 --- a/C5/Logger.cs +++ b/C5/Logger.cs @@ -3,29 +3,28 @@ using System; -namespace C5 +namespace C5; + +/// +/// Logging module +/// +public static class Logger { /// - /// Logging module + /// Gets or sets the log. /// - public static class Logger - { - /// - /// Gets or sets the log. - /// - /// The following is an example of assigning a observer to the logging module: - /// - /// Logger.Log = x => Console.WriteLine(x); - /// - /// - /// - /// If Log is not set it will return a dummy action - /// _ => {}) - /// eliminating the need for null-reference checks. - /// - /// - /// The log. - /// - public static Action Log { get; set; } = _ => {}; - } + /// The following is an example of assigning a observer to the logging module: + /// + /// Logger.Log = x => Console.WriteLine(x); + /// + /// + /// + /// If Log is not set it will return a dummy action + /// _ => {}) + /// eliminating the need for null-reference checks. + /// + /// + /// The log. + /// + public static Action Log { get; set; } = _ => {}; } \ No newline at end of file diff --git a/C5/Showing.cs b/C5/Showing.cs index 45df0105..566fafa5 100644 --- a/C5/Showing.cs +++ b/C5/Showing.cs @@ -4,211 +4,157 @@ using System; using System.Text; -namespace C5 +namespace C5; + +// ------------------------------------------------------------ + +// Static helper methods for Showing collections + +/// +/// +/// +public static class Showing { - // ------------------------------------------------------------ + /// + /// Show Object obj by appending it to stringbuilder + /// + /// + /// + /// + /// + /// True if obj was shown completely. + public static bool Show(object? obj, StringBuilder stringbuilder, ref int rest, IFormatProvider? formatProvider) + { + if (rest <= 0) + { + return false; + } + else if (obj is IShowable showable) + { + return showable.Show(stringbuilder, ref rest, formatProvider); + } - // Static helper methods for Showing collections + int oldLength = stringbuilder.Length; + stringbuilder.AppendFormat(formatProvider, "{0}", obj); + rest -= (stringbuilder.Length - oldLength); + return true; + } /// /// /// - public static class Showing + /// + /// + /// + /// + public static string ShowString(IShowable showable, string? format, IFormatProvider? formatProvider) { - /// - /// Show Object obj by appending it to stringbuilder - /// - /// - /// - /// - /// - /// True if obj was shown completely. - public static bool Show(Object? obj, StringBuilder stringbuilder, ref int rest, IFormatProvider? formatProvider) - { - if (rest <= 0) - { - return false; - } - else if (obj is IShowable showable) - { - return showable.Show(stringbuilder, ref rest, formatProvider); - } + int rest = MaxLength(format); + StringBuilder sb = new(); + showable.Show(sb, ref rest, formatProvider); + return sb.ToString(); + } - int oldLength = stringbuilder.Length; - stringbuilder.AppendFormat(formatProvider, "{0}", obj); - rest -= (stringbuilder.Length - oldLength); - return true; + /// + /// + /// + /// + /// + private static int MaxLength(string? format) + { + //TODO: validate format string + if (format == null) + { + return 80; } - /// - /// - /// - /// - /// - /// - /// - public static string ShowString(IShowable showable, string? format, IFormatProvider? formatProvider) + if (format.Length > 1 && format.StartsWith("L")) { - int rest = MaxLength(format); - StringBuilder sb = new StringBuilder(); - showable.Show(sb, ref rest, formatProvider); - return sb.ToString(); + return int.Parse(format.Substring(1)); } - - /// - /// - /// - /// - /// - private static int MaxLength(string? format) + else { - //TODO: validate format string - if (format == null) - { - return 80; - } - - if (format.Length > 1 && format.StartsWith("L")) - { - return int.Parse(format.Substring(1)); - } - else - { - return int.MaxValue; - } + return int.MaxValue; } + } - /// - /// - /// - /// - /// - /// - /// - /// - /// True if collection was shown completely - public static bool ShowCollectionValue(ICollectionValue? items, StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider) + /// + /// + /// + /// + /// + /// + /// + /// + /// True if collection was shown completely + public static bool ShowCollectionValue(ICollectionValue? items, StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider) + { + string startdelim = "{ ", enddelim = " }"; + bool showIndexes = false; + bool showMultiplicities = false; + if (items is null) { - string startdelim = "{ ", enddelim = " }"; - bool showIndexes = false; - bool showMultiplicities = false; - if (items is null) - { - return true; - } - //TODO: do not test here at run time, but select code at compile time - // perhaps by delivering the print type to this method - ICollection coll = (items! as ICollection)!; - if (items is IList list) - { - startdelim = "[ "; - enddelim = " ]"; - //TODO: should have been (items as IIndexed).IndexingSpeed - showIndexes = list.IndexingSpeed == Speed.Constant; - } - else if (coll != null) + return true; + } + //TODO: do not test here at run time, but select code at compile time + // perhaps by delivering the print type to this method + ICollection coll = (items! as ICollection)!; + if (items is IList list) + { + startdelim = "[ "; + enddelim = " ]"; + //TODO: should have been (items as IIndexed).IndexingSpeed + showIndexes = list.IndexingSpeed == Speed.Constant; + } + else if (coll != null) + { + if (coll.AllowsDuplicates) { - if (coll.AllowsDuplicates) + startdelim = "{{ "; + enddelim = " }}"; + if (coll.DuplicatesByCounting) { - startdelim = "{{ "; - enddelim = " }}"; - if (coll.DuplicatesByCounting) - { - showMultiplicities = true; - } + showMultiplicities = true; } } + } - stringbuilder.Append(startdelim); - rest -= 2 * startdelim.Length; - bool first = true; - bool complete = true; - int index = 0; + stringbuilder.Append(startdelim); + rest -= 2 * startdelim.Length; + bool first = true; + bool complete = true; + int index = 0; - if (showMultiplicities) + if (showMultiplicities) + { + foreach (System.Collections.Generic.KeyValuePair p in coll!.ItemMultiplicities()) { - foreach (System.Collections.Generic.KeyValuePair p in coll!.ItemMultiplicities()) + complete = false; + if (rest <= 0) { - complete = false; - if (rest <= 0) - { - break; - } - - if (first) - { - first = false; - } - else - { - stringbuilder.Append(", "); - rest -= 2; - } - if (complete = Showing.Show(p.Key, stringbuilder, ref rest, formatProvider)) - { - string multiplicityString = string.Format("(*{0})", p.Value); - stringbuilder.Append(multiplicityString); - rest -= multiplicityString.Length; - } + break; } - } - else - { - foreach (T x in items) + + if (first) { - complete = false; - if (rest <= 0) - { - break; - } - - if (first) - { - first = false; - } - else - { - stringbuilder.Append(", "); - rest -= 2; - } - if (showIndexes) - { - string indexString = string.Format("{0}:", index++); - stringbuilder.Append(indexString); - rest -= indexString.Length; - } - complete = Showing.Show(x, stringbuilder, ref rest, formatProvider); + first = false; + } + else + { + stringbuilder.Append(", "); + rest -= 2; + } + if (complete = Show(p.Key, stringbuilder, ref rest, formatProvider)) + { + string multiplicityString = string.Format("(*{0})", p.Value); + stringbuilder.Append(multiplicityString); + rest -= multiplicityString.Length; } } - if (!complete) - { - stringbuilder.Append("..."); - rest -= 3; - } - stringbuilder.Append(enddelim); - return complete; } - - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public static bool ShowDictionary(IDictionary dictionary, StringBuilder stringbuilder, ref int rest, IFormatProvider? formatProvider) + else { - bool sorted = dictionary is ISortedDictionary; - stringbuilder.Append(sorted ? "[ " : "{ "); - rest -= 4; // Account for "( " and " )" - bool first = true; - bool complete = true; - - foreach (System.Collections.Generic.KeyValuePair p in dictionary) + foreach (T x in items) { complete = false; if (rest <= 0) @@ -225,15 +171,68 @@ public static bool ShowDictionary(IDictionary dictionary, StringBuil stringbuilder.Append(", "); rest -= 2; } - complete = Showing.Show(p, stringbuilder, ref rest, formatProvider); + if (showIndexes) + { + string indexString = string.Format("{0}:", index++); + stringbuilder.Append(indexString); + rest -= indexString.Length; + } + complete = Show(x, stringbuilder, ref rest, formatProvider); } - if (!complete) + } + if (!complete) + { + stringbuilder.Append("..."); + rest -= 3; + } + stringbuilder.Append(enddelim); + return complete; + } + + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public static bool ShowDictionary(IDictionary dictionary, StringBuilder stringbuilder, ref int rest, IFormatProvider? formatProvider) + { + bool sorted = dictionary is ISortedDictionary; + stringbuilder.Append(sorted ? "[ " : "{ "); + rest -= 4; // Account for "( " and " )" + bool first = true; + bool complete = true; + + foreach (System.Collections.Generic.KeyValuePair p in dictionary) + { + complete = false; + if (rest <= 0) + { + break; + } + + if (first) { - stringbuilder.Append("..."); - rest -= 3; + first = false; } - stringbuilder.Append(sorted ? " ]" : " }"); - return complete; + else + { + stringbuilder.Append(", "); + rest -= 2; + } + complete = Show(p, stringbuilder, ref rest, formatProvider); + } + if (!complete) + { + stringbuilder.Append("..."); + rest -= 3; } + stringbuilder.Append(sorted ? " ]" : " }"); + return complete; } } \ No newline at end of file diff --git a/C5/Sorting/Sorting.cs b/C5/Sorting/Sorting.cs index 0157cd4f..a6fecfe4 100644 --- a/C5/Sorting/Sorting.cs +++ b/C5/Sorting/Sorting.cs @@ -3,242 +3,242 @@ using System; using SCG = System.Collections.Generic; -namespace C5 + +namespace C5; + +/// +/// A utility class with functions for sorting arrays with respect to an IComparer<T> +/// +public class Sorting { + private Sorting() { } + /// - /// A utility class with functions for sorting arrays with respect to an IComparer<T> + /// Sort part of array in place using IntroSort /// - public class Sorting + /// If the start + /// and count arguments does not describe a valid range. + /// Array to sort + /// Index of first position to sort + /// Number of elements to sort + /// IComparer<T> to sort by + public static void IntroSort(T[] array, int start, int count, SCG.IComparer comparer) { - private Sorting() { } - - /// - /// Sort part of array in place using IntroSort - /// - /// If the start - /// and count arguments does not describe a valid range. - /// Array to sort - /// Index of first position to sort - /// Number of elements to sort - /// IComparer<T> to sort by - public static void IntroSort(T[] array, int start, int count, SCG.IComparer comparer) + if (start < 0 || count < 0 || start + count > array.Length) { - if (start < 0 || count < 0 || start + count > array.Length) - { - throw new ArgumentOutOfRangeException(); - } + throw new ArgumentOutOfRangeException(); + } - new Sorter(array, comparer).IntroSort(start, start + count); + new Sorter(array, comparer).IntroSort(start, start + count); + } + + /// + /// Sort an array in place using IntroSort and default comparer + /// + /// If T is not comparable + /// Array to sort + public static void IntroSort(T[] array) + { + new Sorter(array, SCG.Comparer.Default).IntroSort(0, array.Length); + } + + + /// + /// Sort part of array in place using Insertion Sort + /// + /// If the start + /// and count arguments does not describe a valid range. + /// Array to sort + /// Index of first position to sort + /// Number of elements to sort + /// IComparer<T> to sort by + public static void InsertionSort(T[] array, int start, int count, SCG.IComparer comparer) + { + if (start < 0 || count < 0 || start + count > array.Length) + { + throw new ArgumentOutOfRangeException(); } - /// - /// Sort an array in place using IntroSort and default comparer - /// - /// If T is not comparable - /// Array to sort - public static void IntroSort(T[] array) + new Sorter(array, comparer).InsertionSort(start, start + count); + } + + + /// + /// Sort part of array in place using Heap Sort + /// + /// If the start + /// and count arguments does not describe a valid range. + /// Array to sort + /// Index of first position to sort + /// Number of elements to sort + /// IComparer<T> to sort by + public static void HeapSort(T[] array, int start, int count, SCG.IComparer comparer) + { + if (start < 0 || count < 0 || start + count > array.Length) { - new Sorter(array, SCG.Comparer.Default).IntroSort(0, array.Length); + throw new ArgumentOutOfRangeException(); } + new Sorter(array, comparer).HeapSort(start, start + count); + } + + + private class Sorter + { + private readonly T[] a; + private readonly SCG.IComparer c; + - /// - /// Sort part of array in place using Insertion Sort - /// - /// If the start - /// and count arguments does not describe a valid range. - /// Array to sort - /// Index of first position to sort - /// Number of elements to sort - /// IComparer<T> to sort by - public static void InsertionSort(T[] array, int start, int count, SCG.IComparer comparer) + internal Sorter(T[] a, SCG.IComparer c) { this.a = a; this.c = c; } + + + internal void IntroSort(int f, int b) { - if (start < 0 || count < 0 || start + count > array.Length) + if (b - f > 31) { - throw new ArgumentOutOfRangeException(); - } + int depth_limit = (int)Math.Floor(2.5 * Math.Log(b - f, 2)); - new Sorter(array, comparer).InsertionSort(start, start + count); + IntroSort(f, b, depth_limit); + } + else + { + InsertionSort(f, b); + } } - - /// - /// Sort part of array in place using Heap Sort - /// - /// If the start - /// and count arguments does not describe a valid range. - /// Array to sort - /// Index of first position to sort - /// Number of elements to sort - /// IComparer<T> to sort by - public static void HeapSort(T[] array, int start, int count, SCG.IComparer comparer) + private void IntroSort(int f, int b, int depth_limit) { - if (start < 0 || count < 0 || start + count > array.Length) + const int size_threshold = 14;//24; + + if (depth_limit-- == 0) { - throw new ArgumentOutOfRangeException(); + HeapSort(f, b); } + else if (b - f <= size_threshold) + { + InsertionSort(f, b); + } + else + { + int p = Partition(f, b); - new Sorter(array, comparer).HeapSort(start, start + count); + IntroSort(f, p, depth_limit); + IntroSort(p, b, depth_limit); + } } - - private class Sorter + private int CompareInner(T i1, T i2) { - private readonly T[] a; - private readonly SCG.IComparer c; + return c.Compare(i1, i2); + } + private int Partition(int f, int b) + { + int bot = f, mid = (b + f) / 2, top = b - 1; + T abot = a[bot], amid = a[mid], atop = a[top]; - internal Sorter(T[] a, SCG.IComparer c) { this.a = a; this.c = c; } + if (CompareInner(abot, amid) < 0) + { + if (CompareInner(atop, abot) < 0)//atop 0) //atop 0) //amid<=atop 31) - { - int depth_limit = (int)Math.Floor(2.5 * Math.Log(b - f, 2)); - - IntroSort(f, b, depth_limit); - } - else + while (CompareInner(a[++i], amid) < 0) { - InsertionSort(f, b); + ; } - } - - private void IntroSort(int f, int b, int depth_limit) - { - const int size_threshold = 14;//24; - if (depth_limit-- == 0) + while (CompareInner(amid, a[--j]) < 0) { - HeapSort(f, b); + ; } - else if (b - f <= size_threshold) + + if (i < j) { - InsertionSort(f, b); + T tmp = a[i]; a[i] = a[j]; a[j] = tmp; } else { - int p = Partition(f, b); - - IntroSort(f, p, depth_limit); - IntroSort(p, b, depth_limit); + return i; } } + } - private int CompareInner(T i1, T i2) - { - return c.Compare(i1, i2); - } - private int Partition(int f, int b) + internal void InsertionSort(int f, int b) + { + for (int j = f + 1; j < b; j++) { - int bot = f, mid = (b + f) / 2, top = b - 1; - T abot = a[bot], amid = a[mid], atop = a[top]; + T key = a[j], other; + int i = j - 1; - if (CompareInner(abot, amid) < 0) - { - if (CompareInner(atop, abot) < 0)//atop 0) { - if (CompareInner(amid, atop) > 0) //atop 0) //amid<=atop f && c.Compare(other = a[i - 1], key) > 0) { a[i--] = other; } - while (true) - { - while (CompareInner(a[++i], amid) < 0) - { - ; - } - - while (CompareInner(amid, a[--j]) < 0) - { - ; - } - - if (i < j) - { - T tmp = a[i]; a[i] = a[j]; a[j] = tmp; - } - else - { - return i; - } + a[i] = key; } } + } - internal void InsertionSort(int f, int b) + internal void HeapSort(int f, int b) + { + for (int i = (b + f) / 2; i >= f; i--) { - for (int j = f + 1; j < b; j++) - { - T key = a[j], other; - int i = j - 1; - - if (c.Compare(other = a[i], key) > 0) - { - a[j] = other; - while (i > f && c.Compare(other = a[i - 1], key) > 0) { a[i--] = other; } - - a[i] = key; - } - } + Heapify(f, b, i); } - - internal void HeapSort(int f, int b) + for (int i = b - 1; i > f; i--) { - for (int i = (b + f) / 2; i >= f; i--) - { - Heapify(f, b, i); - } - - for (int i = b - 1; i > f; i--) - { - T tmp = a[f]; a[f] = a[i]; a[i] = tmp; - Heapify(f, i, f); - } + T tmp = a[f]; a[f] = a[i]; a[i] = tmp; + Heapify(f, i, f); } + } - private void Heapify(int f, int b, int i) - { - T pv = a[i], lv, rv, max = pv; - int j = i, maxpt = j; - - while (true) - { - int l = 2 * j - f + 1, r = l + 1; + private void Heapify(int f, int b, int i) + { + T pv = a[i], lv, rv, max = pv; + int j = i, maxpt = j; - if (l < b && CompareInner(lv = a[l], max) > 0) { maxpt = l; max = lv; } + while (true) + { + int l = 2 * j - f + 1, r = l + 1; - if (r < b && CompareInner(rv = a[r], max) > 0) { maxpt = r; max = rv; } + if (l < b && CompareInner(lv = a[l], max) > 0) { maxpt = l; max = lv; } - if (maxpt == j) - { - break; - } + if (r < b && CompareInner(rv = a[r], max) > 0) { maxpt = r; max = rv; } - a[j] = max; - max = pv; - j = maxpt; - } - - if (j > i) + if (maxpt == j) { - a[j] = pv; + break; } + + a[j] = max; + max = pv; + j = maxpt; + } + + if (j > i) + { + a[j] = pv; } } } diff --git a/C5/Trees/TreeBag.cs b/C5/Trees/TreeBag.cs index 6a46a2cd..595e0be1 100644 --- a/C5/Trees/TreeBag.cs +++ b/C5/Trees/TreeBag.cs @@ -4,4493 +4,4492 @@ using System; using SCG = System.Collections.Generic; -namespace C5 +namespace C5; + +///
+public class TreeBag : SequencedBase, IIndexedSorted, IPersistentSorted { - /// - /// An implementation of Red-Black trees as an indexed, sorted collection with bag semantics, - /// cf. CLRS. ( for an - /// implementation with set semantics). - ///
- /// The comparer (sorting order) may be either natural, because the item type is comparable - /// (generic: or non-generic: System.IComparable) or it can - /// be external and supplied by the user in the constructor. - ///
- /// Each distinct item is only kept in one place in the tree - together with the number - /// of times it is a member of the bag. Thus, if two items that are equal according - ///
- public class TreeBag : SequencedBase, IIndexedSorted, IPersistentSorted - { - #region Fields + #region Fields - private SCG.IComparer? comparer; - private Node? root; + private SCG.IComparer? comparer; + private Node? root; - //TODO: wonder if we should remove that - private int blackdepth = 0; + //TODO: wonder if we should remove that + private int blackdepth = 0; - /// - /// Maintain a unique items counter - /// - public int UniqueCount { get; private set; } + /// + /// Maintain a unique items counter + /// + public int UniqueCount { get; private set; } - //We double these stacks for the iterative add and remove on demand - //TODO: refactor dirs[] into bool fields on Node (?) - private int[]? dirs = new int[2]; + //We double these stacks for the iterative add and remove on demand + //TODO: refactor dirs[] into bool fields on Node (?) + private int[]? dirs = new int[2]; - private Node?[]? path = new Node[2]; + private Node?[]? path = new Node[2]; - //TODO: refactor into separate class - private bool isSnapShot = false; - private int generation; - private bool isValid = true; - private SnapRef? snapList; + //TODO: refactor into separate class + private bool isSnapShot = false; + private int generation; + private bool isValid = true; + private SnapRef? snapList; - #endregion + #endregion - #region Events + #region Events - /// - /// - /// - /// - public override EventType ListenableEvents => EventType.Basic; + /// + /// + /// + /// + public override EventType ListenableEvents => EventType.Basic; - #endregion - #region Util + #endregion + #region Util - /// - /// Fetch the left child of n taking node-copying persistence into - /// account if relevant. - /// - /// - /// - private Node Left(Node n) + /// + /// Fetch the left child of n taking node-copying persistence into + /// account if relevant. + /// + /// + /// + private Node Left(Node n) + { + if (isSnapShot) { - if (isSnapShot) - { - if (n.lastgeneration >= generation && n.leftnode) - { - return n.oldref!; - } + if (n.lastgeneration >= generation && n.leftnode) + { + return n.oldref!; } - return n.left; } + return n.left; + } - private Node Right(Node n) + private Node Right(Node n) + { + if (isSnapShot) { - if (isSnapShot) - { - if (n.lastgeneration >= generation && !n.leftnode) - { - return n.oldref!; - } + if (n.lastgeneration >= generation && !n.leftnode) + { + return n.oldref!; } - return n.right!; } + return n.right!; + } - //This method should be called by methods that use the internal - //traversal stack, unless certain that there is room enough - private void StackCheck() + //This method should be called by methods that use the internal + //traversal stack, unless certain that there is room enough + private void StackCheck() + { + while (dirs!.Length < 2 * blackdepth) { - while (dirs!.Length < 2 * blackdepth) - { - dirs = new int[2 * dirs.Length]; - path = new Node[2 * dirs.Length]; - } + dirs = new int[2 * dirs.Length]; + path = new Node[2 * dirs.Length]; } + } - #endregion - - #region Node nested class + #endregion + #region Node nested class - /// - /// The type of node in a Red-Black binary tree - /// - private class Node - { - public bool red = true; - public T item; + /// + /// The type of node in a Red-Black binary tree + /// + private class Node + { + public bool red = true; - public Node left; + public T item; - public Node? right; + public Node left; - public int size = 1; + public Node? right; - public int items = 1; + public int size = 1; + public int items = 1; - //TODO: move everything into (separate) Extra - public int generation; - public int lastgeneration = -1; + //TODO: move everything into (separate) Extra + public int generation; - public Node? oldref; + public int lastgeneration = -1; - public bool leftnode; + public Node? oldref; - /// - /// Update a child pointer - /// - /// - /// - /// - /// - /// - /// True if node was *copied* - internal static bool Update(ref Node cursor, bool leftnode, Node child, int maxsnapid, int generation) - { - Node oldref = (leftnode ? cursor.left : cursor.right)!; + public bool leftnode; - if (child == oldref) - { - return false; - } + /// + /// Update a child pointer + /// + /// + /// + /// + /// + /// + /// True if node was *copied* + internal static bool Update(ref Node cursor, bool leftnode, Node child, int maxsnapid, int generation) + { + Node oldref = (leftnode ? cursor.left : cursor.right)!; - bool retval = false; + if (child == oldref) + { + return false; + } - if (cursor.generation <= maxsnapid) - { - if (cursor.lastgeneration == -1) - { - cursor.leftnode = leftnode; - cursor.lastgeneration = maxsnapid; - cursor.oldref = oldref!; - } - else if (cursor.leftnode != leftnode || cursor.lastgeneration < maxsnapid) - { - CopyNode(ref cursor, maxsnapid, generation); - retval = true; - } - } + bool retval = false; - if (leftnode) + if (cursor.generation <= maxsnapid) + { + if (cursor.lastgeneration == -1) { - cursor.left = child; + cursor.leftnode = leftnode; + cursor.lastgeneration = maxsnapid; + cursor.oldref = oldref!; } - else + else if (cursor.leftnode != leftnode || cursor.lastgeneration < maxsnapid) { - cursor.right = child; + CopyNode(ref cursor, maxsnapid, generation); + retval = true; } + } - return retval; + if (leftnode) + { + cursor.left = child; + } + else + { + cursor.right = child; } + return retval; + } - //If cursor.extra.lastgeneration==maxsnapid, the extra pointer will - //always be used in the old copy of cursor. Therefore, after - //making the clone, we should update the old copy by restoring - //the child pointer and setting extra to null. - //OTOH then we cannot clean up unused Extra objects unless we link - //them together in a doubly linked list. - public static bool CopyNode(ref Node cursor, int maxsnapid, int generation) - { - if (cursor.generation <= maxsnapid) - { - cursor = (Node)(cursor.MemberwiseClone()); - cursor.generation = generation; - cursor.lastgeneration = -1; - return true; - } - return false; + //If cursor.extra.lastgeneration==maxsnapid, the extra pointer will + //always be used in the old copy of cursor. Therefore, after + //making the clone, we should update the old copy by restoring + //the child pointer and setting extra to null. + //OTOH then we cannot clean up unused Extra objects unless we link + //them together in a doubly linked list. + public static bool CopyNode(ref Node cursor, int maxsnapid, int generation) + { + if (cursor.generation <= maxsnapid) + { + cursor = (Node)(cursor.MemberwiseClone()); + cursor.generation = generation; + cursor.lastgeneration = -1; + return true; } + + return false; } + } - #endregion + #endregion - #region Constructors + #region Constructors - /// - /// Create a red-black tree collection with natural comparer and item equalityComparer. - /// We assume that if T is comparable, its default equalityComparer - /// will be compatible with the comparer. - /// - /// If T is not comparable. - /// - public TreeBag() : this(SCG.Comparer.Default, EqualityComparer.Default) { } + /// + /// Create a red-black tree collection with natural comparer and item equalityComparer. + /// We assume that if T is comparable, its default equalityComparer + /// will be compatible with the comparer. + /// + /// If T is not comparable. + /// + public TreeBag() : this(SCG.Comparer.Default, EqualityComparer.Default) { } - /// - /// Create a red-black tree collection with an external comparer. - /// The itemequalityComparer will be a compatible - /// since the - /// default equalityComparer for T () - /// is unlikely to be compatible with the external comparer. This makes the - /// tree inadequate for use as item in a collection of unsequenced or sequenced sets or bags - /// ( and ) - /// - /// - /// The external comparer - public TreeBag(SCG.IComparer comparer) : this(comparer, new ComparerZeroHashCodeEqualityComparer(comparer)) { } + /// + /// Create a red-black tree collection with an external comparer. + /// The itemequalityComparer will be a compatible + /// since the + /// default equalityComparer for T () + /// is unlikely to be compatible with the external comparer. This makes the + /// tree inadequate for use as item in a collection of unsequenced or sequenced sets or bags + /// ( and ) + /// + /// + /// The external comparer + public TreeBag(SCG.IComparer comparer) : this(comparer, new ComparerZeroHashCodeEqualityComparer(comparer)) { } + + /// + /// Create a red-black tree collection with an external comparer and an external + /// item equalityComparer, assumed consistent. + /// + /// The external comparer + /// The external item equalitySCG.Comparer + public TreeBag(SCG.IComparer comparer, SCG.IEqualityComparer equalityComparer) + : base(equalityComparer) + { + this.comparer = comparer ?? throw new NullReferenceException("Item comparer cannot be null"); + } + + #endregion + #region TreeBag.Enumerator nested class + + /// + /// An enumerator for a red-black tree collection. Based on an explicit stack + /// of subtrees waiting to be enumerated. Currently only used for the tree set + /// enumerators (tree bag enumerators use an iterator block based enumerator). + /// + internal class Enumerator : SCG.IEnumerator + { + #region Private Fields + private readonly TreeBag tree; + private bool valid = false; + private readonly int stamp; + private T current; + private Node? cursor; + private Node[]? path; // stack of nodes + + private int level = 0; + #endregion /// - /// Create a red-black tree collection with an external comparer and an external - /// item equalityComparer, assumed consistent. + /// Create a tree enumerator /// - /// The external comparer - /// The external item equalitySCG.Comparer - public TreeBag(SCG.IComparer comparer, SCG.IEqualityComparer equalityComparer) - : base(equalityComparer) + /// The red-black tree to enumerate + public Enumerator(TreeBag tree) { - this.comparer = comparer ?? throw new NullReferenceException("Item comparer cannot be null"); + this.tree = tree; + stamp = tree.stamp; + path = new Node[2 * tree.blackdepth]; + cursor = new Node + { + right = tree.root + }; } - #endregion - - #region TreeBag.Enumerator nested class /// - /// An enumerator for a red-black tree collection. Based on an explicit stack - /// of subtrees waiting to be enumerated. Currently only used for the tree set - /// enumerators (tree bag enumerators use an iterator block based enumerator). + /// Undefined if enumerator is not valid (MoveNext hash been called returning true) /// - internal class Enumerator : SCG.IEnumerator + /// The current item of the enumerator. + public T Current { - #region Private Fields - private readonly TreeBag tree; - private bool valid = false; - private readonly int stamp; - private T current; - private Node? cursor; - private Node[]? path; // stack of nodes - - private int level = 0; - #endregion - /// - /// Create a tree enumerator - /// - /// The red-black tree to enumerate - public Enumerator(TreeBag tree) + get { - this.tree = tree; - stamp = tree.stamp; - path = new Node[2 * tree.blackdepth]; - cursor = new Node + if (valid) { - right = tree.root - }; - } - - - /// - /// Undefined if enumerator is not valid (MoveNext hash been called returning true) - /// - /// The current item of the enumerator. - public T Current - { - get + return current; + } + else { - if (valid) - { - return current; - } - else - { - throw new InvalidOperationException(); - } + throw new InvalidOperationException(); } } + } - //Maintain a stack of nodes that are roots of - //subtrees not completely exported yet. Invariant: - //The stack nodes together with their right subtrees - //consists of exactly the items we have not passed - //yet (the top of the stack holds current item). - /// - /// Move enumerator to next item in tree, or the first item if - /// this is the first call to MoveNext. - /// if underlying tree was modified. - /// - /// True if enumerator is valid now - public bool MoveNext() + //Maintain a stack of nodes that are roots of + //subtrees not completely exported yet. Invariant: + //The stack nodes together with their right subtrees + //consists of exactly the items we have not passed + //yet (the top of the stack holds current item). + /// + /// Move enumerator to next item in tree, or the first item if + /// this is the first call to MoveNext. + /// if underlying tree was modified. + /// + /// True if enumerator is valid now + public bool MoveNext() + { + tree.ModifyCheck(stamp); + if (cursor!.right != null) { - tree.ModifyCheck(stamp); - if (cursor!.right != null) - { - path![level] = cursor = cursor.right; - while (cursor.left != null) - { - path[++level] = cursor = cursor.left; - } - } - else if (level == 0) - { - return valid = false; - } - else + path![level] = cursor = cursor.right; + while (cursor.left != null) { - cursor = path![--level]; + path[++level] = cursor = cursor.left; } - - current = cursor.item; - return valid = true; + } + else if (level == 0) + { + return valid = false; + } + else + { + cursor = path![--level]; } + current = cursor.item; + return valid = true; + } - #region IDisposable Members for Enumerator - private bool disposed; + #region IDisposable Members for Enumerator + private bool disposed; - /// - /// Call Dispose(true) and then suppress finalization of this enumerator. - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } + + /// + /// Call Dispose(true) and then suppress finalization of this enumerator. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } - /// - /// Remove the internal data (notably the stack array). - /// - /// True if called from Dispose(), - /// false if called from the finalizer - protected virtual void Dispose(bool disposing) + /// + /// Remove the internal data (notably the stack array). + /// + /// True if called from Dispose(), + /// false if called from the finalizer + protected virtual void Dispose(bool disposing) + { + if (!disposed) { - if (!disposed) + if (disposing) { - if (disposing) - { - } - - current = default; - cursor = null; - path = null; - disposed = true; } - } - - /// - /// Finalizer for enumerator - /// - ~Enumerator() - { - Dispose(false); + current = default; + cursor = null; + path = null; + disposed = true; } - #endregion + } - #region IEnumerator Members + /// + /// Finalizer for enumerator + /// + ~Enumerator() + { + Dispose(false); + } + #endregion - object System.Collections.IEnumerator.Current => Current!; - bool System.Collections.IEnumerator.MoveNext() - { - return MoveNext(); - } + #region IEnumerator Members - void System.Collections.IEnumerator.Reset() - { - throw new NotImplementedException(); - } + object System.Collections.IEnumerator.Current => Current!; - #endregion + bool System.Collections.IEnumerator.MoveNext() + { + return MoveNext(); + } + + void System.Collections.IEnumerator.Reset() + { + throw new NotImplementedException(); } + #endregion + } + + /// + /// An enumerator for a snapshot of a node copy persistent red-black tree + /// collection. + /// + internal class SnapEnumerator : SCG.IEnumerator + { + #region Private Fields + private TreeBag? tree; + private bool valid = false; + private readonly int stamp; + private int togo; + private T current; + private Node? cursor; + private Node[]? path; // stack of nodes + + private int level; + #endregion + /// - /// An enumerator for a snapshot of a node copy persistent red-black tree - /// collection. + /// Create an enumerator for a snapshot of a node copy persistent red-black tree + /// collection /// - internal class SnapEnumerator : SCG.IEnumerator + /// The snapshot + public SnapEnumerator(TreeBag tree) { - #region Private Fields - private TreeBag? tree; - private bool valid = false; - private readonly int stamp; - private int togo; - private T current; - private Node? cursor; - private Node[]? path; // stack of nodes + this.tree = tree; + stamp = tree.stamp; + path = new Node[2 * tree.blackdepth]; + cursor = new Node + { + right = tree.root + }; + } - private int level; - #endregion - /// - /// Create an enumerator for a snapshot of a node copy persistent red-black tree - /// collection - /// - /// The snapshot - public SnapEnumerator(TreeBag tree) - { - this.tree = tree; - stamp = tree.stamp; - path = new Node[2 * tree.blackdepth]; - cursor = new Node - { - right = tree.root - }; - } + #region SCG.IEnumerator Members + /// + /// Move enumerator to next item in tree, or the first item if + /// this is the first call to MoveNext. + /// if underlying tree was modified. + /// + /// True if enumerator is valid now + public bool MoveNext() + { + tree!.ModifyCheck(stamp);//??? - #region SCG.IEnumerator Members - /// - /// Move enumerator to next item in tree, or the first item if - /// this is the first call to MoveNext. - /// if underlying tree was modified. - /// - /// True if enumerator is valid now - public bool MoveNext() + if (--togo > 0) { - tree!.ModifyCheck(stamp);//??? + return true; + } + Node next = tree.Right(cursor!); - if (--togo > 0) + if (next != null) + { + path![level] = cursor = next; + next = tree.Left(cursor); + while (next != null) { - return true; - } - - Node next = tree.Right(cursor!); - - if (next != null) - { - path![level] = cursor = next; - next = tree.Left(cursor); - while (next != null) - { - path[++level] = cursor = next; - next = tree.Left(cursor); - } - } - else if (level == 0) - { - return valid = false; - } - else - { - cursor = path![--level]; + path[++level] = cursor = next; + next = tree.Left(cursor); } + } + else if (level == 0) + { + return valid = false; + } + else + { + cursor = path![--level]; + } - togo = cursor.items; + togo = cursor.items; - current = cursor.item; - return valid = true; - } + current = cursor.item; + return valid = true; + } - /// - /// Undefined if enumerator is not valid (MoveNext hash been called returning true) - /// - /// The current value of the enumerator. - public T Current + /// + /// Undefined if enumerator is not valid (MoveNext hash been called returning true) + /// + /// The current value of the enumerator. + public T Current + { + get { - get + if (valid) { - if (valid) - { - return current; - } - else - { - throw new InvalidOperationException(); - } + return current; + } + else + { + throw new InvalidOperationException(); } } + } - #endregion - - #region IDisposable Members + #endregion - void System.IDisposable.Dispose() - { - tree = null; - valid = false; - current = default; - cursor = null; - path = null; - } + #region IDisposable Members - #endregion + void System.IDisposable.Dispose() + { + tree = null; + valid = false; + current = default; + cursor = null; + path = null; + } - #region IEnumerator Members + #endregion - object System.Collections.IEnumerator.Current => Current!; + #region IEnumerator Members - bool System.Collections.IEnumerator.MoveNext() - { - return MoveNext(); - } + object System.Collections.IEnumerator.Current => Current!; - void System.Collections.IEnumerator.Reset() - { - throw new NotImplementedException(); - } + bool System.Collections.IEnumerator.MoveNext() + { + return MoveNext(); + } - #endregion + void System.Collections.IEnumerator.Reset() + { + throw new NotImplementedException(); } #endregion + } - #region IEnumerable Members + #endregion - private SCG.IEnumerator GetEnumerator(Node node, int origstamp) - { - if (node == null) - { - yield break; - } + #region IEnumerable Members - if (node.left != null) - { - SCG.IEnumerator child = GetEnumerator(node.left, origstamp); + private SCG.IEnumerator GetEnumerator(Node node, int origstamp) + { + if (node == null) + { + yield break; + } - while (child.MoveNext()) - { - ModifyCheck(origstamp); - yield return child.Current; - } - } + if (node.left != null) + { + SCG.IEnumerator child = GetEnumerator(node.left, origstamp); - int togo = node.items; - while (togo-- > 0) + while (child.MoveNext()) { ModifyCheck(origstamp); - yield return node.item; + yield return child.Current; } + } - if (node.right != null) - { - SCG.IEnumerator child = GetEnumerator(node.right, origstamp); - - while (child.MoveNext()) - { - ModifyCheck(origstamp); - yield return child.Current; - } - } + int togo = node.items; + while (togo-- > 0) + { + ModifyCheck(origstamp); + yield return node.item; } - /// - /// - /// - /// If tree is empty - /// - public override T Choose() + if (node.right != null) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + SCG.IEnumerator child = GetEnumerator(node.right, origstamp); - if (size == 0) + while (child.MoveNext()) { - throw new NoSuchItemException(); + ModifyCheck(origstamp); + yield return child.Current; } - - return root!.item; } + } + /// + /// + /// + /// If tree is empty + /// + public override T Choose() + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); + } - /// - /// Create an enumerator for this tree - /// - /// The enumerator - public override SCG.IEnumerator GetEnumerator() + if (size == 0) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new NoSuchItemException(); + } - if (isSnapShot) - { - return new SnapEnumerator(this); - } + return root!.item; + } - return GetEnumerator(root!, stamp); + /// + /// Create an enumerator for this tree + /// + /// The enumerator + public override SCG.IEnumerator GetEnumerator() + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); + } + + if (isSnapShot) + { + return new SnapEnumerator(this); } - #endregion + return GetEnumerator(root!, stamp); - #region ISink Members + } - /// - /// Add item to tree. If already there, return the found item in the second argument. - /// - /// Item to add - /// item found - /// whether item in node should be updated - /// true if found in bag, false if not found or tree is a set - /// True if item was added - private bool AddIterative(T item, ref T founditem, bool update, out bool wasfound) - { - wasfound = false; - if (root == null) + #endregion + + #region ISink Members + + /// + /// Add item to tree. If already there, return the found item in the second argument. + /// + /// Item to add + /// item found + /// whether item in node should be updated + /// true if found in bag, false if not found or tree is a set + /// True if item was added + private bool AddIterative(T item, ref T founditem, bool update, out bool wasfound) + { + wasfound = false; + if (root == null) + { + root = new Node { - root = new Node - { - red = false - }; - blackdepth = 1; - root.item = item; - root.generation = generation; - return true; - } + red = false + }; + blackdepth = 1; + root.item = item; + root.generation = generation; + return true; + } - StackCheck(); + StackCheck(); - int level = 0; - Node cursor = root; + int level = 0; + Node cursor = root; - while (true) + while (true) + { + int comp = comparer!.Compare(cursor.item, item); + + if (comp == 0) { - int comp = comparer!.Compare(cursor.item, item); + founditem = cursor.item; - if (comp == 0) + wasfound = true; + bool nodeWasUpdated = true; + Node.CopyNode(ref cursor, MaxSnapId, generation); + if (update) { - founditem = cursor.item; - - wasfound = true; - bool nodeWasUpdated = true; - Node.CopyNode(ref cursor, MaxSnapId, generation); - if (update) - { - cursor.item = item; - } - else - { - cursor.items++; - cursor.size++; - } + cursor.item = item; + } + else + { + cursor.items++; + cursor.size++; + } - while (level-- > 0) + while (level-- > 0) + { + if (nodeWasUpdated) { - if (nodeWasUpdated) - { - Node kid = cursor; + Node kid = cursor; - cursor = path![level]!; - Node.Update(ref cursor!, dirs![level] > 0, kid, MaxSnapId, generation); + cursor = path![level]!; + Node.Update(ref cursor!, dirs![level] > 0, kid, MaxSnapId, generation); - if (!update) - { - cursor.size++; - } + if (!update) + { + cursor.size++; } - - path![level] = null; } - // bug20120422: the root was never updated because this was missing: - root = cursor; + path![level] = null; + } - return !update; + // bug20120422: the root was never updated because this was missing: + root = cursor; - } + return !update; + + } - //else - Node child = (comp > 0 ? cursor.left : cursor.right)!; + //else + Node child = (comp > 0 ? cursor.left : cursor.right)!; - if (child == null) + if (child == null) + { + child = new Node { - child = new Node - { - item = item, - generation = generation - }; - Node.Update(ref cursor, comp > 0, child, MaxSnapId, generation); + item = item, + generation = generation + }; + Node.Update(ref cursor, comp > 0, child, MaxSnapId, generation); - cursor.size++; + cursor.size++; - dirs![level] = comp; - break; - } - else - { - dirs![level] = comp; - path![level++] = cursor; - cursor = child; - } + dirs![level] = comp; + break; + } + else + { + dirs![level] = comp; + path![level++] = cursor; + cursor = child; } + } + + //We have just added the red node child to "cursor" + while (cursor.red) + { + //take one step up: + Node child = cursor; + + cursor = path![--level]!; + path[level] = null; + Node.Update(ref cursor!, dirs[level] > 0, child, MaxSnapId, generation); + + cursor.size++; - //We have just added the red node child to "cursor" - while (cursor.red) + int comp = dirs[level]; + Node childsibling = (comp > 0 ? cursor.right : cursor.left)!; + + if (childsibling != null && childsibling.red) { - //take one step up: - Node child = cursor; + //Promote + child.red = false; + Node.Update(ref cursor, comp < 0, childsibling, MaxSnapId, generation); + childsibling.red = false; - cursor = path![--level]!; - path[level] = null; - Node.Update(ref cursor!, dirs[level] > 0, child, MaxSnapId, generation); + //color cursor red & take one step up the tree unless at root + if (level == 0) + { + root = cursor; + blackdepth++; + return true; + } + else + { + cursor.red = true; + child = cursor; + cursor = path[--level]!; + Node.Update(ref cursor!, dirs[level] > 0, child, MaxSnapId, generation); + path[level] = null; - cursor.size++; + cursor.size++; - int comp = dirs[level]; - Node childsibling = (comp > 0 ? cursor.right : cursor.left)!; + } + } + else + { + //ROTATE!!! + int childcomp = dirs[level + 1]; - if (childsibling != null && childsibling.red) + cursor.red = true; + if (comp > 0) { - //Promote - child.red = false; - Node.Update(ref cursor, comp < 0, childsibling, MaxSnapId, generation); - childsibling.red = false; + if (childcomp > 0) + {//zagzag + Node.Update(ref cursor, true, child.right!, MaxSnapId, generation); + Node.Update(ref child, false, cursor, MaxSnapId, generation); - //color cursor red & take one step up the tree unless at root - if (level == 0) - { - root = cursor; - blackdepth++; - return true; + cursor = child; } else - { - cursor.red = true; - child = cursor; - cursor = path[--level]!; - Node.Update(ref cursor!, dirs[level] > 0, child, MaxSnapId, generation); - path[level] = null; - - cursor.size++; - + {//zagzig + Node badgrandchild = child.right!; + Node.Update(ref cursor, true, badgrandchild.right!, MaxSnapId, generation); + Node.Update(ref child, false, badgrandchild.left, MaxSnapId, generation); + Node.CopyNode(ref badgrandchild, MaxSnapId, generation); + + badgrandchild.left = child; + badgrandchild.right = cursor; + cursor = badgrandchild; } } else - { - //ROTATE!!! - int childcomp = dirs[level + 1]; - - cursor.red = true; - if (comp > 0) - { - if (childcomp > 0) - {//zagzag - Node.Update(ref cursor, true, child.right!, MaxSnapId, generation); - Node.Update(ref child, false, cursor, MaxSnapId, generation); + {//comp < 0 + if (childcomp < 0) + {//zigzig + Node.Update(ref cursor, false, child.left, MaxSnapId, generation); + Node.Update(ref child, true, cursor, MaxSnapId, generation); - cursor = child; - } - else - {//zagzig - Node badgrandchild = child.right!; - Node.Update(ref cursor, true, badgrandchild.right!, MaxSnapId, generation); - Node.Update(ref child, false, badgrandchild.left, MaxSnapId, generation); - Node.CopyNode(ref badgrandchild, MaxSnapId, generation); - - badgrandchild.left = child; - badgrandchild.right = cursor; - cursor = badgrandchild; - } + cursor = child; } else - {//comp < 0 - if (childcomp < 0) - {//zigzig - Node.Update(ref cursor, false, child.left, MaxSnapId, generation); - Node.Update(ref child, true, cursor, MaxSnapId, generation); - - cursor = child; - } - else - {//zigzag - Node badgrandchild = child.left; - Node.Update(ref cursor, false, badgrandchild.left, MaxSnapId, generation); - Node.Update(ref child, true, badgrandchild.right!, MaxSnapId, generation); - Node.CopyNode(ref badgrandchild, MaxSnapId, generation); - - badgrandchild.right = child; - badgrandchild.left = cursor; - cursor = badgrandchild; - } + {//zigzag + Node badgrandchild = child.left; + Node.Update(ref cursor, false, badgrandchild.left, MaxSnapId, generation); + Node.Update(ref child, true, badgrandchild.right!, MaxSnapId, generation); + Node.CopyNode(ref badgrandchild, MaxSnapId, generation); + + badgrandchild.right = child; + badgrandchild.left = cursor; + cursor = badgrandchild; } + } - cursor.red = false; + cursor.red = false; - Node n; + Node n; - n = cursor.right!; - cursor.size = n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items; - n = cursor.left; - n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items; - cursor.size += n.size + cursor.items; + n = cursor.right!; + cursor.size = n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items; + n = cursor.left; + n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items; + cursor.size += n.size + cursor.items; - if (level == 0) - { - root = cursor; - return true; - } - else - { - child = cursor; - cursor = path![--level]!; - path[level] = null; - Node.Update(ref cursor!, dirs[level] > 0, child, MaxSnapId, generation); + if (level == 0) + { + root = cursor; + return true; + } + else + { + child = cursor; + cursor = path![--level]!; + path[level] = null; + Node.Update(ref cursor!, dirs[level] > 0, child, MaxSnapId, generation); - cursor.size++; - break; - } + cursor.size++; + break; } } - bool stillmore = true; - while (level > 0) + } + bool stillmore = true; + while (level > 0) + { + Node child = cursor; + + cursor = path![--level]!; + path[level] = null; + if (stillmore) { - Node child = cursor; + stillmore = Node.Update(ref cursor, dirs[level] > 0, child, MaxSnapId, generation); + } - cursor = path![--level]!; - path[level] = null; - if (stillmore) - { - stillmore = Node.Update(ref cursor, dirs[level] > 0, child, MaxSnapId, generation); - } + cursor.size++; - cursor.size++; + } - } + root = cursor; + return true; + } - root = cursor; - return true; + + /// + /// Add an item to this collection if possible. If this collection has set + /// semantics, the item will be added if not already in the collection. If + /// bag semantics, the item will always be added. + /// + /// The item to add. + /// True if item was added. + public bool Add(T item) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } + UpdateCheck(); - /// - /// Add an item to this collection if possible. If this collection has set - /// semantics, the item will be added if not already in the collection. If - /// bag semantics, the item will always be added. - /// - /// The item to add. - /// True if item was added. - public bool Add(T item) + //Note: blackdepth of the tree is set inside addIterative + T jtem = default; + if (!Add(item, ref jtem)) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + return false; + } - UpdateCheck(); + if (ActiveEvents != 0) + { + RaiseForAdd(jtem); + } - //Note: blackdepth of the tree is set inside addIterative - T jtem = default; - if (!Add(item, ref jtem)) - { - return false; - } + return true; + } - if (ActiveEvents != 0) + /// + /// Add an item to this collection if possible. If this collection has set + /// semantics, the item will be added if not already in the collection. If + /// bag semantics, the item will always be added. + /// + /// The item to add. + void SCG.ICollection.Add(T item) + { + Add(item); + } + + private bool Add(T item, ref T j) + { + + if (AddIterative(item, ref j, false, out bool wasFound)) + { + size++; + if (!wasFound) { - RaiseForAdd(jtem); + UniqueCount++; + j = item; } - return true; } - - /// - /// Add an item to this collection if possible. If this collection has set - /// semantics, the item will be added if not already in the collection. If - /// bag semantics, the item will always be added. - /// - /// The item to add. - void SCG.ICollection.Add(T item) + else { - Add(item); + return false; } + } - private bool Add(T item, ref T j) + /// + /// Add the elements from another collection with a more specialized item type + /// to this collection. If this + /// collection has set semantics, only items not already in the collection + /// will be added. + /// + /// The items to add + public void AddAll(SCG.IEnumerable items) + { + if (!isValid) { - - if (AddIterative(item, ref j, false, out bool wasFound)) - { - size++; - if (!wasFound) - { - UniqueCount++; - j = item; - } - return true; - } - else - { - return false; - } + throw new ViewDisposedException("Snapshot has been disposed"); } - /// - /// Add the elements from another collection with a more specialized item type - /// to this collection. If this - /// collection has set semantics, only items not already in the collection - /// will be added. - /// - /// The items to add - public void AddAll(SCG.IEnumerable items) - { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - - UpdateCheck(); + UpdateCheck(); - int c = 0, _uniqueAdds = 0; - T j = default; + int c = 0, _uniqueAdds = 0; + T j = default; - bool raiseAdded = (ActiveEvents & EventType.Added) != 0; - CircularQueue? wasAdded = raiseAdded ? new CircularQueue() : null; + bool raiseAdded = (ActiveEvents & EventType.Added) != 0; + CircularQueue? wasAdded = raiseAdded ? new CircularQueue() : null; - foreach (T i in items) + foreach (T i in items) + { + if (AddIterative(i, ref j, false, out bool wasfound)) { - if (AddIterative(i, ref j, false, out bool wasfound)) + c++; + if (!wasfound) { - c++; - if (!wasfound) - { - _uniqueAdds++; - } + _uniqueAdds++; + } - if (raiseAdded) - { - wasAdded!.Enqueue(wasfound ? j : i); - } + if (raiseAdded) + { + wasAdded!.Enqueue(wasfound ? j : i); } } + } - if (c == 0) - { - return; - } + if (c == 0) + { + return; + } - size += c; - UniqueCount += _uniqueAdds; + size += c; + UniqueCount += _uniqueAdds; - //TODO: implement a RaiseForAddAll() method - if (raiseAdded) + //TODO: implement a RaiseForAddAll() method + if (raiseAdded) + { + foreach (T item in wasAdded!) { - foreach (T item in wasAdded!) - { - RaiseItemsAdded(item, 1); - } + RaiseItemsAdded(item, 1); } + } - if (((ActiveEvents & EventType.Changed) != 0)) - { - RaiseCollectionChanged(); - } + if (((ActiveEvents & EventType.Changed) != 0)) + { + RaiseCollectionChanged(); } + } - /// - /// Add all the items from another collection with an enumeration order that - /// is increasing in the items. The idea is that the implementation may use - /// a faster algorithm to merge the two collections. - /// if the enumerated items turns out - /// not to be in increasing order. - /// - /// The collection to add. - public void AddSorted(SCG.IEnumerable items) + /// + /// Add all the items from another collection with an enumeration order that + /// is increasing in the items. The idea is that the implementation may use + /// a faster algorithm to merge the two collections. + /// if the enumerated items turns out + /// not to be in increasing order. + /// + /// The collection to add. + public void AddSorted(SCG.IEnumerable items) + { + if (size > 0) + { + AddAll(items); + } + else { - if (size > 0) + if (!isValid) { - AddAll(items); + throw new ViewDisposedException("Snapshot has been disposed"); } - else - { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - UpdateCheck(); - AddSorted(items, true); - } + UpdateCheck(); + AddSorted(items, true); } + } - #region add-sorted helpers + #region add-sorted helpers - //Create a RB tree from x+2^h-1 (x < 2^h, h>=1) nodes taken from a - //singly linked list of red nodes using only the right child refs. - //The x nodes at depth h+1 will be red, the rest black. - //(h is the blackdepth of the resulting tree) - private static Node MakeTreer(ref Node rest, int blackheight, int maxred, int red) + //Create a RB tree from x+2^h-1 (x < 2^h, h>=1) nodes taken from a + //singly linked list of red nodes using only the right child refs. + //The x nodes at depth h+1 will be red, the rest black. + //(h is the blackdepth of the resulting tree) + private static Node MakeTreer(ref Node rest, int blackheight, int maxred, int red) + { + if (blackheight == 1) { - if (blackheight == 1) - { - Node top = rest; - - rest = rest.right!; - if (red > 0) - { - top.right = null; - rest!.left = top; - top = rest; + Node top = rest; - top.size += top.left.size; + rest = rest.right!; + if (red > 0) + { + top.right = null; + rest!.left = top; + top = rest; - rest = rest.right!; - red--; - } + top.size += top.left.size; - if (red > 0) - { + rest = rest.right!; + red--; + } - top.size += rest.size; + if (red > 0) + { - top.right = rest; - rest = rest.right!; - top.right.right = null; - } - else - { - top.right = null; - } + top.size += rest.size; - top.red = false; - return top; + top.right = rest; + rest = rest.right!; + top.right.right = null; } else { - maxred >>= 1; + top.right = null; + } + + top.red = false; + return top; + } + else + { + maxred >>= 1; - int lred = red > maxred ? maxred : red; - Node left = MakeTreer(ref rest, blackheight - 1, maxred, lred); - Node top = rest; + int lred = red > maxred ? maxred : red; + Node left = MakeTreer(ref rest, blackheight - 1, maxred, lred); + Node top = rest; - rest = rest.right!; - top.left = left; - top.red = false; - top.right = MakeTreer(ref rest, blackheight - 1, maxred, red - lred); + rest = rest.right!; + top.left = left; + top.red = false; + top.right = MakeTreer(ref rest, blackheight - 1, maxred, red - lred); - top.size = top.items + top.left.size + top.right.size; + top.size = top.items + top.left.size + top.right.size; - return top; - } + return top; } + } - private void AddSorted(SCG.IEnumerable items, bool raise) + private void AddSorted(SCG.IEnumerable items, bool raise) + { + SCG.IEnumerator e = items.GetEnumerator(); + if (size > 0) { - SCG.IEnumerator e = items.GetEnumerator(); - if (size > 0) - { - throw new InternalException("This can't happen"); - } - - if (!e.MoveNext()) - { - return; - } + throw new InternalException("This can't happen"); + } - //To count theCollect - Node head = new Node(), tail = head; - int z = 1; - T lastitem = tail.item = e.Current; + if (!e.MoveNext()) + { + return; + } - int ec = 0; + //To count theCollect + Node head = new(), tail = head; + int z = 1; + T lastitem = tail.item = e.Current; - while (e.MoveNext()) - { + int ec = 0; - T thisitem = e.Current; - int comp = comparer!.Compare(lastitem, thisitem); - if (comp > 0) - { - throw new ArgumentException("Argument not sorted"); - } + while (e.MoveNext()) + { - if (comp == 0) - { - tail.items++; - ec++; - } - else - { - tail.size = tail.items; - z++; - tail.right = new Node(); - tail = tail.right; - lastitem = tail.item = thisitem; - tail.generation = generation; - } + T thisitem = e.Current; + int comp = comparer!.Compare(lastitem, thisitem); + if (comp > 0) + { + throw new ArgumentException("Argument not sorted"); + } + if (comp == 0) + { + tail.items++; + ec++; + } + else + { + tail.size = tail.items; + z++; + tail.right = new Node(); + tail = tail.right; + lastitem = tail.item = thisitem; + tail.generation = generation; } - tail.size = tail.items; + } - int blackheight = 0, red = z, maxred = 1; + tail.size = tail.items; - while (maxred <= red) - { - red -= maxred; - maxred <<= 1; - blackheight++; - } + int blackheight = 0, red = z, maxred = 1; + + while (maxred <= red) + { + red -= maxred; + maxred <<= 1; + blackheight++; + } - root = TreeBag.MakeTreer(ref head, blackheight, maxred, red); - blackdepth = blackheight; - size = z; - UniqueCount = z; + root = TreeBag.MakeTreer(ref head, blackheight, maxred, red); + blackdepth = blackheight; + size = z; + UniqueCount = z; - size += ec; + size += ec; - if (raise) + if (raise) + { + if ((ActiveEvents & EventType.Added) != 0) { - if ((ActiveEvents & EventType.Added) != 0) + CircularQueue wasAdded = new(); + foreach (T item in this) { - CircularQueue wasAdded = new CircularQueue(); - foreach (T item in this) - { - wasAdded.Enqueue(item); - } - - foreach (T item in wasAdded) - { - RaiseItemsAdded(item, 1); - } + wasAdded.Enqueue(item); } - if ((ActiveEvents & EventType.Changed) != 0) + + foreach (T item in wasAdded) { - RaiseCollectionChanged(); + RaiseItemsAdded(item, 1); } } - return; + if ((ActiveEvents & EventType.Changed) != 0) + { + RaiseCollectionChanged(); + } } + return; + } - #endregion + #endregion - /// - /// True since this collection has bag semantics. - public bool AllowsDuplicates => true; + /// + /// True since this collection has bag semantics. + public bool AllowsDuplicates => true; - /// - /// By convention this is true for any collection with set semantics. - /// - /// True if only one representative of a group of equal items - /// is kept in the collection together with the total count. - public virtual bool DuplicatesByCounting => true; + /// + /// By convention this is true for any collection with set semantics. + /// + /// True if only one representative of a group of equal items + /// is kept in the collection together with the total count. + public virtual bool DuplicatesByCounting => true; - #endregion + #endregion - #region IEditableCollection Members + #region IEditableCollection Members - /// - /// The value is symbolic indicating the type of asymptotic complexity - /// in terms of the size of this collection (worst-case or amortized as - /// relevant). - /// - /// Speed.Log - public Speed ContainsSpeed => Speed.Log; + /// + /// The value is symbolic indicating the type of asymptotic complexity + /// in terms of the size of this collection (worst-case or amortized as + /// relevant). + /// + /// Speed.Log + public Speed ContainsSpeed => Speed.Log; - /// - /// Check if this collection contains (an item equivalent to according to the - /// itemequalityComparer) a particular value. - /// - /// The value to check for. - /// True if the items is in this collection. - public bool Contains(T item) + /// + /// Check if this collection contains (an item equivalent to according to the + /// itemequalityComparer) a particular value. + /// + /// The value to check for. + /// True if the items is in this collection. + public bool Contains(T item) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - Node next; - next = root!; - while (next != null) + Node next; + next = root!; + while (next != null) + { + int comp = comparer!.Compare(next.item, item); + if (comp == 0) { - int comp = comparer!.Compare(next.item, item); - if (comp == 0) - { - return true; - } - - next = comp < 0 ? Right(next) : Left(next); + return true; } - return false; + next = comp < 0 ? Right(next) : Left(next); } + return false; + } + - //Variant for dictionary use - //Will return the actual matching item in the ref argument. - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, return in the ref argument (a - /// binary copy of) the actual value found. - /// - /// The value to look for. - /// True if the items is in this collection. - public bool Find(ref T item) + //Variant for dictionary use + //Will return the actual matching item in the ref argument. + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, return in the ref argument (a + /// binary copy of) the actual value found. + /// + /// The value to look for. + /// True if the items is in this collection. + public bool Find(ref T item) + { + if (!isValid) { - if (!isValid) + throw new ViewDisposedException("Snapshot has been disposed"); + } + + Node next; + next = root!; + while (next != null) + { + int comp = comparer!.Compare(next.item, item); + if (comp == 0) { - throw new ViewDisposedException("Snapshot has been disposed"); + item = next.item; + return true; } - Node next; - next = root!; - while (next != null) - { - int comp = comparer!.Compare(next.item, item); - if (comp == 0) - { - item = next.item; - return true; - } + next = comp < 0 ? Right(next) : Left(next); + } - next = comp < 0 ? Right(next) : Left(next); - } + return false; + } - return false; + + /// + /// Find or add the item to the tree. If the tree does not contain + /// an item equivalent to this item add it, else return the existing + /// one in the ref argument. + /// + /// + /// + /// True if item was found + public bool FindOrAdd(ref T item) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } + UpdateCheck(); - /// - /// Find or add the item to the tree. If the tree does not contain - /// an item equivalent to this item add it, else return the existing - /// one in the ref argument. - /// - /// - /// - /// True if item was found - public bool FindOrAdd(ref T item) + //Note: blackdepth of the tree is set inside addIterative + if (AddIterative(item, ref item, false, out bool wasfound)) { - if (!isValid) + size++; + if (!wasfound) { - throw new ViewDisposedException("Snapshot has been disposed"); + UniqueCount++; } - UpdateCheck(); - - //Note: blackdepth of the tree is set inside addIterative - if (AddIterative(item, ref item, false, out bool wasfound)) + if (ActiveEvents != 0 && !wasfound) { - size++; - if (!wasfound) - { - UniqueCount++; - } + RaiseForAdd(item); + } - if (ActiveEvents != 0 && !wasfound) - { - RaiseForAdd(item); - } - - return wasfound; - } - else - { - return true; - } + return wasfound; } + else + { + return true; + } + } - //For dictionary use. - //If found, the matching entry will be updated with the new item. - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// to with a binary copy of the supplied value. If the collection has bag semantics, - /// this updates all equivalent copies in - /// the collection. - /// - /// Value to update. - /// True if the item was found and hence updated. - public bool Update(T item) + //For dictionary use. + //If found, the matching entry will be updated with the new item. + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// to with a binary copy of the supplied value. If the collection has bag semantics, + /// this updates all equivalent copies in + /// the collection. + /// + /// Value to update. + /// True if the item was found and hence updated. + public bool Update(T item) + { + return Update(item, out _); + } + + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// with a binary copy of the supplied value. If the collection has bag semantics, + /// this updates all equivalent copies in + /// the collection. + /// + /// + /// + /// + public bool Update(T item, out T olditem) + { + if (!isValid) { - return Update(item, out _); + throw new ViewDisposedException("Snapshot has been disposed"); } - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// with a binary copy of the supplied value. If the collection has bag semantics, - /// this updates all equivalent copies in - /// the collection. - /// - /// - /// - /// - public bool Update(T item, out T olditem) + UpdateCheck(); + StackCheck(); + + int level = 0; + Node cursor = root!; + while (cursor != null) { - if (!isValid) + int comp = comparer!.Compare(cursor.item, item); + if (comp == 0) { - throw new ViewDisposedException("Snapshot has been disposed"); - } + Node.CopyNode(ref cursor, MaxSnapId, generation); + olditem = cursor.item; - UpdateCheck(); - StackCheck(); + int items = cursor.items; - int level = 0; - Node cursor = root!; - while (cursor != null) - { - int comp = comparer!.Compare(cursor.item, item); - if (comp == 0) + cursor.item = item; + while (level > 0) { - Node.CopyNode(ref cursor, MaxSnapId, generation); - olditem = cursor.item; - - int items = cursor.items; - - cursor.item = item; - while (level > 0) - { - Node child = cursor; - - cursor = path![--level]!; - path[level] = null; - Node.Update(ref cursor, dirs![level] > 0, child, MaxSnapId, generation); + Node child = cursor; - } + cursor = path![--level]!; + path[level] = null; + Node.Update(ref cursor, dirs![level] > 0, child, MaxSnapId, generation); - root = cursor; + } - if (ActiveEvents != 0) - { - RaiseForUpdate(item, olditem, items); - } + root = cursor; - return true; + if (ActiveEvents != 0) + { + RaiseForUpdate(item, olditem, items); } - dirs![level] = comp; - path![level++] = cursor; - cursor = (comp < 0 ? cursor.right : cursor.left)!; - } - olditem = default; - return false; + return true; + } + dirs![level] = comp; + path![level++] = cursor; + cursor = (comp < 0 ? cursor.right : cursor.left)!; } + olditem = default; + return false; + } + - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// with a binary copy of the supplied value; else add the value to the collection. - /// - /// NOTE: the bag implementation is currently wrong! ????? - /// - /// Value to add or update. - /// True if the item was found and updated (hence not added). - public bool UpdateOrAdd(T item) + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// with a binary copy of the supplied value; else add the value to the collection. + /// + /// NOTE: the bag implementation is currently wrong! ????? + /// + /// Value to add or update. + /// True if the item was found and updated (hence not added). + public bool UpdateOrAdd(T item) + { + return UpdateOrAdd(item, out _); + } + + /// + /// + /// + /// + /// + /// + public bool UpdateOrAdd(T item, out T olditem) + { + if (!isValid) { - return UpdateOrAdd(item, out _); + throw new ViewDisposedException("Snapshot has been disposed"); } - /// - /// - /// - /// - /// - /// - public bool UpdateOrAdd(T item, out T olditem) + UpdateCheck(); + olditem = default; + + + //Note: blackdepth of the tree is set inside addIterative + if (AddIterative(item, ref olditem, true, out bool wasfound)) { - if (!isValid) + size++; + if (!wasfound) { - throw new ViewDisposedException("Snapshot has been disposed"); + UniqueCount++; } - UpdateCheck(); - olditem = default; - - - //Note: blackdepth of the tree is set inside addIterative - if (AddIterative(item, ref olditem, true, out bool wasfound)) + if (ActiveEvents != 0) { - size++; - if (!wasfound) - { - UniqueCount++; - } - - if (ActiveEvents != 0) - { - RaiseForAdd(wasfound ? olditem : item); - } - - return wasfound; + RaiseForAdd(wasfound ? olditem : item); } - else - { -#warning for bag implementation: count is wrong - if (ActiveEvents != 0) - { - RaiseForUpdate(item, olditem, 1); - } - return true; - } + return wasfound; } - - - /// - /// Remove a particular item from this collection. If the collection has bag - /// semantics only one copy equivalent to the supplied item is removed. - /// - /// The value to remove. - /// True if the item was found (and removed). - public bool Remove(T item) + else { - if (!isValid) +#warning for bag implementation: count is wrong + if (ActiveEvents != 0) { - throw new ViewDisposedException("Snapshot has been disposed"); + RaiseForUpdate(item, olditem, 1); } - UpdateCheck(); - if (root == null) - { - return false; - } + return true; + } + } - bool retval = RemoveIterative(ref item, false, out _); - if (ActiveEvents != 0 && retval) - { - RaiseForRemove(item); - } - return retval; + /// + /// Remove a particular item from this collection. If the collection has bag + /// semantics only one copy equivalent to the supplied item is removed. + /// + /// The value to remove. + /// True if the item was found (and removed). + public bool Remove(T item) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } - /// - /// Remove a particular item from this collection if found. If the collection - /// has bag semantics only one copy equivalent to the supplied item is removed, - /// which one is implementation dependent. - /// If an item was removed, report a binary copy of the actual item removed in - /// the argument. - /// - /// The value to remove. - /// The removed value. - /// True if the item was found (and removed). - public bool Remove(T item, out T removeditem) + UpdateCheck(); + if (root == null) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + return false; + } - UpdateCheck(); - removeditem = item; - if (root == null) - { - return false; - } + bool retval = RemoveIterative(ref item, false, out _); + if (ActiveEvents != 0 && retval) + { + RaiseForRemove(item); + } - bool retval = RemoveIterative(ref removeditem, false, out _); - if (ActiveEvents != 0 && retval) - { - RaiseForRemove(item); - } + return retval; + } - return retval; + /// + /// Remove a particular item from this collection if found. If the collection + /// has bag semantics only one copy equivalent to the supplied item is removed, + /// which one is implementation dependent. + /// If an item was removed, report a binary copy of the actual item removed in + /// the argument. + /// + /// The value to remove. + /// The removed value. + /// True if the item was found (and removed). + public bool Remove(T item, out T removeditem) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } - /// - /// - /// - /// input: item to remove; output: item actually removed - /// If true, remove all copies - /// - /// - private bool RemoveIterative(ref T item, bool all, out int wasRemoved) + UpdateCheck(); + removeditem = item; + if (root == null) + { + return false; + } + + bool retval = RemoveIterative(ref removeditem, false, out _); + if (ActiveEvents != 0 && retval) { - wasRemoved = 0; - //Stage 1: find item - StackCheck(); + RaiseForRemove(item); + } - int level = 0, comp; - Node cursor = root!; + return retval; + } - while (true) + /// + /// + /// + /// input: item to remove; output: item actually removed + /// If true, remove all copies + /// + /// + private bool RemoveIterative(ref T item, bool all, out int wasRemoved) + { + wasRemoved = 0; + //Stage 1: find item + StackCheck(); + + int level = 0, comp; + Node cursor = root!; + + while (true) + { + comp = comparer!.Compare(cursor.item, item); + if (comp == 0) { - comp = comparer!.Compare(cursor.item, item); - if (comp == 0) - { - item = cursor.item; + item = cursor.item; - if (!all && cursor.items > 1) + if (!all && cursor.items > 1) + { + Node.CopyNode(ref cursor, MaxSnapId, generation); + cursor.items--; + cursor.size--; + while (level-- > 0) { - Node.CopyNode(ref cursor, MaxSnapId, generation); - cursor.items--; - cursor.size--; - while (level-- > 0) - { - Node kid = cursor; + Node kid = cursor; - cursor = path![level]!; - Node.Update(ref cursor!, dirs![level] > 0, kid, MaxSnapId, generation); - cursor.size--; - path[level] = null; - } - size--; - wasRemoved = 1; - return true; + cursor = path![level]!; + Node.Update(ref cursor!, dirs![level] > 0, kid, MaxSnapId, generation); + cursor.size--; + path[level] = null; } - wasRemoved = cursor.items; - - break; + size--; + wasRemoved = 1; + return true; } + wasRemoved = cursor.items; - Node child = (comp > 0 ? cursor.left : cursor.right)!; + break; + } - if (child == null) - { - return false; - } + Node child = (comp > 0 ? cursor.left : cursor.right)!; - dirs![level] = comp; - path![level++] = cursor; - cursor = child; + if (child == null) + { + return false; } - return RemoveIterativePhase2(cursor, level); + dirs![level] = comp; + path![level++] = cursor; + cursor = child; } + return RemoveIterativePhase2(cursor, level); + } + + + private bool RemoveIterativePhase2(Node cursor, int level) + { + if (size == 1) + { + ClearInner(); + return true; + } - private bool RemoveIterativePhase2(Node cursor, int level) + UniqueCount--; + size -= cursor.items; + + //Stage 2: if item's node has no null child, find predecessor + int level_of_item = level; + + if (cursor.left != null && cursor.right != null) { - if (size == 1) + dirs![level] = 1; + path![level++] = cursor; + cursor = cursor.left; + while (cursor.right != null) { - ClearInner(); - return true; + dirs[level] = -1; + path[level++] = cursor; + cursor = cursor.right; } + Node.CopyNode(ref path[level_of_item]!, MaxSnapId, generation); + path[level_of_item]!.item = cursor.item; - UniqueCount--; - size -= cursor.items; + path[level_of_item]!.items = cursor.items; - //Stage 2: if item's node has no null child, find predecessor - int level_of_item = level; + } - if (cursor.left != null && cursor.right != null) - { - dirs![level] = 1; - path![level++] = cursor; - cursor = cursor.left; - while (cursor.right != null) - { - dirs[level] = -1; - path[level++] = cursor; - cursor = cursor.right; - } - Node.CopyNode(ref path[level_of_item]!, MaxSnapId, generation); - path[level_of_item]!.item = cursor.item; + //Stage 3: splice out node to be removed + Node newchild = (cursor.right ?? cursor.left)!; + bool demote_or_rotate = newchild == null && !cursor.red; + + //assert newchild.red + if (newchild != null) + { + newchild.red = false; + } + + if (level == 0) + { + root = newchild!; + return true; + } + + level--; + cursor = path![level]!; + path[level] = null; + + int comp = dirs![level]; + Node childsibling; + Node.Update(ref cursor!, comp > 0, newchild!, MaxSnapId, generation); + + childsibling = (comp > 0 ? cursor.right : cursor.left)!; - path[level_of_item]!.items = cursor.items; + cursor.size = cursor.items + (newchild == null ? 0 : newchild.size) + (childsibling == null ? 0 : childsibling.size); + + //Stage 4: demote till we must rotate + Node? farnephew = null, nearnephew = null; + + while (demote_or_rotate) + { + if (childsibling!.red) + { + break; //rotate 2+? } - //Stage 3: splice out node to be removed - Node newchild = (cursor.right ?? cursor.left)!; - bool demote_or_rotate = newchild == null && !cursor.red; + farnephew = comp > 0 ? childsibling.right : childsibling.left; + if (farnephew != null && farnephew.red) + { + break; //rotate 1b + } - //assert newchild.red - if (newchild != null) + nearnephew = comp > 0 ? childsibling.left : childsibling.right; + if (nearnephew != null && nearnephew.red) { - newchild.red = false; + break; //rotate 1c } + //demote cursor + childsibling.red = true; if (level == 0) { - root = newchild!; + cursor.red = false; + blackdepth--; + root = cursor; return true; } + else if (cursor.red) + { + cursor.red = false; + demote_or_rotate = false; + break; //No rotation + } + else + { + Node child = cursor; - level--; - cursor = path![level]!; - path[level] = null; - - int comp = dirs![level]; - Node childsibling; - Node.Update(ref cursor!, comp > 0, newchild!, MaxSnapId, generation); - - childsibling = (comp > 0 ? cursor.right : cursor.left)!; - - cursor.size = cursor.items + (newchild == null ? 0 : newchild.size) + (childsibling == null ? 0 : childsibling.size); - - - //Stage 4: demote till we must rotate - Node? farnephew = null, nearnephew = null; + cursor = path[--level]!; + path[level] = null; + comp = dirs[level]; + childsibling = (comp > 0 ? cursor.right : cursor.left)!; + Node.Update(ref cursor, comp > 0, child, MaxSnapId, generation); - while (demote_or_rotate) - { - if (childsibling!.red) - { - break; //rotate 2+? - } + cursor.size = cursor.items + (child == null ? 0 : child.size) + (childsibling == null ? 0 : childsibling.size); - farnephew = comp > 0 ? childsibling.right : childsibling.left; - if (farnephew != null && farnephew.red) - { - break; //rotate 1b - } + } + } - nearnephew = comp > 0 ? childsibling.left : childsibling.right; - if (nearnephew != null && nearnephew.red) - { - break; //rotate 1c - } + //Stage 5: rotate + if (demote_or_rotate) + { + //At start: + //parent = cursor (temporary for swapping nodes) + //childsibling is the sibling of the updated child (x) + //cursor is always the top of the subtree + Node parent = cursor; + + if (childsibling!.red) + {//Case 2 and perhaps more. + //The y.rank == px.rank >= x.rank+2 >=2 so both nephews are != null + //(and black). The grandnephews are children of nearnephew + Node neargrandnephew, fargrandnephew; - //demote cursor - childsibling.red = true; - if (level == 0) - { - cursor.red = false; - blackdepth--; - root = cursor; - return true; - } - else if (cursor.red) + if (comp > 0) { - cursor.red = false; - demote_or_rotate = false; - break; //No rotation + nearnephew = childsibling.left; + farnephew = childsibling.right; + neargrandnephew = nearnephew.left; + fargrandnephew = nearnephew.right!; } else { - Node child = cursor; - - cursor = path[--level]!; - path[level] = null; - comp = dirs[level]; - childsibling = (comp > 0 ? cursor.right : cursor.left)!; - Node.Update(ref cursor, comp > 0, child, MaxSnapId, generation); - - cursor.size = cursor.items + (child == null ? 0 : child.size) + (childsibling == null ? 0 : childsibling.size); - + nearnephew = childsibling.right; + farnephew = childsibling.left; + neargrandnephew = nearnephew!.right!; + fargrandnephew = nearnephew.left; } - } - //Stage 5: rotate - if (demote_or_rotate) - { - //At start: - //parent = cursor (temporary for swapping nodes) - //childsibling is the sibling of the updated child (x) - //cursor is always the top of the subtree - Node parent = cursor; - - if (childsibling!.red) - {//Case 2 and perhaps more. - //The y.rank == px.rank >= x.rank+2 >=2 so both nephews are != null - //(and black). The grandnephews are children of nearnephew - Node neargrandnephew, fargrandnephew; + if (fargrandnephew != null && fargrandnephew.red) + {//Case 2+1b + Node.CopyNode(ref nearnephew!, MaxSnapId, generation); + //The end result of this will always be e copy of parent + Node.Update(ref parent, comp < 0, neargrandnephew!, MaxSnapId, generation); + Node.Update(ref childsibling, comp > 0, nearnephew, MaxSnapId, generation); if (comp > 0) { - nearnephew = childsibling.left; - farnephew = childsibling.right; - neargrandnephew = nearnephew.left; - fargrandnephew = nearnephew.right!; + nearnephew.left = parent; + parent.right = neargrandnephew; } else { - nearnephew = childsibling.right; - farnephew = childsibling.left; - neargrandnephew = nearnephew!.right!; - fargrandnephew = nearnephew.left; + nearnephew.right = parent; + parent.left = neargrandnephew!; } - if (fargrandnephew != null && fargrandnephew.red) - {//Case 2+1b - Node.CopyNode(ref nearnephew!, MaxSnapId, generation); + cursor = childsibling; + childsibling.red = false; + nearnephew.red = true; + fargrandnephew.red = false; - //The end result of this will always be e copy of parent - Node.Update(ref parent, comp < 0, neargrandnephew!, MaxSnapId, generation); - Node.Update(ref childsibling, comp > 0, nearnephew, MaxSnapId, generation); - if (comp > 0) - { - nearnephew.left = parent; - parent.right = neargrandnephew; - } - else - { - nearnephew.right = parent; - parent.left = neargrandnephew!; - } - - cursor = childsibling; - childsibling.red = false; - nearnephew.red = true; - fargrandnephew.red = false; - - cursor.size = parent.size; - nearnephew.size = cursor.size - cursor.items - farnephew!.size; - parent.size = nearnephew.size - nearnephew.items - fargrandnephew.size; - - } - else if (neargrandnephew != null && neargrandnephew.red) - {//Case 2+1c - Node.CopyNode(ref neargrandnephew, MaxSnapId, generation); - if (comp > 0) - { - Node.Update(ref childsibling, true, neargrandnephew, MaxSnapId, generation); - Node.Update(ref nearnephew!, true, neargrandnephew.right!, MaxSnapId, generation); - Node.Update(ref parent, false, neargrandnephew.left, MaxSnapId, generation); - neargrandnephew.left = parent; - neargrandnephew.right = nearnephew; - } - else - { - Node.Update(ref childsibling, false, neargrandnephew, MaxSnapId, generation); - Node.Update(ref nearnephew!, false, neargrandnephew.left, MaxSnapId, generation); - Node.Update(ref parent, true, neargrandnephew.right!, MaxSnapId, generation); - neargrandnephew.right = parent; - neargrandnephew.left = nearnephew; - } - - cursor = childsibling; - childsibling.red = false; - - cursor.size = parent.size; - parent.size = parent.items + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size); - nearnephew.size = nearnephew.items + (nearnephew.left == null ? 0 : nearnephew.left.size) + (nearnephew.right == null ? 0 : nearnephew.right.size); - neargrandnephew.size = neargrandnephew.items + parent.size + nearnephew.size; - - } - else - {//Case 2 only - Node.Update(ref parent, comp < 0, nearnephew, MaxSnapId, generation); - Node.Update(ref childsibling, comp > 0, parent, MaxSnapId, generation); - - cursor = childsibling; - childsibling.red = false; - nearnephew.red = true; - - cursor.size = parent.size; - parent.size -= farnephew!.size + cursor.items; + cursor.size = parent.size; + nearnephew.size = cursor.size - cursor.items - farnephew!.size; + parent.size = nearnephew.size - nearnephew.items - fargrandnephew.size; - } } - else if (farnephew != null && farnephew.red) - {//Case 1b - nearnephew = comp > 0 ? childsibling.left : childsibling.right; - Node.Update(ref parent, comp < 0, nearnephew!, MaxSnapId, generation); - Node.CopyNode(ref childsibling, MaxSnapId, generation); + else if (neargrandnephew != null && neargrandnephew.red) + {//Case 2+1c + Node.CopyNode(ref neargrandnephew, MaxSnapId, generation); if (comp > 0) { - childsibling.left = parent; - childsibling.right = farnephew; + Node.Update(ref childsibling, true, neargrandnephew, MaxSnapId, generation); + Node.Update(ref nearnephew!, true, neargrandnephew.right!, MaxSnapId, generation); + Node.Update(ref parent, false, neargrandnephew.left, MaxSnapId, generation); + neargrandnephew.left = parent; + neargrandnephew.right = nearnephew; } else { - childsibling.right = parent; - childsibling.left = farnephew; + Node.Update(ref childsibling, false, neargrandnephew, MaxSnapId, generation); + Node.Update(ref nearnephew!, false, neargrandnephew.left, MaxSnapId, generation); + Node.Update(ref parent, true, neargrandnephew.right!, MaxSnapId, generation); + neargrandnephew.right = parent; + neargrandnephew.left = nearnephew; } cursor = childsibling; - cursor.red = parent.red; - parent.red = false; - farnephew.red = false; - + childsibling.red = false; cursor.size = parent.size; - parent.size -= farnephew.size + cursor.items; + parent.size = parent.items + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size); + nearnephew.size = nearnephew.items + (nearnephew.left == null ? 0 : nearnephew.left.size) + (nearnephew.right == null ? 0 : nearnephew.right.size); + neargrandnephew.size = neargrandnephew.items + parent.size + nearnephew.size; } - else if (nearnephew != null && nearnephew.red) - {//Case 1c - Node.CopyNode(ref nearnephew!, MaxSnapId, generation); - if (comp > 0) - { - Node.Update(ref childsibling, true, nearnephew.right!, MaxSnapId, generation); - Node.Update(ref parent, false, nearnephew.left, MaxSnapId, generation); - - nearnephew.left = parent; - nearnephew.right = childsibling; - } - else - { - Node.Update(ref childsibling, false, nearnephew.left, MaxSnapId, generation); - Node.Update(ref parent, true, nearnephew.right!, MaxSnapId, generation); - - nearnephew.right = parent; - nearnephew.left = childsibling; - } + else + {//Case 2 only + Node.Update(ref parent, comp < 0, nearnephew, MaxSnapId, generation); + Node.Update(ref childsibling, comp > 0, parent, MaxSnapId, generation); - cursor = nearnephew; - cursor.red = parent.red; - parent.red = false; + cursor = childsibling; + childsibling.red = false; + nearnephew.red = true; cursor.size = parent.size; - parent.size = parent.items + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size); - childsibling.size = childsibling.items + (childsibling.left == null ? 0 : childsibling.left.size) + (childsibling.right == null ? 0 : childsibling.right.size); + parent.size -= farnephew!.size + cursor.items; } + } + else if (farnephew != null && farnephew.red) + {//Case 1b + nearnephew = comp > 0 ? childsibling.left : childsibling.right; + Node.Update(ref parent, comp < 0, nearnephew!, MaxSnapId, generation); + Node.CopyNode(ref childsibling, MaxSnapId, generation); + if (comp > 0) + { + childsibling.left = parent; + childsibling.right = farnephew; + } else - {//Case 1a can't happen - throw new InternalException("Case 1a can't happen here"); + { + childsibling.right = parent; + childsibling.left = farnephew; } - //Resplice cursor: - if (level == 0) + cursor = childsibling; + cursor.red = parent.red; + parent.red = false; + farnephew.red = false; + + + cursor.size = parent.size; + parent.size -= farnephew.size + cursor.items; + + } + else if (nearnephew != null && nearnephew.red) + {//Case 1c + Node.CopyNode(ref nearnephew!, MaxSnapId, generation); + if (comp > 0) { - root = cursor; + Node.Update(ref childsibling, true, nearnephew.right!, MaxSnapId, generation); + Node.Update(ref parent, false, nearnephew.left, MaxSnapId, generation); + + nearnephew.left = parent; + nearnephew.right = childsibling; } else { - Node swap = cursor; + Node.Update(ref childsibling, false, nearnephew.left, MaxSnapId, generation); + Node.Update(ref parent, true, nearnephew.right!, MaxSnapId, generation); - cursor = path![--level]!; - path[level] = null; - Node.Update(ref cursor!, dirs[level] > 0, swap, MaxSnapId, generation); + nearnephew.right = parent; + nearnephew.left = childsibling; + } + cursor = nearnephew; + cursor.red = parent.red; + parent.red = false; - cursor.size = cursor.items + (cursor.right == null ? 0 : cursor.right.size) + (cursor.left == null ? 0 : cursor.left.size); + cursor.size = parent.size; + parent.size = parent.items + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size); + childsibling.size = childsibling.items + (childsibling.left == null ? 0 : childsibling.left.size) + (childsibling.right == null ? 0 : childsibling.right.size); - } + } + else + {//Case 1a can't happen + throw new InternalException("Case 1a can't happen here"); } - //Stage 6: fixup to the root - while (level > 0) + //Resplice cursor: + if (level == 0) { - Node child = cursor; + root = cursor; + } + else + { + Node swap = cursor; cursor = path![--level]!; path[level] = null; - if (child != (dirs[level] > 0 ? cursor.left : cursor.right)) - { - Node.Update(ref cursor, dirs[level] > 0, child, MaxSnapId, generation); - } + Node.Update(ref cursor!, dirs[level] > 0, swap, MaxSnapId, generation); + cursor.size = cursor.items + (cursor.right == null ? 0 : cursor.right.size) + (cursor.left == null ? 0 : cursor.left.size); } - - root = cursor; - return true; } - - /// - /// Remove all items from this collection. - /// - public void Clear() + //Stage 6: fixup to the root + while (level > 0) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + Node child = cursor; - UpdateCheck(); - if (size == 0) + cursor = path![--level]!; + path[level] = null; + if (child != (dirs[level] > 0 ? cursor.left : cursor.right)) { - return; + Node.Update(ref cursor, dirs[level] > 0, child, MaxSnapId, generation); } - int oldsize = size; - ClearInner(); - if ((ActiveEvents & EventType.Cleared) != 0) - { - RaiseCollectionCleared(true, oldsize); - } + cursor.size = cursor.items + (cursor.right == null ? 0 : cursor.right.size) + (cursor.left == null ? 0 : cursor.left.size); - if ((ActiveEvents & EventType.Changed) != 0) - { - RaiseCollectionChanged(); - } } - private void ClearInner() + root = cursor; + return true; + } + + + /// + /// Remove all items from this collection. + /// + public void Clear() + { + if (!isValid) { - size = 0; - UniqueCount = 0; - root = null; - blackdepth = 0; + throw new ViewDisposedException("Snapshot has been disposed"); } - /// - /// Remove all items in another collection from this one. If this collection - /// has bag semantics, take multiplicities into account. - /// - /// The items to remove. - public void RemoveAll(SCG.IEnumerable items) + UpdateCheck(); + if (size == 0) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + return; + } - UpdateCheck(); + int oldsize = size; + ClearInner(); + if ((ActiveEvents & EventType.Cleared) != 0) + { + RaiseCollectionCleared(true, oldsize); + } - T jtem; + if ((ActiveEvents & EventType.Changed) != 0) + { + RaiseCollectionChanged(); + } + } - bool mustRaise = (ActiveEvents & (EventType.Removed | EventType.Changed)) != 0; - RaiseForRemoveAllHandler? raiseHandler = mustRaise ? new RaiseForRemoveAllHandler(this) : null; + private void ClearInner() + { + size = 0; + UniqueCount = 0; + root = null; + blackdepth = 0; + } - foreach (T item in items) - { - if (root == null) - { - break; - } + /// + /// Remove all items in another collection from this one. If this collection + /// has bag semantics, take multiplicities into account. + /// + /// The items to remove. + public void RemoveAll(SCG.IEnumerable items) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); + } - jtem = item; - if (RemoveIterative(ref jtem, false, out int junk) && mustRaise) - { - raiseHandler!.Remove(jtem); - } + UpdateCheck(); + + T jtem; + + bool mustRaise = (ActiveEvents & (EventType.Removed | EventType.Changed)) != 0; + RaiseForRemoveAllHandler? raiseHandler = mustRaise ? new RaiseForRemoveAllHandler(this) : null; + + foreach (T item in items) + { + if (root == null) + { + break; } - if (mustRaise) + + jtem = item; + if (RemoveIterative(ref jtem, false, out int junk) && mustRaise) { - raiseHandler!.Raise(); + raiseHandler!.Remove(jtem); } } + if (mustRaise) + { + raiseHandler!.Raise(); + } + } - /// - /// Remove all items not in some other collection from this one. If this collection - /// has bag semantics, take multiplicities into account. - /// - /// The items to retain. - public void RetainAll(SCG.IEnumerable items) + /// + /// Remove all items not in some other collection from this one. If this collection + /// has bag semantics, take multiplicities into account. + /// + /// The items to retain. + public void RetainAll(SCG.IEnumerable items) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - UpdateCheck(); + UpdateCheck(); - //A much more efficient version is possible if items is sorted like this. - //Well, it is unclear how efficient it would be. - //We could use a marking method!? + //A much more efficient version is possible if items is sorted like this. + //Well, it is unclear how efficient it would be. + //We could use a marking method!? #warning how does this work together with persistence? - TreeBag t = (TreeBag)MemberwiseClone(); + TreeBag t = (TreeBag)MemberwiseClone(); - T jtem = default; - t.ClearInner(); - foreach (T item in items) + T jtem = default; + t.ClearInner(); + foreach (T item in items) + { + if (ContainsCount(item) > t.ContainsCount(item)) { - if (ContainsCount(item) > t.ContainsCount(item)) - { - t.Add(item, ref jtem); - } + t.Add(item, ref jtem); } + } - if (size == t.size) - { - return; - } + if (size == t.size) + { + return; + } #warning improve (mainly for bag) by using a Node iterator instead of ItemMultiplicities() - CircularQueue>? wasRemoved = null; - if ((ActiveEvents & EventType.Removed) != 0) + CircularQueue>? wasRemoved = null; + if ((ActiveEvents & EventType.Removed) != 0) + { + wasRemoved = new CircularQueue>(); + SCG.IEnumerator> ie = ItemMultiplicities().GetEnumerator(); + foreach (System.Collections.Generic.KeyValuePair p in t.ItemMultiplicities()) { - wasRemoved = new CircularQueue>(); - SCG.IEnumerator> ie = ItemMultiplicities().GetEnumerator(); - foreach (System.Collections.Generic.KeyValuePair p in t.ItemMultiplicities()) + //We know p.Key is in this! + while (ie.MoveNext()) { - //We know p.Key is in this! - while (ie.MoveNext()) + if (comparer!.Compare(ie.Current.Key, p.Key) == 0) { - if (comparer!.Compare(ie.Current.Key, p.Key) == 0) - { - - int removed = ie.Current.Value - p.Value; - if (removed > 0) - { - wasRemoved.Enqueue(new System.Collections.Generic.KeyValuePair(p.Key, removed)); - } - break; - } - else + int removed = ie.Current.Value - p.Value; + if (removed > 0) { - wasRemoved.Enqueue(ie.Current); + wasRemoved.Enqueue(new System.Collections.Generic.KeyValuePair(p.Key, removed)); } - } - } - while (ie.MoveNext()) - { - wasRemoved.Enqueue(ie.Current); - } - } - root = t.root; - size = t.size; - UniqueCount = t.UniqueCount; - blackdepth = t.blackdepth; - if (wasRemoved != null) - { - foreach (System.Collections.Generic.KeyValuePair p in wasRemoved) - { - RaiseItemsRemoved(p.Key, p.Value); + break; + } + else + { + wasRemoved.Enqueue(ie.Current); + } } } - - if ((ActiveEvents & EventType.Changed) != 0) + while (ie.MoveNext()) { - RaiseCollectionChanged(); + wasRemoved.Enqueue(ie.Current); } } - /// - /// Check if this collection contains all the values in another collection. - /// If this collection has bag semantics (AllowsDuplicates==true) - /// the check is made with respect to multiplicities, else multiplicities - /// are not taken into account. - /// - /// The - /// True if all values in itemsis in this collection. - public bool ContainsAll(SCG.IEnumerable items) + root = t.root; + size = t.size; + UniqueCount = t.UniqueCount; + blackdepth = t.blackdepth; + if (wasRemoved != null) { - //TODO: fix bag implementation - if (!isValid) + foreach (System.Collections.Generic.KeyValuePair p in wasRemoved) { - throw new ViewDisposedException("Snapshot has been disposed"); - } - //This is worst-case O(m*logn) - foreach (T item in items) - { - if (!Contains(item)) - { - return false; - } + RaiseItemsRemoved(p.Key, p.Value); } - - return true; } + if ((ActiveEvents & EventType.Changed) != 0) + { + RaiseCollectionChanged(); + } + } - //Higher order: - /// - /// Create a new indexed sorted collection consisting of the items of this - /// indexed sorted collection satisfying a certain predicate. - /// - /// The filter delegate defining the predicate. - /// The new indexed sorted collection. - public IIndexedSorted FindAll(Func filter) + /// + /// Check if this collection contains all the values in another collection. + /// If this collection has bag semantics (AllowsDuplicates==true) + /// the check is made with respect to multiplicities, else multiplicities + /// are not taken into account. + /// + /// The + /// True if all values in itemsis in this collection. + public bool ContainsAll(SCG.IEnumerable items) + { + //TODO: fix bag implementation + if (!isValid) { - if (!isValid) + throw new ViewDisposedException("Snapshot has been disposed"); + } + //This is worst-case O(m*logn) + foreach (T item in items) + { + if (!Contains(item)) { - throw new ViewDisposedException("Snapshot has been disposed"); + return false; } + } - TreeBag res = new TreeBag(comparer!); - SCG.IEnumerator e = GetEnumerator(); - Node? head = null, tail = null; - int z = 0; - - int ec = 0; + return true; + } - while (e.MoveNext()) - { - T thisitem = e.Current; - //We could document that filter will only be called - //once on each unique item. That might even be good for the user! - if (tail != null && comparer!.Compare(thisitem, tail.item) == 0) - { - tail.items++; - ec++; - continue; - } + //Higher order: + /// + /// Create a new indexed sorted collection consisting of the items of this + /// indexed sorted collection satisfying a certain predicate. + /// + /// The filter delegate defining the predicate. + /// The new indexed sorted collection. + public IIndexedSorted FindAll(Func filter) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); + } - if (filter(thisitem)) - { - if (head == null) - { - head = tail = new Node(); - } - else - { + TreeBag res = new(comparer!); + SCG.IEnumerator e = GetEnumerator(); + Node? head = null, tail = null; + int z = 0; - tail!.size = tail.items; - tail.right = new Node(); - tail = tail.right; - } + int ec = 0; - tail.item = thisitem; - z++; - } - } + while (e.MoveNext()) + { + T thisitem = e.Current; - if (tail != null) + //We could document that filter will only be called + //once on each unique item. That might even be good for the user! + if (tail != null && comparer!.Compare(thisitem, tail.item) == 0) { - tail.size = tail.items; + tail.items++; + ec++; + continue; } - if (z == 0) + if (filter(thisitem)) { - return res; - } + if (head == null) + { + head = tail = new Node(); + } + else + { - int blackheight = 0, red = z, maxred = 1; + tail!.size = tail.items; + tail.right = new Node(); + tail = tail.right; + } - while (maxred <= red) - { - red -= maxred; - maxred <<= 1; - blackheight++; + tail.item = thisitem; + z++; } + } - res.root = MakeTreer(ref head!, blackheight, maxred, red); - res.blackdepth = blackheight; - res.size = z; - res.UniqueCount = z; - res.size += ec; + if (tail != null) + { + tail.size = tail.items; + } + if (z == 0) + { return res; } + int blackheight = 0, red = z, maxred = 1; - /// - /// Create a new indexed sorted collection consisting of the results of - /// mapping all items of this list. - /// if the map is not increasing over - /// the items of this collection (with respect to the two given comparison - /// relations). - /// - /// The delegate definging the map. - /// The comparion relation to use for the result. - /// The new sorted collection. - public IIndexedSorted Map(Func mapper, SCG.IComparer c) + while (maxred <= red) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - - TreeBag res = new TreeBag(c); + red -= maxred; + maxred <<= 1; + blackheight++; + } - if (size == 0) - { - return res; - } + res.root = MakeTreer(ref head!, blackheight, maxred, red); + res.blackdepth = blackheight; + res.size = z; + res.UniqueCount = z; + res.size += ec; - SCG.IEnumerator e = GetEnumerator(); - TreeBag.Node? head = null, tail = null; - V oldv = default; - int z = 0; + return res; + } - T lastitem = default; - while (e.MoveNext()) - { - T thisitem = e.Current; + /// + /// Create a new indexed sorted collection consisting of the results of + /// mapping all items of this list. + /// if the map is not increasing over + /// the items of this collection (with respect to the two given comparison + /// relations). + /// + /// The delegate definging the map. + /// The comparion relation to use for the result. + /// The new sorted collection. + public IIndexedSorted Map(Func mapper, SCG.IComparer c) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); + } - //We could document that mapper will only be called - //once on each unique item. That might even be good for the user! - if (tail != null && comparer!.Compare(thisitem, lastitem) == 0) - { - tail.items++; - continue; - } + TreeBag res = new(c); - V newv = mapper(thisitem); + if (size == 0) + { + return res; + } - if (head == null) - { - head = tail = new TreeBag.Node(); - z++; - } - else - { - int comp = c.Compare(oldv, newv); + SCG.IEnumerator e = GetEnumerator(); + TreeBag.Node? head = null, tail = null; + V oldv = default; + int z = 0; - if (comp == 0) - { - tail!.items++; - continue; - } - if (comp > 0) - { - throw new ArgumentException("mapper not monotonic"); - } + T lastitem = default; - tail!.size = tail.items; + while (e.MoveNext()) + { + T thisitem = e.Current; - tail.right = new TreeBag.Node(); - tail = tail.right; - z++; + //We could document that mapper will only be called + //once on each unique item. That might even be good for the user! + if (tail != null && comparer!.Compare(thisitem, lastitem) == 0) + { + tail.items++; + continue; + } + + V newv = mapper(thisitem); + + if (head == null) + { + head = tail = new TreeBag.Node(); + z++; + } + else + { + int comp = c.Compare(oldv, newv); + + if (comp == 0) + { + tail!.items++; + continue; + } + if (comp > 0) + { + throw new ArgumentException("mapper not monotonic"); } - lastitem = thisitem; + tail!.size = tail.items; - tail.item = oldv = newv; + tail.right = new TreeBag.Node(); + tail = tail.right; + z++; } + lastitem = thisitem; - tail!.size = tail.items; + tail.item = oldv = newv; + } - int blackheight = 0, red = z, maxred = 1; + tail!.size = tail.items; - while (maxred <= red) - { - red -= maxred; - maxred <<= 1; - blackheight++; - } - res.root = TreeBag.MakeTreer(ref head!, blackheight, maxred, red); - res.blackdepth = blackheight; - res.size = size; - res.UniqueCount = UniqueCount; - return res; + int blackheight = 0, red = z, maxred = 1; + + while (maxred <= red) + { + red -= maxred; + maxred <<= 1; + blackheight++; } + res.root = TreeBag.MakeTreer(ref head!, blackheight, maxred, red); + res.blackdepth = blackheight; + res.size = size; + res.UniqueCount = UniqueCount; + return res; + } - //below is the bag utility stuff - /// - /// Count the number of items of the collection equal to a particular value. - /// Returns 0 if and only if the value is not in the collection. - /// - /// The value to count. - /// The number of copies found. - public int ContainsCount(T item) + + //below is the bag utility stuff + /// + /// Count the number of items of the collection equal to a particular value. + /// Returns 0 if and only if the value is not in the collection. + /// + /// The value to count. + /// The number of copies found. + public int ContainsCount(T item) + { + if (!isValid) { - if (!isValid) + throw new ViewDisposedException("Snapshot has been disposed"); + } + + Node next; + next = root!; + while (next != null) + { + int comp = comparer!.Compare(next.item, item); + if (comp == 0) { - throw new ViewDisposedException("Snapshot has been disposed"); + return next.items; } - Node next; - next = root!; - while (next != null) - { - int comp = comparer!.Compare(next.item, item); - if (comp == 0) - { - return next.items; - } + next = comp < 0 ? Right(next) : Left(next); + } - next = comp < 0 ? Right(next) : Left(next); - } + return 0; - return 0; + } - } + //TODO: make work with snapshots + private class Multiplicities : CollectionValueBase>, ICollectionValue> + { + private readonly TreeBag treebag; + private readonly int origstamp; + internal Multiplicities(TreeBag treebag) { this.treebag = treebag; origstamp = treebag.stamp; } + public override System.Collections.Generic.KeyValuePair Choose() { return new System.Collections.Generic.KeyValuePair(treebag.root!.item, treebag.root.items); } - //TODO: make work with snapshots - private class Multiplicities : CollectionValueBase>, ICollectionValue> + public override SCG.IEnumerator> GetEnumerator() { - private readonly TreeBag treebag; - private readonly int origstamp; - internal Multiplicities(TreeBag treebag) { this.treebag = treebag; origstamp = treebag.stamp; } - public override System.Collections.Generic.KeyValuePair Choose() { return new System.Collections.Generic.KeyValuePair(treebag.root!.item, treebag.root.items); } + return GetEnumerator(treebag.root!, origstamp); //TODO: NBNBNB + } - public override SCG.IEnumerator> GetEnumerator() + private SCG.IEnumerator> GetEnumerator(Node node, int origstamp) + { + if (node == null) { - return GetEnumerator(treebag.root!, origstamp); //TODO: NBNBNB + yield break; } - private SCG.IEnumerator> GetEnumerator(Node node, int origstamp) + if (node.left != null) { - if (node == null) - { - yield break; - } + SCG.IEnumerator> child = GetEnumerator(node.left, origstamp); - if (node.left != null) + while (child.MoveNext()) { - SCG.IEnumerator> child = GetEnumerator(node.left, origstamp); - - while (child.MoveNext()) - { - treebag.ModifyCheck(origstamp); - yield return child.Current; - } + treebag.ModifyCheck(origstamp); + yield return child.Current; } - yield return new System.Collections.Generic.KeyValuePair(node.item, node.items); - if (node.right != null) - { - SCG.IEnumerator> child = GetEnumerator(node.right, origstamp); + } + yield return new System.Collections.Generic.KeyValuePair(node.item, node.items); + if (node.right != null) + { + SCG.IEnumerator> child = GetEnumerator(node.right, origstamp); - while (child.MoveNext()) - { - treebag.ModifyCheck(origstamp); - yield return child.Current; - } + while (child.MoveNext()) + { + treebag.ModifyCheck(origstamp); + yield return child.Current; } } - - public override bool IsEmpty => treebag.IsEmpty; - public override int Count { get { int i = 0; foreach (System.Collections.Generic.KeyValuePair p in this) { i++; } return i; } } //TODO: make better - public override Speed CountSpeed => Speed.Linear; //TODO: make better } + public override bool IsEmpty => treebag.IsEmpty; + public override int Count { get { int i = 0; foreach (System.Collections.Generic.KeyValuePair p in this) { i++; } return i; } } //TODO: make better + public override Speed CountSpeed => Speed.Linear; //TODO: make better + } - /// - /// - /// - /// - public virtual ICollectionValue UniqueItems() + + /// + /// + /// + /// + public virtual ICollectionValue UniqueItems() + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - return new DropMultiplicity(ItemMultiplicities()); + return new DropMultiplicity(ItemMultiplicities()); - } + } - /// - /// - /// - /// - public virtual ICollectionValue> ItemMultiplicities() + /// + /// + /// + /// + public virtual ICollectionValue> ItemMultiplicities() + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } + + return new Multiplicities(this); + + } - return new Multiplicities(this); + /// + /// Remove all items equivalent to a given value. + /// + /// The value to remove. + public void RemoveAllCopies(T item) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } - /// - /// Remove all items equivalent to a given value. - /// - /// The value to remove. - public void RemoveAllCopies(T item) + UpdateCheck(); + if (RemoveIterative(ref item, true, out int removed) && ActiveEvents != 0) { + RaiseForRemove(item, removed); + } - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + } - UpdateCheck(); - if (RemoveIterative(ref item, true, out int removed) && ActiveEvents != 0) - { - RaiseForRemove(item, removed); - } - } + #endregion + #region IIndexed Members - #endregion + private Node FindNode(int i) + { + if (isSnapShot) + { + throw new NotSupportedException("Indexing not supported for snapshots"); + } - #region IIndexed Members + Node? next = root; - private Node FindNode(int i) + if (i >= 0 && i < size) { - if (isSnapShot) + while (true) { - throw new NotSupportedException("Indexing not supported for snapshots"); - } - - Node? next = root; + int j = next!.left == null ? 0 : next.left.size; - if (i >= 0 && i < size) - { - while (true) + if (i > j) { - int j = next!.left == null ? 0 : next.left.size; - - if (i > j) - { - i -= j + next.items; - if (i < 0) - { - return next; - } - - next = next.right!; - } - else if (i == j) + i -= j + next.items; + if (i < 0) { return next; } - else - { - next = next.left!; - } + + next = next.right!; + } + else if (i == j) + { + return next; + } + else + { + next = next.left!; } } + } - throw new IndexOutOfRangeException(); + throw new IndexOutOfRangeException(); - } + } - /// - /// if i is negative or - /// >= the size of the collection. - /// - /// The i'th item of this list. - /// the index to lookup - public T this[int i] => FindNode(i).item; + /// + /// if i is negative or + /// >= the size of the collection. + /// + /// The i'th item of this list. + /// the index to lookup + public T this[int i] => FindNode(i).item; - /// - /// - /// - /// - public virtual Speed IndexingSpeed => Speed.Log; + /// + /// + /// + /// + public virtual Speed IndexingSpeed => Speed.Log; - //TODO: return -upper instead of -1 in case of not found - /// - /// Searches for an item in this indexed collection going forwards from the start. - /// - /// Item to search for. - /// Index of first occurrence from start of the item - /// if found, else the two-complement - /// (always negative) of the index at which the item would be put if it was added. - public int IndexOf(T item) + //TODO: return -upper instead of -1 in case of not found + /// + /// Searches for an item in this indexed collection going forwards from the start. + /// + /// Item to search for. + /// Index of first occurrence from start of the item + /// if found, else the two-complement + /// (always negative) of the index at which the item would be put if it was added. + public int IndexOf(T item) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } + + return IndexOf(item, out _); + } + - return IndexOf(item, out _); + private int IndexOf(T item, out int upper) + { + if (isSnapShot) + { + throw new NotSupportedException("Indexing not supported for snapshots"); } + int ind = 0; Node? next = root; - private int IndexOf(T item, out int upper) + while (next != null) { - if (isSnapShot) + int comp = comparer!.Compare(item, next.item); + + if (comp < 0) { - throw new NotSupportedException("Indexing not supported for snapshots"); + next = next.left; } - - int ind = 0; Node? next = root; - - while (next != null) + else { - int comp = comparer!.Compare(item, next.item); + int leftcnt = next.left == null ? 0 : next.left.size; - if (comp < 0) + if (comp == 0) { - next = next.left; + + upper = ind + leftcnt + next.items - 1; + return ind + leftcnt; + } else { - int leftcnt = next.left == null ? 0 : next.left.size; - - if (comp == 0) - { - - upper = ind + leftcnt + next.items - 1; - return ind + leftcnt; - - } - else - { - ind = ind + next.items + leftcnt; + ind = ind + next.items + leftcnt; - next = next.right; - } + next = next.right; } } - - upper = ~ind; - return ~ind; } + upper = ~ind; + return ~ind; + } - /// - /// Searches for an item in the tree going backwards from the end. - /// - /// Item to search for. - /// Index of last occurrence from the end of item if found, - /// else the two-complement (always negative) of the index at which - /// the item would be put if it was added. - public int LastIndexOf(T item) + + /// + /// Searches for an item in the tree going backwards from the end. + /// + /// Item to search for. + /// Index of last occurrence from the end of item if found, + /// else the two-complement (always negative) of the index at which + /// the item would be put if it was added. + public int LastIndexOf(T item) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - IndexOf(item, out int res); - return res; + IndexOf(item, out int res); + return res; - } + } - /// - /// Remove the item at a specific position of the list. - /// if i is negative or - /// >= the size of the collection. - /// - /// The index of the item to remove. - /// The removed item. - public T RemoveAt(int i) + /// + /// Remove the item at a specific position of the list. + /// if i is negative or + /// >= the size of the collection. + /// + /// The index of the item to remove. + /// The removed item. + public T RemoveAt(int i) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - - UpdateCheck(); - T retval = RemoveAtInner(i); - if (ActiveEvents != 0) - { - RaiseForRemove(retval); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - return retval; + UpdateCheck(); + T retval = RemoveAtInner(i); + if (ActiveEvents != 0) + { + RaiseForRemove(retval); } - private T RemoveAtInner(int i) + return retval; + } + + private T RemoveAtInner(int i) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - UpdateCheck(); + UpdateCheck(); - if (i < 0 || i >= size) - { - throw new IndexOutOfRangeException("Index out of range for sequenced collectionvalue"); - } + if (i < 0 || i >= size) + { + throw new IndexOutOfRangeException("Index out of range for sequenced collectionvalue"); + } - //We must follow the pattern of removeIterative() - while (dirs!.Length < 2 * blackdepth) - { - dirs = new int[2 * dirs.Length]; - path = new Node[2 * dirs.Length]; - } + //We must follow the pattern of removeIterative() + while (dirs!.Length < 2 * blackdepth) + { + dirs = new int[2 * dirs.Length]; + path = new Node[2 * dirs.Length]; + } - int level = 0; - Node? cursor = root; + int level = 0; + Node? cursor = root; - while (true) + while (true) + { + int j = cursor!.left == null ? 0 : cursor.left.size; + + if (i > j) { - int j = cursor!.left == null ? 0 : cursor.left.size; - if (i > j) + i -= j + cursor.items; + if (i < 0) { + break; + } - i -= j + cursor.items; - if (i < 0) - { - break; - } - - dirs[level] = -1; - path![level++] = cursor; - cursor = cursor.right; - } - else if (i == j) - { - break; - } - else - { - dirs[level] = 1; - path![level++] = cursor; - cursor = cursor.left; - } + dirs[level] = -1; + path![level++] = cursor; + cursor = cursor.right; } - - T retval = cursor.item; - - - if (cursor.items > 1) + else if (i == j) { - RespliceBag(level, cursor); - size--; - return retval; + break; + } + else + { + dirs[level] = 1; + path![level++] = cursor; + cursor = cursor.left; } + } + + T retval = cursor.item; - RemoveIterativePhase2(cursor, level); - return retval; + if (cursor.items > 1) + { + RespliceBag(level, cursor); + size--; + return retval; } + RemoveIterativePhase2(cursor, level); + return retval; + + } + - private void RespliceBag(int level, Node cursor) + private void RespliceBag(int level, Node cursor) + { + Node.CopyNode(ref cursor, MaxSnapId, generation); + cursor.items--; + cursor.size--; + while (level-- > 0) { - Node.CopyNode(ref cursor, MaxSnapId, generation); - cursor.items--; - cursor.size--; - while (level-- > 0) - { - Node kid = cursor; + Node kid = cursor; - cursor = path![level]!; - Node.Update(ref cursor!, dirs![level] > 0, kid, MaxSnapId, generation); - cursor.size--; - path[level] = null; - } + cursor = path![level]!; + Node.Update(ref cursor!, dirs![level] > 0, kid, MaxSnapId, generation); + cursor.size--; + path[level] = null; } + } - /// - /// Remove all items in an index interval. - /// ???. - /// - /// The index of the first item to remove. - /// The number of items to remove. - public void RemoveInterval(int start, int count) + /// + /// Remove all items in an index interval. + /// ???. + /// + /// The index of the first item to remove. + /// The number of items to remove. + public void RemoveInterval(int start, int count) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - if (start < 0 || count < 0 || start + count > size) - { - throw new ArgumentOutOfRangeException(); - } + if (start < 0 || count < 0 || start + count > size) + { + throw new ArgumentOutOfRangeException(); + } - UpdateCheck(); + UpdateCheck(); - if (count == 0) - { - return; - } + if (count == 0) + { + return; + } - //This is terrible for large count. We should split the tree at - //the endpoints of the range and fuse the parts! - //We really need good internal destructive split and catenate functions! - //Alternative for large counts: rebuild tree using maketree() - for (int i = 0; i < count; i++) - { - RemoveAtInner(start); - } + //This is terrible for large count. We should split the tree at + //the endpoints of the range and fuse the parts! + //We really need good internal destructive split and catenate functions! + //Alternative for large counts: rebuild tree using maketree() + for (int i = 0; i < count; i++) + { + RemoveAtInner(start); + } - if ((ActiveEvents & EventType.Cleared) != 0) - { - RaiseCollectionCleared(false, count); - } + if ((ActiveEvents & EventType.Cleared) != 0) + { + RaiseCollectionCleared(false, count); + } - if ((ActiveEvents & EventType.Changed) != 0) - { - RaiseCollectionChanged(); - } + if ((ActiveEvents & EventType.Changed) != 0) + { + RaiseCollectionChanged(); } + } - /// - /// . - /// - /// The directed collection of items in a specific index interval. - /// The starting index of the interval (inclusive). - /// The length of the interval. - public IDirectedCollectionValue this[int start, int count] + /// + /// . + /// + /// The directed collection of items in a specific index interval. + /// The starting index of the interval (inclusive). + /// The length of the interval. + public IDirectedCollectionValue this[int start, int count] + { + get { - get - { - CheckRange(start, count); - return new Interval(this, start, count, true); - } + CheckRange(start, count); + return new Interval(this, start, count, true); } + } - #region Interval nested class - private class Interval : DirectedCollectionValueBase, IDirectedCollectionValue - { - private readonly int start, length, stamp; - private readonly bool forwards; - private readonly TreeBag tree; + #region Interval nested class + private class Interval : DirectedCollectionValueBase, IDirectedCollectionValue + { + private readonly int start, length, stamp; + private readonly bool forwards; + private readonly TreeBag tree; - internal Interval(TreeBag tree, int start, int count, bool forwards) + internal Interval(TreeBag tree, int start, int count, bool forwards) + { + if (tree.isSnapShot) { - if (tree.isSnapShot) - { - throw new NotSupportedException("Indexing not supported for snapshots"); - } - - this.start = start; length = count; this.forwards = forwards; - this.tree = tree; stamp = tree.stamp; + throw new NotSupportedException("Indexing not supported for snapshots"); } - public override bool IsEmpty => length == 0; + this.start = start; length = count; this.forwards = forwards; + this.tree = tree; stamp = tree.stamp; + } + + public override bool IsEmpty => length == 0; - public override int Count => length; + public override int Count => length; - public override Speed CountSpeed => Speed.Constant; + public override Speed CountSpeed => Speed.Constant; - public override T Choose() + public override T Choose() + { + if (length == 0) { - if (length == 0) - { - throw new NoSuchItemException(); - } - - return tree[start]; + throw new NoSuchItemException(); } - public override SCG.IEnumerator GetEnumerator() - { + return tree[start]; + } - tree.ModifyCheck(stamp); + public override SCG.IEnumerator GetEnumerator() + { - int togo; + tree.ModifyCheck(stamp); - Node cursor = tree.root!; - Node[] path = new Node[2 * tree.blackdepth]; - int level = 0, totaltogo = length; + int togo; - if (totaltogo == 0) - { - yield break; - } + Node cursor = tree.root!; + Node[] path = new Node[2 * tree.blackdepth]; + int level = 0, totaltogo = length; - if (forwards) - { - int i = start; + if (totaltogo == 0) + { + yield break; + } - while (true) - { - int j = cursor!.left == null ? 0 : cursor.left.size; + if (forwards) + { + int i = start; - if (i > j) - { + while (true) + { + int j = cursor!.left == null ? 0 : cursor.left.size; - if (cursor.items > i - j) - { - togo = cursor.items - (i - j); - break; - } - i -= j + cursor.items; + if (i > j) + { - cursor = cursor.right!; - } - else if (i == j) + if (cursor.items > i - j) { - - togo = cursor.items; - + togo = cursor.items - (i - j); break; - } // i < j, start point tree[start] is in left subtree - else - { - path[level++] = cursor; - cursor = cursor.left!; } - } + i -= j + cursor.items; - T current = cursor.item; - - while (totaltogo-- > 0) + cursor = cursor.right!; + } + else if (i == j) { - yield return current; - tree.ModifyCheck(stamp); - - if (--togo > 0) - { - continue; - } - - if (cursor.right != null) - { - path[level] = cursor = cursor.right; - while (cursor.left != null) - { - path[++level] = cursor = cursor.left; - } - } - else if (level == 0) - { - yield break; - } - else - { - cursor = path[--level]; - } - - current = cursor.item; togo = cursor.items; - } - } - else // backwards - { - int i = start + length - 1; - while (true) + break; + } // i < j, start point tree[start] is in left subtree + else { - int j = cursor!.left == null ? 0 : cursor.left.size; + path[level++] = cursor; + cursor = cursor.left!; + } + } - if (i > j) - { - if (i - j < cursor.items) - { - togo = i - j + 1; - break; - } - i -= j + cursor.items; + T current = cursor.item; - path[level++] = cursor; - cursor = cursor.right!; - } - else if (i == j) - { + while (totaltogo-- > 0) + { + yield return current; + tree.ModifyCheck(stamp); - togo = 1; + if (--togo > 0) + { + continue; + } - break; - } - else // i <= j, end point tree[start+count-1] is in left subtree + if (cursor.right != null) + { + path[level] = cursor = cursor.right; + while (cursor.left != null) { - cursor = cursor.left!; + path[++level] = cursor = cursor.left; } } + else if (level == 0) + { + yield break; + } + else + { + cursor = path[--level]; + } - T current = cursor.item; + current = cursor.item; - while (totaltogo-- > 0) - { - yield return current; - tree.ModifyCheck(stamp); + togo = cursor.items; + } + } + else // backwards + { + int i = start + length - 1; - if (--togo > 0) - { - continue; - } + while (true) + { + int j = cursor!.left == null ? 0 : cursor.left.size; - if (cursor.left != null) - { - path[level] = cursor = cursor.left; - while (cursor.right != null) - { - path[++level] = cursor = cursor.right; - } - } - else if (level == 0) - { - yield break; - } - else + if (i > j) + { + if (i - j < cursor.items) { - cursor = path[--level]; + togo = i - j + 1; + break; } + i -= j + cursor.items; - current = cursor.item; + path[level++] = cursor; + cursor = cursor.right!; + } + else if (i == j) + { - togo = cursor.items; + togo = 1; + break; + } + else // i <= j, end point tree[start+count-1] is in left subtree + { + cursor = cursor.left!; } } - } + T current = cursor.item; + while (totaltogo-- > 0) + { + yield return current; + tree.ModifyCheck(stamp); - public override IDirectedCollectionValue Backwards() - { return new Interval(tree, start, length, !forwards); } + if (--togo > 0) + { + continue; + } + if (cursor.left != null) + { + path[level] = cursor = cursor.left; + while (cursor.right != null) + { + path[++level] = cursor = cursor.right; + } + } + else if (level == 0) + { + yield break; + } + else + { + cursor = path[--level]; + } - IDirectedEnumerable C5.IDirectedEnumerable.Backwards() - { return Backwards(); } + current = cursor.item; + togo = cursor.items; + + } + } - public override Direction Direction => forwards ? Direction.Forwards : Direction.Backwards; } - #endregion - /// - /// Create a collection containing the same items as this collection, but - /// whose enumerator will enumerate the items backwards. The new collection - /// will become invalid if the original is modified. Method typically used as in - /// foreach (T x in coll.Backwards()) {...} - /// - /// The backwards collection. - public override IDirectedCollectionValue Backwards() { return RangeAll().Backwards(); } + public override IDirectedCollectionValue Backwards() + { return new Interval(tree, start, length, !forwards); } - IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } - #endregion + IDirectedEnumerable C5.IDirectedEnumerable.Backwards() + { return Backwards(); } - #region PriorityQueue Members - /// - /// The comparer object supplied at creation time for this collection - /// - /// The comparer - public SCG.IComparer Comparer => comparer!; + public override Direction Direction => forwards ? Direction.Forwards : Direction.Backwards; + } + #endregion + /// + /// Create a collection containing the same items as this collection, but + /// whose enumerator will enumerate the items backwards. The new collection + /// will become invalid if the original is modified. Method typically used as in + /// foreach (T x in coll.Backwards()) {...} + /// + /// The backwards collection. + public override IDirectedCollectionValue Backwards() { return RangeAll().Backwards(); } - /// - /// Find the current least item of this priority queue. - /// - /// The least item. - public T FindMin() - { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - if (size == 0) - { - throw new NoSuchItemException(); - } + IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } - Node? cursor = root, next = Left(cursor!); + #endregion - while (next != null) - { - cursor = next; - next = Left(cursor); - } + #region PriorityQueue Members - return cursor!.item; - } + /// + /// The comparer object supplied at creation time for this collection + /// + /// The comparer + public SCG.IComparer Comparer => comparer!; - /// - /// Remove the least item from this priority queue. - /// - /// The removed item. - public T DeleteMin() + /// + /// Find the current least item of this priority queue. + /// + /// The least item. + public T FindMin() + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - - UpdateCheck(); - - //persistence guard? - if (size == 0) - { - throw new NoSuchItemException(); - } - - //We must follow the pattern of removeIterative() - StackCheck(); - - T retval = DeleteMinInner(); - if (ActiveEvents != 0) - { - RaiseItemsRemoved(retval, 1); - RaiseCollectionChanged(); - } - return retval; + throw new ViewDisposedException("Snapshot has been disposed"); } - private T DeleteMinInner() + if (size == 0) { - int level = 0; - Node? cursor = root; + throw new NoSuchItemException(); + } - while (cursor!.left != null) - { - dirs![level] = 1; - path![level++] = cursor; - cursor = cursor.left; - } + Node? cursor = root, next = Left(cursor!); - T retval = cursor.item; + while (next != null) + { + cursor = next; + next = Left(cursor); + } + return cursor!.item; + } - if (cursor.items > 1) - { - RespliceBag(level, cursor); - size--; - return retval; - } - RemoveIterativePhase2(cursor, level); - return retval; + /// + /// Remove the least item from this priority queue. + /// + /// The removed item. + public T DeleteMin() + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } + UpdateCheck(); - /// - /// Find the current largest item of this priority queue. - /// - /// The largest item. - public T FindMax() + //persistence guard? + if (size == 0) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new NoSuchItemException(); + } - if (size == 0) - { - throw new NoSuchItemException(); - } + //We must follow the pattern of removeIterative() + StackCheck(); - Node cursor = root!, next = Right(cursor!); + T retval = DeleteMinInner(); + if (ActiveEvents != 0) + { + RaiseItemsRemoved(retval, 1); + RaiseCollectionChanged(); + } + return retval; + } - while (next != null) - { - cursor = next; - next = Right(cursor); - } + private T DeleteMinInner() + { + int level = 0; + Node? cursor = root; - return cursor.item; + while (cursor!.left != null) + { + dirs![level] = 1; + path![level++] = cursor; + cursor = cursor.left; } + T retval = cursor.item; - /// - /// Remove the largest item from this priority queue. - /// - /// The removed item. - public T DeleteMax() + + if (cursor.items > 1) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - //persistence guard? - UpdateCheck(); - if (size == 0) - { - throw new NoSuchItemException(); - } + RespliceBag(level, cursor); + size--; + return retval; + } - //We must follow the pattern of removeIterative() - StackCheck(); + RemoveIterativePhase2(cursor, level); + return retval; + } - T retval = DeleteMaxInner(); - if (ActiveEvents != 0) - { - RaiseItemsRemoved(retval, 1); - RaiseCollectionChanged(); - } - return retval; + + /// + /// Find the current largest item of this priority queue. + /// + /// The largest item. + public T FindMax() + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } - private T DeleteMaxInner() + if (size == 0) { - int level = 0; - Node? cursor = root; + throw new NoSuchItemException(); + } - while (cursor!.right != null) - { - dirs![level] = -1; - path![level++] = cursor; - cursor = cursor.right; - } + Node cursor = root!, next = Right(cursor!); - T retval = cursor.item; + while (next != null) + { + cursor = next; + next = Right(cursor); + } + return cursor.item; + } - if (cursor.items > 1) - { - RespliceBag(level, cursor); - size--; - return retval; - } - RemoveIterativePhase2(cursor, level); - return retval; + /// + /// Remove the largest item from this priority queue. + /// + /// The removed item. + public T DeleteMax() + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); + } + //persistence guard? + UpdateCheck(); + if (size == 0) + { + throw new NoSuchItemException(); } - #endregion - #region ISorted Members + //We must follow the pattern of removeIterative() + StackCheck(); - /// - /// Find the strict predecessor of item in the sorted collection, - /// that is, the greatest item in the collection smaller than the item. - /// - /// The item to find the predecessor for. - /// The predecessor, if any; otherwise the default value for T. - /// True if item has a predecessor; otherwise false. - public bool TryPredecessor(T item, out T res) + T retval = DeleteMaxInner(); + if (ActiveEvents != 0) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - - Node? cursor = root, bestsofar = null; + RaiseItemsRemoved(retval, 1); + RaiseCollectionChanged(); + } + return retval; + } - while (cursor != null) - { - int comp = comparer!.Compare(cursor.item, item); + private T DeleteMaxInner() + { + int level = 0; + Node? cursor = root; - if (comp < 0) - { - bestsofar = cursor; - cursor = Right(cursor); - } - else if (comp == 0) - { - cursor = Left(cursor); - while (cursor != null) - { - bestsofar = cursor; - cursor = Right(cursor); - } - } - else - { - cursor = Left(cursor); - } - } - if (bestsofar == null) - { - res = default; - return false; - } - else - { - res = bestsofar.item; - return true; - } + while (cursor!.right != null) + { + dirs![level] = -1; + path![level++] = cursor; + cursor = cursor.right; } + T retval = cursor.item; - /// - /// Find the strict successor of item in the sorted collection, - /// that is, the least item in the collection greater than the supplied value. - /// - /// The item to find the successor for. - /// The successor, if any; otherwise the default value for T. - /// True if item has a successor; otherwise false. - public bool TrySuccessor(T item, out T res) - { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - Node? cursor = root, bestsofar = null; + if (cursor.items > 1) + { + RespliceBag(level, cursor); + size--; + return retval; + } - while (cursor != null) - { - int comp = comparer!.Compare(cursor.item, item); + RemoveIterativePhase2(cursor, level); + return retval; + } + #endregion - if (comp > 0) - { - bestsofar = cursor; - cursor = Left(cursor); - } - else if (comp == 0) - { - cursor = Right(cursor); - while (cursor != null) - { - bestsofar = cursor; - cursor = Left(cursor); - } - } - else - { - cursor = Right(cursor); - } - } + #region ISorted Members - if (bestsofar == null) - { - res = default; - return false; - } - else - { - res = bestsofar.item; - return true; - } + /// + /// Find the strict predecessor of item in the sorted collection, + /// that is, the greatest item in the collection smaller than the item. + /// + /// The item to find the predecessor for. + /// The predecessor, if any; otherwise the default value for T. + /// True if item has a predecessor; otherwise false. + public bool TryPredecessor(T item, out T res) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } + Node? cursor = root, bestsofar = null; - /// - /// Find the weak predecessor of item in the sorted collection, - /// that is, the greatest item in the collection smaller than or equal to the item. - /// - /// The item to find the weak predecessor for. - /// The weak predecessor, if any; otherwise the default value for T. - /// True if item has a weak predecessor; otherwise false. - public bool TryWeakPredecessor(T item, out T res) + while (cursor != null) { - if (!isValid) + int comp = comparer!.Compare(cursor.item, item); + + if (comp < 0) { - throw new ViewDisposedException("Snapshot has been disposed"); + bestsofar = cursor; + cursor = Right(cursor); } - - Node? cursor = root, bestsofar = null; - - while (cursor != null) + else if (comp == 0) { - int comp = comparer!.Compare(cursor.item, item); - - if (comp < 0) + cursor = Left(cursor); + while (cursor != null) { bestsofar = cursor; cursor = Right(cursor); } - else if (comp == 0) - { - res = cursor.item; - return true; - } - else - { - cursor = Left(cursor); - } - } - if (bestsofar == null) - { - res = default; - return false; } else { - res = bestsofar.item; - return true; + cursor = Left(cursor); } } + if (bestsofar == null) + { + res = default; + return false; + } + else + { + res = bestsofar.item; + return true; + } + } - /// - /// Find the weak successor of item in the sorted collection, - /// that is, the least item in the collection greater than or equal to the supplied value. - /// - /// The item to find the weak successor for. - /// The weak successor, if any; otherwise the default value for T. - /// True if item has a weak successor; otherwise false. - public bool TryWeakSuccessor(T item, out T res) + /// + /// Find the strict successor of item in the sorted collection, + /// that is, the least item in the collection greater than the supplied value. + /// + /// The item to find the successor for. + /// The successor, if any; otherwise the default value for T. + /// True if item has a successor; otherwise false. + public bool TrySuccessor(T item, out T res) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - Node? cursor = root, bestsofar = null; + Node? cursor = root, bestsofar = null; - while (cursor != null) - { - int comp = comparer!.Compare(cursor.item, item); + while (cursor != null) + { + int comp = comparer!.Compare(cursor.item, item); - if (comp == 0) - { - res = cursor.item; - return true; - } - else if (comp > 0) + if (comp > 0) + { + bestsofar = cursor; + cursor = Left(cursor); + } + else if (comp == 0) + { + cursor = Right(cursor); + while (cursor != null) { bestsofar = cursor; cursor = Left(cursor); } - else - { - cursor = Right(cursor); - } - } - - if (bestsofar == null) - { - res = default; - return false; } else { - res = bestsofar.item; - return true; + cursor = Right(cursor); } } + if (bestsofar == null) + { + res = default; + return false; + } + else + { + res = bestsofar.item; + return true; + } + } + - /// - /// Find the strict predecessor in the sorted collection of a particular value, - /// i.e. the largest item in the collection less than the supplied value. - /// - /// if no such element exists (the - /// supplied value is less than or equal to the minimum of this collection.) - /// The item to find the predecessor for. - /// The predecessor. - public T Predecessor(T item) + /// + /// Find the weak predecessor of item in the sorted collection, + /// that is, the greatest item in the collection smaller than or equal to the item. + /// + /// The item to find the weak predecessor for. + /// The weak predecessor, if any; otherwise the default value for T. + /// True if item has a weak predecessor; otherwise false. + public bool TryWeakPredecessor(T item, out T res) + { + if (!isValid) { - if (TryPredecessor(item, out T res)) - { - return res; - } - else - { - throw new NoSuchItemException(); - } + throw new ViewDisposedException("Snapshot has been disposed"); } + Node? cursor = root, bestsofar = null; - /// - /// Find the weak predecessor in the sorted collection of a particular value, - /// i.e. the largest item in the collection less than or equal to the supplied value. - /// - /// if no such element exists (the - /// supplied value is less than the minimum of this collection.) - /// The item to find the weak predecessor for. - /// The weak predecessor. - public T WeakPredecessor(T item) + while (cursor != null) { - if (TryWeakPredecessor(item, out T res)) + int comp = comparer!.Compare(cursor.item, item); + + if (comp < 0) { - return res; + bestsofar = cursor; + cursor = Right(cursor); + } + else if (comp == 0) + { + res = cursor.item; + return true; } else { - throw new NoSuchItemException(); + cursor = Left(cursor); } } + if (bestsofar == null) + { + res = default; + return false; + } + else + { + res = bestsofar.item; + return true; + } + } - /// - /// Find the strict successor in the sorted collection of a particular value, - /// i.e. the least item in the collection greater than the supplied value. - /// - /// if no such element exists (the - /// supplied value is greater than or equal to the maximum of this collection.) - /// The item to find the successor for. - /// The successor. - public T Successor(T item) + /// + /// Find the weak successor of item in the sorted collection, + /// that is, the least item in the collection greater than or equal to the supplied value. + /// + /// The item to find the weak successor for. + /// The weak successor, if any; otherwise the default value for T. + /// True if item has a weak successor; otherwise false. + public bool TryWeakSuccessor(T item, out T res) + { + if (!isValid) { - if (TrySuccessor(item, out T res)) - { - return res; - } - else - { - throw new NoSuchItemException(); - } + throw new ViewDisposedException("Snapshot has been disposed"); } + Node? cursor = root, bestsofar = null; - /// - /// Find the weak successor in the sorted collection of a particular value, - /// i.e. the least item in the collection greater than or equal to the supplied value. - /// if no such element exists (the - /// supplied value is greater than the maximum of this collection.) - /// - /// The item to find the weak successor for. - /// The weak successor. - public T WeakSuccessor(T item) + while (cursor != null) { - if (TryWeakSuccessor(item, out T res)) + int comp = comparer!.Compare(cursor.item, item); + + if (comp == 0) + { + res = cursor.item; + return true; + } + else if (comp > 0) { - return res; + bestsofar = cursor; + cursor = Left(cursor); } else { - throw new NoSuchItemException(); + cursor = Right(cursor); } } + if (bestsofar == null) + { + res = default; + return false; + } + else + { + res = bestsofar.item; + return true; + } + } + - /// - /// Query this sorted collection for items greater than or equal to a supplied value. - /// - /// The lower bound (inclusive). - /// The result directed collection. - public IDirectedCollectionValue RangeFrom(T bot) + /// + /// Find the strict predecessor in the sorted collection of a particular value, + /// i.e. the largest item in the collection less than the supplied value. + /// + /// if no such element exists (the + /// supplied value is less than or equal to the minimum of this collection.) + /// The item to find the predecessor for. + /// The predecessor. + public T Predecessor(T item) + { + if (TryPredecessor(item, out T res)) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + return res; + } + else + { + throw new NoSuchItemException(); + } + } + - return new Range(this, true, bot, false, default, Direction.Forwards); + /// + /// Find the weak predecessor in the sorted collection of a particular value, + /// i.e. the largest item in the collection less than or equal to the supplied value. + /// + /// if no such element exists (the + /// supplied value is less than the minimum of this collection.) + /// The item to find the weak predecessor for. + /// The weak predecessor. + public T WeakPredecessor(T item) + { + if (TryWeakPredecessor(item, out T res)) + { + return res; + } + else + { + throw new NoSuchItemException(); } + } - /// - /// Query this sorted collection for items between two supplied values. - /// - /// The lower bound (inclusive). - /// The upper bound (exclusive). - /// The result directed collection. - public IDirectedCollectionValue RangeFromTo(T bot, T top) + /// + /// Find the strict successor in the sorted collection of a particular value, + /// i.e. the least item in the collection greater than the supplied value. + /// + /// if no such element exists (the + /// supplied value is greater than or equal to the maximum of this collection.) + /// The item to find the successor for. + /// The successor. + public T Successor(T item) + { + if (TrySuccessor(item, out T res)) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + return res; + } + else + { + throw new NoSuchItemException(); + } + } - return new Range(this, true, bot, true, top, Direction.Forwards); + + /// + /// Find the weak successor in the sorted collection of a particular value, + /// i.e. the least item in the collection greater than or equal to the supplied value. + /// if no such element exists (the + /// supplied value is greater than the maximum of this collection.) + /// + /// The item to find the weak successor for. + /// The weak successor. + public T WeakSuccessor(T item) + { + if (TryWeakSuccessor(item, out T res)) + { + return res; } + else + { + throw new NoSuchItemException(); + } + } - /// - /// Query this sorted collection for items less than a supplied value. - /// - /// The upper bound (exclusive). - /// The result directed collection. - public IDirectedCollectionValue RangeTo(T top) + /// + /// Query this sorted collection for items greater than or equal to a supplied value. + /// + /// The lower bound (inclusive). + /// The result directed collection. + public IDirectedCollectionValue RangeFrom(T bot) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } + + return new Range(this, true, bot, false, default, Direction.Forwards); + } + - return new Range(this, false, default, true, top, Direction.Forwards); + /// + /// Query this sorted collection for items between two supplied values. + /// + /// The lower bound (inclusive). + /// The upper bound (exclusive). + /// The result directed collection. + public IDirectedCollectionValue RangeFromTo(T bot, T top) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } + return new Range(this, true, bot, true, top, Direction.Forwards); + } - /// - /// Create a directed collection with the same items as this collection. - /// - /// The result directed collection. - public IDirectedCollectionValue RangeAll() + + /// + /// Query this sorted collection for items less than a supplied value. + /// + /// The upper bound (exclusive). + /// The result directed collection. + public IDirectedCollectionValue RangeTo(T top) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - return new Range(this, false, default, false, default, Direction.Forwards); + return new Range(this, false, default, true, top, Direction.Forwards); + } + + + /// + /// Create a directed collection with the same items as this collection. + /// + /// The result directed collection. + public IDirectedCollectionValue RangeAll() + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } + return new Range(this, false, default, false, default, Direction.Forwards); + } + - IDirectedEnumerable ISorted.RangeFrom(T bot) { return RangeFrom(bot); } + IDirectedEnumerable ISorted.RangeFrom(T bot) { return RangeFrom(bot); } - IDirectedEnumerable ISorted.RangeFromTo(T bot, T top) { return RangeFromTo(bot, top); } + IDirectedEnumerable ISorted.RangeFromTo(T bot, T top) { return RangeFromTo(bot, top); } - IDirectedEnumerable ISorted.RangeTo(T top) { return RangeTo(top); } + IDirectedEnumerable ISorted.RangeTo(T top) { return RangeTo(top); } - //Utility for CountXxxx. Actually always called with strict = true. - private int CountTo(T item, bool strict) + //Utility for CountXxxx. Actually always called with strict = true. + private int CountTo(T item, bool strict) + { + if (isSnapShot) { - if (isSnapShot) - { - throw new NotSupportedException("Indexing not supported for snapshots"); - } + throw new NotSupportedException("Indexing not supported for snapshots"); + } - int ind = 0; Node? next = root; + int ind = 0; Node? next = root; - while (next != null) + while (next != null) + { + int comp = comparer!.Compare(item, next.item); + if (comp < 0) { - int comp = comparer!.Compare(item, next.item); - if (comp < 0) + next = next.left; + } + else + { + int leftcnt = next.left == null ? 0 : next.left.size; + + if (comp == 0) { - next = next.left; + return strict ? ind + leftcnt : ind + leftcnt + next.items; } else { - int leftcnt = next.left == null ? 0 : next.left.size; - - if (comp == 0) - { - return strict ? ind + leftcnt : ind + leftcnt + next.items; - } - else - { - ind = ind + next.items + leftcnt; - next = next.right; - } - + ind = ind + next.items + leftcnt; + next = next.right; } + } + } + + //if we get here, we are at the same side of the whole collection: + return ind; + + } - //if we get here, we are at the same side of the whole collection: - return ind; + /// + /// Perform a search in the sorted collection for the ranges in which a + /// non-increasing (i.e. weakly decreasing) function from the item type to + /// int is + /// negative, zero respectively positive. If the supplied cut function is + /// not non-increasing, the result of this call is undefined. + /// + /// The cut function T to int, given + /// as an IComparable<T> object, where the cut function is + /// the c.CompareTo(T that) method. + /// Returns the largest item in the collection, where the + /// cut function is positive (if any). + /// True if the cut function is positive somewhere + /// on this collection. + /// Returns the least item in the collection, where the + /// cut function is negative (if any). + /// True if the cut function is negative somewhere + /// on this collection. + /// + public bool Cut(IComparable c, out T low, out bool lowIsValid, out T high, out bool highIsValid) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } + Node? cursor = root, lbest = null, rbest = null; + bool res = false; - /// - /// Perform a search in the sorted collection for the ranges in which a - /// non-increasing (i.e. weakly decreasing) function from the item type to - /// int is - /// negative, zero respectively positive. If the supplied cut function is - /// not non-increasing, the result of this call is undefined. - /// - /// The cut function T to int, given - /// as an IComparable<T> object, where the cut function is - /// the c.CompareTo(T that) method. - /// Returns the largest item in the collection, where the - /// cut function is positive (if any). - /// True if the cut function is positive somewhere - /// on this collection. - /// Returns the least item in the collection, where the - /// cut function is negative (if any). - /// True if the cut function is negative somewhere - /// on this collection. - /// - public bool Cut(IComparable c, out T low, out bool lowIsValid, out T high, out bool highIsValid) + while (cursor != null) { - if (!isValid) + int comp = c.CompareTo(cursor.item); + + if (comp > 0) { - throw new ViewDisposedException("Snapshot has been disposed"); + lbest = cursor; + cursor = Right(cursor); } - - Node? cursor = root, lbest = null, rbest = null; - bool res = false; - - while (cursor != null) + else if (comp < 0) { - int comp = c.CompareTo(cursor.item); + rbest = cursor; + cursor = Left(cursor); + } + else + { + res = true; - if (comp > 0) - { - lbest = cursor; - cursor = Right(cursor); - } - else if (comp < 0) + Node tmp = Left(cursor); + + while (tmp != null && c.CompareTo(tmp.item) == 0) { - rbest = cursor; - cursor = Left(cursor); + tmp = Left(tmp); } - else - { - res = true; - - Node tmp = Left(cursor); - while (tmp != null && c.CompareTo(tmp.item) == 0) - { - tmp = Left(tmp); - } - - if (tmp != null) + if (tmp != null) + { + lbest = tmp; + tmp = Right(tmp); + while (tmp != null) { - lbest = tmp; - tmp = Right(tmp); - while (tmp != null) + if (c.CompareTo(tmp.item) > 0) { - if (c.CompareTo(tmp.item) > 0) - { - lbest = tmp; - tmp = Right(tmp); - } - else - { - tmp = Left(tmp); - } + lbest = tmp; + tmp = Right(tmp); + } + else + { + tmp = Left(tmp); } } + } - tmp = Right(cursor); - while (tmp != null && c.CompareTo(tmp.item) == 0) - { - tmp = Right(tmp); - } + tmp = Right(cursor); + while (tmp != null && c.CompareTo(tmp.item) == 0) + { + tmp = Right(tmp); + } - if (tmp != null) + if (tmp != null) + { + rbest = tmp; + tmp = Left(tmp); + while (tmp != null) { - rbest = tmp; - tmp = Left(tmp); - while (tmp != null) + if (c.CompareTo(tmp.item) < 0) { - if (c.CompareTo(tmp.item) < 0) - { - rbest = tmp; - tmp = Left(tmp); - } - else - { - tmp = Right(tmp); - } + rbest = tmp; + tmp = Left(tmp); + } + else + { + tmp = Right(tmp); } } - - break; } - } - if (highIsValid = (rbest != null)) - { - high = rbest!.item; - } - else - { - high = default; + break; } + } - if (lowIsValid = (lbest != null)) - { - low = lbest!.item; - } - else - { - low = default; - } + if (highIsValid = (rbest != null)) + { + high = rbest!.item; + } + else + { + high = default; + } - return res; + if (lowIsValid = (lbest != null)) + { + low = lbest!.item; + } + else + { + low = default; } + return res; + } + - /// - /// Determine the number of items at or above a supplied threshold. - /// - /// The lower bound (inclusive) - /// The number of matching items. - public int CountFrom(T bot) + /// + /// Determine the number of items at or above a supplied threshold. + /// + /// The lower bound (inclusive) + /// The number of matching items. + public int CountFrom(T bot) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - - return size - CountTo(bot, true); + throw new ViewDisposedException("Snapshot has been disposed"); } + return size - CountTo(bot, true); + } - /// - /// Determine the number of items between two supplied thresholds. - /// - /// The lower bound (inclusive) - /// The upper bound (exclusive) - /// The number of matching items. - public int CountFromTo(T bot, T top) - { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - if (comparer!.Compare(bot, top) >= 0) - { - return 0; - } + /// + /// Determine the number of items between two supplied thresholds. + /// + /// The lower bound (inclusive) + /// The upper bound (exclusive) + /// The number of matching items. + public int CountFromTo(T bot, T top) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); + } - return CountTo(top, true) - CountTo(bot, true); + if (comparer!.Compare(bot, top) >= 0) + { + return 0; } + return CountTo(top, true) - CountTo(bot, true); + } - /// - /// Determine the number of items below a supplied threshold. - /// - /// The upper bound (exclusive) - /// The number of matching items. - public int CountTo(T top) - { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - return CountTo(top, true); + /// + /// Determine the number of items below a supplied threshold. + /// + /// The upper bound (exclusive) + /// The number of matching items. + public int CountTo(T top) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } + return CountTo(top, true); + } - /// - /// Remove all items of this collection above or at a supplied threshold. - /// - /// The lower threshold (inclusive). - public void RemoveRangeFrom(T low) + + /// + /// Remove all items of this collection above or at a supplied threshold. + /// + /// The lower threshold (inclusive). + public void RemoveRangeFrom(T low) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - UpdateCheck(); + UpdateCheck(); - int count = CountFrom(low); + int count = CountFrom(low); - if (count == 0) - { - return; - } + if (count == 0) + { + return; + } - StackCheck(); - CircularQueue? wasRemoved = (ActiveEvents & EventType.Removed) != 0 ? new CircularQueue() : null; + StackCheck(); + CircularQueue? wasRemoved = (ActiveEvents & EventType.Removed) != 0 ? new CircularQueue() : null; - for (int i = 0; i < count; i++) - { - T item = DeleteMaxInner(); - wasRemoved?.Enqueue(item); - } - if (wasRemoved != null) - { - RaiseForRemoveAll(wasRemoved); - } - else if ((ActiveEvents & EventType.Changed) != 0) - { - RaiseCollectionChanged(); - } + for (int i = 0; i < count; i++) + { + T item = DeleteMaxInner(); + wasRemoved?.Enqueue(item); + } + if (wasRemoved != null) + { + RaiseForRemoveAll(wasRemoved); } + else if ((ActiveEvents & EventType.Changed) != 0) + { + RaiseCollectionChanged(); + } + } - /// - /// Remove all items of this collection between two supplied thresholds. - /// - /// The lower threshold (inclusive). - /// The upper threshold (exclusive). - public void RemoveRangeFromTo(T low, T hi) + /// + /// Remove all items of this collection between two supplied thresholds. + /// + /// The lower threshold (inclusive). + /// The upper threshold (exclusive). + public void RemoveRangeFromTo(T low, T hi) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - UpdateCheck(); + UpdateCheck(); - int count = CountFromTo(low, hi); + int count = CountFromTo(low, hi); - if (count == 0) - { - return; - } + if (count == 0) + { + return; + } - CircularQueue? wasRemoved = (ActiveEvents & EventType.Removed) != 0 ? new CircularQueue() : null; - for (int i = 0; i < count; i++) - { - T item = Predecessor(hi); - RemoveIterative(ref item, false, out _); - wasRemoved?.Enqueue(item); - } - if (wasRemoved != null) - { - RaiseForRemoveAll(wasRemoved); - } - else if ((ActiveEvents & EventType.Changed) != 0) - { - RaiseCollectionChanged(); - } + CircularQueue? wasRemoved = (ActiveEvents & EventType.Removed) != 0 ? new CircularQueue() : null; + for (int i = 0; i < count; i++) + { + T item = Predecessor(hi); + RemoveIterative(ref item, false, out _); + wasRemoved?.Enqueue(item); + } + if (wasRemoved != null) + { + RaiseForRemoveAll(wasRemoved); + } + else if ((ActiveEvents & EventType.Changed) != 0) + { + RaiseCollectionChanged(); } + } - /// - /// Remove all items of this collection below a supplied threshold. - /// - /// The upper threshold (exclusive). - public void RemoveRangeTo(T hi) + /// + /// Remove all items of this collection below a supplied threshold. + /// + /// The upper threshold (exclusive). + public void RemoveRangeTo(T hi) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - UpdateCheck(); + UpdateCheck(); - int count = CountTo(hi); + int count = CountTo(hi); - if (count == 0) - { - return; - } + if (count == 0) + { + return; + } - StackCheck(); - CircularQueue? wasRemoved = (ActiveEvents & EventType.Removed) != 0 ? new CircularQueue() : null; + StackCheck(); + CircularQueue? wasRemoved = (ActiveEvents & EventType.Removed) != 0 ? new CircularQueue() : null; - for (int i = 0; i < count; i++) - { - T item = DeleteMinInner(); - wasRemoved?.Enqueue(item); - } - if (wasRemoved != null) - { - RaiseForRemoveAll(wasRemoved); - } - else if ((ActiveEvents & EventType.Changed) != 0) - { - RaiseCollectionChanged(); - } + for (int i = 0; i < count; i++) + { + T item = DeleteMinInner(); + wasRemoved?.Enqueue(item); + } + if (wasRemoved != null) + { + RaiseForRemoveAll(wasRemoved); + } + else if ((ActiveEvents & EventType.Changed) != 0) + { + RaiseCollectionChanged(); } + } - #endregion + #endregion - #region IPersistent Members - private int MaxSnapId => snapList == null ? -1 : FindLastLiveSnapShot(); + #region IPersistent Members + private int MaxSnapId => snapList == null ? -1 : FindLastLiveSnapShot(); - private int FindLastLiveSnapShot() + private int FindLastLiveSnapShot() + { + if (snapList == null) { - if (snapList == null) - { - return -1; - } + return -1; + } - SnapRef? lastLiveSnapRef = snapList.Prev; - object? _snapshot = null; - while (lastLiveSnapRef != null && (_snapshot = lastLiveSnapRef.Tree.Target) == null) - { - lastLiveSnapRef = lastLiveSnapRef.Prev; - } + SnapRef? lastLiveSnapRef = snapList.Prev; + object? _snapshot = null; + while (lastLiveSnapRef != null && (_snapshot = lastLiveSnapRef.Tree.Target) == null) + { + lastLiveSnapRef = lastLiveSnapRef.Prev; + } - if (lastLiveSnapRef == null) - { - snapList = null; - return -1; - } - if (snapList.Prev != lastLiveSnapRef) - { - snapList.Prev = lastLiveSnapRef; - lastLiveSnapRef.Next = snapList; - } - return ((TreeBag)_snapshot!)!.generation; + if (lastLiveSnapRef == null) + { + snapList = null; + return -1; } + if (snapList.Prev != lastLiveSnapRef) + { + snapList.Prev = lastLiveSnapRef; + lastLiveSnapRef.Next = snapList; + } + return ((TreeBag)_snapshot!)!.generation; + } - private class SnapRef + private class SnapRef + { + public SnapRef? Prev, Next; + public WeakReference Tree; + public SnapRef(TreeBag tree) { Tree = new WeakReference(tree); } + public void Dispose() { - public SnapRef? Prev, Next; - public WeakReference Tree; - public SnapRef(TreeBag tree) { Tree = new WeakReference(tree); } - public void Dispose() + Next!.Prev = Prev; + if (Prev != null) { - Next!.Prev = Prev; - if (Prev != null) - { - Prev.Next = Next; - } - - Next = Prev = null; + Prev.Next = Next; } + + Next = Prev = null; } + } - #region IDisposable Support - private bool _disposed = false; // To detect redundant calls + #region IDisposable Support + private bool _disposed = false; // To detect redundant calls - /// - /// If this tree is a snapshot, remove registration in base tree - /// - /// - protected virtual void Dispose(bool disposing) + /// + /// If this tree is a snapshot, remove registration in base tree + /// + /// + protected virtual void Dispose(bool disposing) + { + if (!_disposed) { - if (!_disposed) + if (disposing) { - if (disposing) + if (!isValid) { - if (!isValid) - { - return; - } + return; + } - if (isSnapShot) - { - snapList!.Dispose(); - SnapDispose(); - } - else + if (isSnapShot) + { + snapList!.Dispose(); + SnapDispose(); + } + else + { + if (snapList != null) { - if (snapList != null) + SnapRef someSnapRef = snapList.Prev!; + while (someSnapRef != null) { - SnapRef someSnapRef = snapList.Prev!; - while (someSnapRef != null) + if (someSnapRef.Tree.Target is TreeBag lastsnap) { - if (someSnapRef.Tree.Target is TreeBag lastsnap) - { - lastsnap.SnapDispose(); - } - - someSnapRef = someSnapRef.Prev!; + lastsnap.SnapDispose(); } + + someSnapRef = someSnapRef.Prev!; } - snapList = null; - Clear(); } + snapList = null; + Clear(); } - - _disposed = true; } - } - /// - /// If this tree is a snapshot, remove registration in base tree - /// - public void Dispose() - { - // Do not change this code. Put cleanup code in Dispose(bool disposing) above. - Dispose(true); - // TODO: uncomment the following line if the finalizer is overridden above. - GC.SuppressFinalize(this); + _disposed = true; } - #endregion + } + + /// + /// If this tree is a snapshot, remove registration in base tree + /// + public void Dispose() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + Dispose(true); + // TODO: uncomment the following line if the finalizer is overridden above. + GC.SuppressFinalize(this); + } + #endregion + + private void SnapDispose() + { + root = null; + dirs = null; + path = null; + comparer = null; + isValid = false; + snapList = null; + } - private void SnapDispose() + /// + /// Make a (read-only) snapshot of this collection. + /// + /// The snapshot. + public ISorted Snapshot() + { + if (isSnapShot) { - root = null; - dirs = null; - path = null; - comparer = null; - isValid = false; - snapList = null; + throw new InvalidOperationException("Cannot snapshot a snapshot"); } - /// - /// Make a (read-only) snapshot of this collection. - /// - /// The snapshot. - public ISorted Snapshot() - { - if (isSnapShot) - { - throw new InvalidOperationException("Cannot snapshot a snapshot"); - } + TreeBag res = (TreeBag)MemberwiseClone(); + SnapRef newSnapRef = new(res); + res.isReadOnlyBase = true; + res.isSnapShot = true; + res.snapList = newSnapRef; - TreeBag res = (TreeBag)MemberwiseClone(); - SnapRef newSnapRef = new SnapRef(res); - res.isReadOnlyBase = true; - res.isSnapShot = true; - res.snapList = newSnapRef; + FindLastLiveSnapShot(); + snapList ??= new SnapRef(this); - FindLastLiveSnapShot(); - snapList ??= new SnapRef(this); + SnapRef? lastLiveSnapRef = snapList.Prev; - SnapRef? lastLiveSnapRef = snapList.Prev; + newSnapRef.Prev = lastLiveSnapRef; + if (lastLiveSnapRef != null) + { + lastLiveSnapRef.Next = newSnapRef; + } - newSnapRef.Prev = lastLiveSnapRef; - if (lastLiveSnapRef != null) - { - lastLiveSnapRef.Next = newSnapRef; - } + newSnapRef.Next = snapList; + snapList.Prev = newSnapRef; - newSnapRef.Next = snapList; - snapList.Prev = newSnapRef; + generation++; - generation++; + return res; + } - return res; - } + #endregion - #endregion + #region TreeBag.Range nested class - #region TreeBag.Range nested class + internal class Range : DirectedCollectionValueBase, IDirectedCollectionValue + { + private int stamp; + private readonly int size; + private readonly TreeBag basis; - internal class Range : DirectedCollectionValueBase, IDirectedCollectionValue - { - private int stamp; - private readonly int size; - private readonly TreeBag basis; + private readonly T lowend, highend; - private readonly T lowend, highend; + private readonly bool haslowend, hashighend; + private Direction direction; - private readonly bool haslowend, hashighend; - private Direction direction; + public Range(TreeBag basis, bool haslowend, T lowend, bool hashighend, T highend, Direction direction) + { + this.basis = basis; + stamp = basis.stamp; - public Range(TreeBag basis, bool haslowend, T lowend, bool hashighend, T highend, Direction direction) + //lowind will be const; should we cache highind? + this.lowend = lowend; //Inclusive + this.highend = highend;//Exclusive + this.haslowend = haslowend; + this.hashighend = hashighend; + this.direction = direction; + if (!basis.isSnapShot) { - this.basis = basis; - stamp = basis.stamp; - - //lowind will be const; should we cache highind? - this.lowend = lowend; //Inclusive - this.highend = highend;//Exclusive - this.haslowend = haslowend; - this.hashighend = hashighend; - this.direction = direction; - if (!basis.isSnapShot) - { - size = haslowend ? - (hashighend ? basis.CountFromTo(lowend, highend) : basis.CountFrom(lowend)) : - (hashighend ? basis.CountTo(highend) : basis.Count); - } + size = haslowend ? + (hashighend ? basis.CountFromTo(lowend, highend) : basis.CountFrom(lowend)) : + (hashighend ? basis.CountTo(highend) : basis.Count); } + } - #region IEnumerable Members + #region IEnumerable Members - #region TreeBag.Range.Enumerator nested class + #region TreeBag.Range.Enumerator nested class - internal class Enumerator : SCG.IEnumerator - { - #region Private Fields - private bool valid = false, ready = true; + internal class Enumerator : SCG.IEnumerator + { + #region Private Fields + private bool valid = false, ready = true; - private SCG.IComparer? comparer; + private SCG.IComparer? comparer; - private T current; - private int togo; + private T current; + private int togo; + + private Node? cursor; + + private Node[]? path; // stack of nodes + + private int level = 0; - private Node? cursor; + private Range? range; - private Node[]? path; // stack of nodes + private readonly bool forwards; - private int level = 0; + #endregion + public Enumerator(Range range) + { + comparer = range.basis.comparer; + path = new Node[2 * range.basis.blackdepth]; + this.range = range; + forwards = range.direction == Direction.Forwards; + cursor = new Node(); + if (forwards) + { + cursor.right = range.basis.root; + } + else + { + cursor.left = range.basis.root!; + } - private Range? range; + range.basis.ModifyCheck(range.stamp); + } - private readonly bool forwards; + private int Compare(T i1, T i2) + { + return comparer!.Compare(i1, i2); + } - #endregion - public Enumerator(Range range) + /// + /// Undefined if enumerator is not valid (MoveNext hash been called returning true) + /// + /// The current value of the enumerator. + public T Current + { + get { - comparer = range.basis.comparer; - path = new Node[2 * range.basis.blackdepth]; - this.range = range; - forwards = range.direction == Direction.Forwards; - cursor = new Node(); - if (forwards) + if (valid) { - cursor.right = range.basis.root; + return current; } else { - cursor.left = range.basis.root!; + throw new InvalidOperationException(); } + } + } - range.basis.ModifyCheck(range.stamp); - } - private int Compare(T i1, T i2) + //Maintain a stack of nodes that are roots of + //subtrees not completely exported yet. Invariant: + //The stack nodes together with their right subtrees + //consists of exactly the items we have not passed + //yet (the top of the stack holds current item). + /// + /// Move enumerator to next item in tree, or the first item if + /// this is the first call to MoveNext. + /// if underlying tree was modified. + /// + /// True if enumerator is valid now + public bool MoveNext() + { + range!.basis.ModifyCheck(range.stamp); + if (!ready) { - return comparer!.Compare(i1, i2); + return false; } - /// - /// Undefined if enumerator is not valid (MoveNext hash been called returning true) - /// - /// The current value of the enumerator. - public T Current + if (--togo > 0) { - get - { - if (valid) - { - return current; - } - else - { - throw new InvalidOperationException(); - } - } + return true; } - - //Maintain a stack of nodes that are roots of - //subtrees not completely exported yet. Invariant: - //The stack nodes together with their right subtrees - //consists of exactly the items we have not passed - //yet (the top of the stack holds current item). - /// - /// Move enumerator to next item in tree, or the first item if - /// this is the first call to MoveNext. - /// if underlying tree was modified. - /// - /// True if enumerator is valid now - public bool MoveNext() + if (forwards) { - range!.basis.ModifyCheck(range.stamp); - if (!ready) - { - return false; - } - - if (--togo > 0) - { - return true; - } - - if (forwards) + if (!valid && range.haslowend) { - if (!valid && range.haslowend) + cursor = cursor!.right!; + while (cursor != null) { - cursor = cursor!.right!; - while (cursor != null) + int comp = Compare(cursor.item, range.lowend); + + if (comp > 0) { - int comp = Compare(cursor.item, range.lowend); - - if (comp > 0) - { - path![level++] = cursor; - cursor = range.basis.Left(cursor); - - } - else if (comp < 0) - { - cursor = range.basis.Right(cursor); - - } - else - { - path![level] = cursor; - break; - } + path![level++] = cursor; + cursor = range.basis.Left(cursor); + } + else if (comp < 0) + { + cursor = range.basis.Right(cursor); - if (cursor == null) + } + else { - if (level == 0) - { - return valid = ready = false; - } - else - { - cursor = path![--level]; - } + path![level] = cursor; + break; } } - else if (range.basis.Right(cursor!) != null) - { - path![level] = cursor = range.basis.Right(cursor!); - Node next = range.basis.Left(cursor); - - while (next != null) + if (cursor == null) + { + if (level == 0) + { + return valid = ready = false; + } + else { - path[++level] = cursor = next; - next = range.basis.Left(cursor); + cursor = path![--level]; } } + } + else if (range.basis.Right(cursor!) != null) + { + path![level] = cursor = range.basis.Right(cursor!); - else if (level == 0) - { - return valid = ready = false; - } - else - { - cursor = path![--level]; - } + Node next = range.basis.Left(cursor); - current = cursor.item; - if (range.hashighend && Compare(current, range.highend) >= 0) + while (next != null) { - return valid = ready = false; + path[++level] = cursor = next; + next = range.basis.Left(cursor); } + } - togo = cursor.items; - - return valid = true; + else if (level == 0) + { + return valid = ready = false; } else { - if (!valid && range.hashighend) - { - cursor = cursor!.left; - while (cursor != null) - { - int comp = Compare(cursor.item, range.highend); - - if (comp < 0) - { - path![level++] = cursor; - cursor = range.basis.Right(cursor); + cursor = path![--level]; + } - } - else - { - cursor = range.basis.Left(cursor); + current = cursor.item; + if (range.hashighend && Compare(current, range.highend) >= 0) + { + return valid = ready = false; + } - } - } + togo = cursor.items; - if (cursor == null) - { - if (level == 0) - { - return valid = ready = false; - } - else - { - cursor = path![--level]; - } - } - } - else if (range.basis.Left(cursor!) != null) + return valid = true; + } + else + { + if (!valid && range.hashighend) + { + cursor = cursor!.left; + while (cursor != null) { - path![level] = cursor = range.basis.Left(cursor!); + int comp = Compare(cursor.item, range.highend); - Node next = range.basis.Right(cursor); + if (comp < 0) + { + path![level++] = cursor; + cursor = range.basis.Right(cursor); - while (next != null) + } + else { - path[++level] = cursor = next; - next = range.basis.Right(cursor); + cursor = range.basis.Left(cursor); + } } - else if (level == 0) - { - return valid = ready = false; - } - else + if (cursor == null) { - cursor = path![--level]; + if (level == 0) + { + return valid = ready = false; + } + else + { + cursor = path![--level]; + } } + } + else if (range.basis.Left(cursor!) != null) + { + path![level] = cursor = range.basis.Left(cursor!); - current = cursor.item; - if (range.haslowend && Compare(current, range.lowend) < 0) + Node next = range.basis.Right(cursor); + + while (next != null) { - return valid = ready = false; + path[++level] = cursor = next; + next = range.basis.Right(cursor); } + } - togo = cursor.items; + else if (level == 0) + { + return valid = ready = false; + } + else + { + cursor = path![--level]; + } - return valid = true; + current = cursor.item; + if (range.haslowend && Compare(current, range.lowend) < 0) + { + return valid = ready = false; } - } + togo = cursor.items; - public void Dispose() - { - comparer = null; - current = default; - cursor = null; - path = null; - range = null; + return valid = true; } + } - #region IEnumerator Members - object System.Collections.IEnumerator.Current => Current!; + public void Dispose() + { + comparer = null; + current = default; + cursor = null; + path = null; + range = null; + } - bool System.Collections.IEnumerator.MoveNext() - { - return MoveNext(); - } + #region IEnumerator Members - void System.Collections.IEnumerator.Reset() - { - throw new NotImplementedException(); - } + object System.Collections.IEnumerator.Current => Current!; + + bool System.Collections.IEnumerator.MoveNext() + { + return MoveNext(); + } - #endregion + void System.Collections.IEnumerator.Reset() + { + throw new NotImplementedException(); } #endregion + } + #endregion - public override T Choose() - { - if (size == 0) - { - throw new NoSuchItemException(); - } - return lowend; + public override T Choose() + { + if (size == 0) + { + throw new NoSuchItemException(); } - public override SCG.IEnumerator GetEnumerator() { return new Enumerator(this); } + return lowend; + } + public override SCG.IEnumerator GetEnumerator() { return new Enumerator(this); } - public override Direction Direction => direction; + public override Direction Direction => direction; - #endregion - #region Utility + #endregion - /* bool inside(T item) - { - return (!haslowend || basis.comparer!.Compare(item, lowend) >= 0) && (!hashighend || basis.comparer!.Compare(item, highend) < 0); - } */ + #region Utility + /* bool inside(T item) + { + return (!haslowend || basis.comparer!.Compare(item, lowend) >= 0) && (!hashighend || basis.comparer!.Compare(item, highend) < 0); + } */ - /* void checkstamp() - { - if (stamp < basis.stamp) - throw new CollectionModifiedException(); - } */ + /* void checkstamp() + { + if (stamp < basis.stamp) + throw new CollectionModifiedException(); + } */ - // void syncstamp() { stamp = basis.stamp; } - #endregion + // void syncstamp() { stamp = basis.stamp; } - public override IDirectedCollectionValue Backwards() - { - Range b = (Range)MemberwiseClone(); + #endregion - b.direction = direction == Direction.Forwards ? Direction.Backwards : Direction.Forwards; - return b; - } + public override IDirectedCollectionValue Backwards() + { + Range b = (Range)MemberwiseClone(); + b.direction = direction == Direction.Forwards ? Direction.Backwards : Direction.Forwards; + return b; + } - IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } + IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } - public override bool IsEmpty => size == 0; - public override int Count => size; + public override bool IsEmpty => size == 0; - //TODO: check that this is correct - public override Speed CountSpeed => Speed.Constant; + public override int Count => size; - } + //TODO: check that this is correct + public override Speed CountSpeed => Speed.Constant; - #endregion + } - #region Diagnostics - /// - /// Display this node on the console, and recursively its subnodes. - /// - /// Node to display - /// Indentation - private void MiniDump(Node n, string space) + #endregion + + #region Diagnostics + /// + /// Display this node on the console, and recursively its subnodes. + /// + /// Node to display + /// Indentation + private void MiniDump(Node n, string space) + { + if (n == null) { - if (n == null) - { - // System.Logger.Log(space + "null"); - } - else - { - MiniDump(n.right!, space + " "); - Logger.Log(string.Format("{0} {4} (size={1}, items={8}, h={2}, gen={3}, id={6}){7}", space + n.item, + // System.Logger.Log(space + "null"); + } + else + { + MiniDump(n.right!, space + " "); + Logger.Log(string.Format("{0} {4} (size={1}, items={8}, h={2}, gen={3}, id={6}){7}", space + n.item, - n.size, +n.size, - 0, - n.generation, - n.red ? "RED" : "BLACK", - 0, - 0, +0, +n.generation, +n.red ? "RED" : "BLACK", + 0, + 0, - n.lastgeneration == -1 ? "" : string.Format(" [extra: lg={0}, c={1}, i={2}]", n.lastgeneration, n.leftnode ? "L" : "R", n.oldref == null ? "()" : "" + n.oldref.item), +n.lastgeneration == -1 ? "" : string.Format(" [extra: lg={0}, c={1}, i={2}]", n.lastgeneration, n.leftnode ? "L" : "R", n.oldref == null ? "()" : "" + n.oldref.item), - n.items +n.items )); - MiniDump(n.left, space + " "); - } + MiniDump(n.left, space + " "); } + } - /// - /// Print the tree structure to the console stdout. - /// - public void Dump() { Dump(""); } + /// + /// Print the tree structure to the console stdout. + /// + public void Dump() { Dump(""); } - /// - /// Print the tree structure to the console stdout. - /// - public void Dump(string msg) - { - Logger.Log(string.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4}, uniqueCount={5})", msg, size, blackdepth, - 0, generation, UniqueCount)); - MiniDump(root!, ""); - CheckInner(); Logger.Log("<<<<<<<<<<<<<<<<<<<"); - } + /// + /// Print the tree structure to the console stdout. + /// + public void Dump(string msg) + { + Logger.Log(string.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4}, uniqueCount={5})", msg, size, blackdepth, + 0, generation, UniqueCount)); + MiniDump(root!, ""); + CheckInner(); Logger.Log("<<<<<<<<<<<<<<<<<<<"); + } - /// - /// Display this tree on the console. - /// - /// Identifying string of this call to dump - /// Extra (error)message to include - private void Dump(string msg, string err) - { - Logger.Log(string.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4}, uniqueCount={5})", msg, size, blackdepth, - 0, generation, UniqueCount)); - MiniDump(root!, ""); Logger.Log(err); - Logger.Log("<<<<<<<<<<<<<<<<<<<"); - } + /// + /// Display this tree on the console. + /// + /// Identifying string of this call to dump + /// Extra (error)message to include + private void Dump(string msg, string err) + { + Logger.Log(string.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4}, uniqueCount={5})", msg, size, blackdepth, + 0, generation, UniqueCount)); + MiniDump(root!, ""); Logger.Log(err); + Logger.Log("<<<<<<<<<<<<<<<<<<<"); + } - /// - /// Print warning m on logger if b is false. - /// - /// Condition that should hold - /// Place (used for id display) - /// Message - /// b - private bool Massert(bool b, Node n, string m) + /// + /// Print warning m on logger if b is false. + /// + /// Condition that should hold + /// Place (used for id display) + /// Message + /// b + private bool Massert(bool b, Node n, string m) + { + if (!b) { - if (!b) - { - Logger.Log(string.Format("*** Node (item={0}, id={1}): {2}", n.item, - 0 - , m)); - } - - return b; + Logger.Log(string.Format("*** Node (item={0}, id={1}): {2}", n.item, + 0 + , m)); } - private bool RbMiniCheck(Node n, bool redp, out T min, out T max, out int blackheight) - {//Red-Black invariant - bool res = true; - - res = Massert(!(n.red && redp), n, "RED parent of RED node") && res; - res = Massert(n.left == null || n.right != null || n.left.red, n, "Left child black, but right child empty") && res; - res = Massert(n.right == null || n.left != null || n.right.red, n, "Right child black, but left child empty") && res; + return b; + } - bool sb = n.size == (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items; + private bool RbMiniCheck(Node n, bool redp, out T min, out T max, out int blackheight) + {//Red-Black invariant + bool res = true; - res = Massert(sb, n, "Bad size") && res; + res = Massert(!(n.red && redp), n, "RED parent of RED node") && res; + res = Massert(n.left == null || n.right != null || n.left.red, n, "Left child black, but right child empty") && res; + res = Massert(n.right == null || n.left != null || n.right.red, n, "Right child black, but left child empty") && res; - min = max = n.item; + bool sb = n.size == (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items; - T otherext; - int lbh = 0, rbh = 0; + res = Massert(sb, n, "Bad size") && res; - if (n.left != null) - { - res = RbMiniCheck(n.left, n.red, out min, out otherext, out lbh) && res; - res = Massert(comparer!.Compare(n.item, otherext) > 0, n, "Value not > all left children") && res; - } + min = max = n.item; - if (n.right != null) - { - res = RbMiniCheck(n.right, n.red, out otherext, out max, out rbh) && res; - res = Massert(comparer!.Compare(n.item, otherext) < 0, n, "Value not < all right children") && res; - } + T otherext; + int lbh = 0, rbh = 0; - res = Massert(rbh == lbh, n, "Different blackheights of children") && res; - blackheight = n.red ? rbh : rbh + 1; - return res; + if (n.left != null) + { + res = RbMiniCheck(n.left, n.red, out min, out otherext, out lbh) && res; + res = Massert(comparer!.Compare(n.item, otherext) > 0, n, "Value not > all left children") && res; } - private bool RbMiniSnapCheck(Node n, out int size, out T min, out T max) + if (n.right != null) { - bool res = true; + res = RbMiniCheck(n.right, n.red, out otherext, out max, out rbh) && res; + res = Massert(comparer!.Compare(n.item, otherext) < 0, n, "Value not < all right children") && res; + } - min = max = n.item; + res = Massert(rbh == lbh, n, "Different blackheights of children") && res; + blackheight = n.red ? rbh : rbh + 1; + return res; + } - int lsz = 0, rsz = 0; - T otherext; + private bool RbMiniSnapCheck(Node n, out int size, out T min, out T max) + { + bool res = true; - Node child = (n.lastgeneration >= generation && n.leftnode) ? n.oldref! : n.left; - if (child != null) - { - res = RbMiniSnapCheck(child, out lsz, out min, out otherext) && res; - res = Massert(comparer!.Compare(n.item, otherext) > 0, n, "Value not > all left children") && res; - } + min = max = n.item; + int lsz = 0, rsz = 0; + T otherext; - child = ((n.lastgeneration >= generation && !n.leftnode) ? n.oldref : n.right)!; - if (child != null) - { - res = RbMiniSnapCheck(child, out rsz, out otherext, out max) && res; - res = Massert(comparer!.Compare(n.item, otherext) < 0, n, "Value not < all right children") && res; - } + Node child = (n.lastgeneration >= generation && n.leftnode) ? n.oldref! : n.left; + if (child != null) + { + res = RbMiniSnapCheck(child, out lsz, out min, out otherext) && res; + res = Massert(comparer!.Compare(n.item, otherext) > 0, n, "Value not > all left children") && res; + } - size = n.items + lsz + rsz; - return res; + child = ((n.lastgeneration >= generation && !n.leftnode) ? n.oldref : n.right)!; + if (child != null) + { + res = RbMiniSnapCheck(child, out rsz, out otherext, out max) && res; + res = Massert(comparer!.Compare(n.item, otherext) < 0, n, "Value not < all right children") && res; } - /// - /// Checks red-black invariant. Dumps tree to console if bad - /// - /// Title of dump - /// false if invariant violation - public bool Check(string name) - { - System.Text.StringBuilder e = new System.Text.StringBuilder(); + size = n.items + lsz + rsz; - if (!CheckInner()) - { - return true; - } - else - { - Dump(name, e.ToString()); - return false; - } - } + return res; + } + /// + /// Checks red-black invariant. Dumps tree to console if bad + /// + /// Title of dump + /// false if invariant violation + public bool Check(string name) + { + System.Text.StringBuilder e = new(); - /// - /// Checks red-black invariant. Dumps tree to console if bad - /// - /// false if invariant violation - public bool Check() + if (!CheckInner()) { - //return check(""); - //Logger.Log("bamse"); - if (!isValid) - { - return true; - } + return true; + } + else + { + Dump(name, e.ToString()); + return false; + } + } + - return Check("-"); + /// + /// Checks red-black invariant. Dumps tree to console if bad + /// + /// false if invariant violation + public bool Check() + { + //return check(""); + //Logger.Log("bamse"); + if (!isValid) + { + return true; } - private bool CheckInner() + return Check("-"); + } + + private bool CheckInner() + { + if (root != null) { - if (root != null) + if (isSnapShot) { - if (isSnapShot) - { - //Logger.Log("Im'a snapshot"); - bool rv = RbMiniSnapCheck(root, out int thesize, out _, out _); + //Logger.Log("Im'a snapshot"); + bool rv = RbMiniSnapCheck(root, out int thesize, out _, out _); - rv = Massert(size == thesize, root, "bad snapshot size") && rv; - return !rv; - } - bool res = RbMiniCheck(root, false, out _, out _, out int blackheight); - res = Massert(blackheight == blackdepth, root, "bad blackh/d") && res; - res = Massert(!root.red, root, "root is red") && res; + rv = Massert(size == thesize, root, "bad snapshot size") && rv; + return !rv; + } + bool res = RbMiniCheck(root, false, out _, out _, out int blackheight); + res = Massert(blackheight == blackdepth, root, "bad blackh/d") && res; + res = Massert(!root.red, root, "root is red") && res; - res = Massert(root.size == size, root, "count!=root.size") && res; + res = Massert(root.size == size, root, "count!=root.size") && res; - return !res; - } - else - { - return false; - } + return !res; + } + else + { + return false; } - #endregion } + #endregion } diff --git a/C5/Trees/TreeDictionary.cs b/C5/Trees/TreeDictionary.cs index 0cd0a104..ff3a78a2 100644 --- a/C5/Trees/TreeDictionary.cs +++ b/C5/Trees/TreeDictionary.cs @@ -4,47 +4,47 @@ using System; using SCG = System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// A sorted generic dictionary based on a red-black tree set. +/// +public class TreeDictionary : SortedDictionaryBase, IDictionary, ISortedDictionary { + + #region Constructors + + /// + /// Create a red-black tree dictionary using the natural comparer for keys. + /// if the key type K is not comparable. + /// + public TreeDictionary() : this(SCG.Comparer.Default, EqualityComparer.Default) { } + + /// + /// Create a red-black tree dictionary using an external comparer for keys. + /// + /// The external comparer + public TreeDictionary(SCG.IComparer comparer) : this(comparer, new ComparerZeroHashCodeEqualityComparer(comparer)) { } + + private TreeDictionary(SCG.IComparer comparer, SCG.IEqualityComparer equalityComparer) + : base(comparer, equalityComparer) + { + pairs = sortedPairs = new TreeSet>(new KeyValuePairComparer(comparer)); + } + + #endregion + + //TODO: put in interface /// - /// A sorted generic dictionary based on a red-black tree set. + /// Make a snapshot of the current state of this dictionary /// - public class TreeDictionary : SortedDictionaryBase, IDictionary, ISortedDictionary + /// The snapshot + public SCG.IEnumerable> Snapshot() { + TreeDictionary res = (TreeDictionary)MemberwiseClone(); + + res.pairs = (TreeSet>)((TreeSet>)sortedPairs).Snapshot(); - #region Constructors - - /// - /// Create a red-black tree dictionary using the natural comparer for keys. - /// if the key type K is not comparable. - /// - public TreeDictionary() : this(SCG.Comparer.Default, EqualityComparer.Default) { } - - /// - /// Create a red-black tree dictionary using an external comparer for keys. - /// - /// The external comparer - public TreeDictionary(SCG.IComparer comparer) : this(comparer, new ComparerZeroHashCodeEqualityComparer(comparer)) { } - - private TreeDictionary(SCG.IComparer comparer, SCG.IEqualityComparer equalityComparer) - : base(comparer, equalityComparer) - { - pairs = sortedpairs = new TreeSet>(new KeyValuePairComparer(comparer)); - } - - #endregion - - //TODO: put in interface - /// - /// Make a snapshot of the current state of this dictionary - /// - /// The snapshot - public SCG.IEnumerable> Snapshot() - { - TreeDictionary res = (TreeDictionary)MemberwiseClone(); - - res.pairs = (TreeSet>)((TreeSet>)sortedpairs).Snapshot(); - return res; - } + return res; } } \ No newline at end of file diff --git a/C5/Trees/TreeSet.cs b/C5/Trees/TreeSet.cs index 3313ac1e..08a234f4 100644 --- a/C5/Trees/TreeSet.cs +++ b/C5/Trees/TreeSet.cs @@ -4,4151 +4,4150 @@ using System; using SCG = System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// An implementation of Red-Black trees as an indexed, sorted collection with set semantics, +/// cf. CLRS. for a version +/// with bag semantics. for a sorted dictionary +/// based on this tree implementation. +/// +/// The comparer (sorting order) may be either natural, because the item type is comparable +/// (generic: or non-generic: System.IComparable) or it can +/// be external and supplied by the user in the constructor. +/// +/// TODO: describe performance here +/// TODO: discuss persistence and its useful usage modes. Warn about the space +/// leak possible with other usage modes. +/// +public class TreeSet : SequencedBase, IIndexedSorted, IPersistentSorted { - /// - /// An implementation of Red-Black trees as an indexed, sorted collection with set semantics, - /// cf. CLRS. for a version - /// with bag semantics. for a sorted dictionary - /// based on this tree implementation. - /// - /// The comparer (sorting order) may be either natural, because the item type is comparable - /// (generic: or non-generic: System.IComparable) or it can - /// be external and supplied by the user in the constructor. - /// - /// TODO: describe performance here - /// TODO: discuss persistence and its useful usage modes. Warn about the space - /// leak possible with other usage modes. - /// - public class TreeSet : SequencedBase, IIndexedSorted, IPersistentSorted - { - #region Fields + #region Fields - private SCG.IComparer? comparer; - private Node? root; + private SCG.IComparer? comparer; + private Node? root; - //TODO: wonder if we should remove that - private int blackdepth = 0; + //TODO: wonder if we should remove that + private int blackdepth = 0; - //We double these stacks for the iterative add and remove on demand - //TODO: refactor dirs[] into bool fields on Node (?) - private int[]? dirs = new int[2]; + //We double these stacks for the iterative add and remove on demand + //TODO: refactor dirs[] into bool fields on Node (?) + private int[]? dirs = new int[2]; - private Node?[]? path = new Node[2]; + private Node?[]? path = new Node[2]; - //TODO: refactor into separate class - private bool isSnapShot = false; - private int generation; - private bool isValid = true; - private SnapRef? snapList; + //TODO: refactor into separate class + private bool isSnapShot = false; + private int generation; + private bool isValid = true; + private SnapRef? snapList; - #endregion + #endregion - #region Events + #region Events - /// - /// - /// - /// - public override EventType ListenableEvents => EventType.Basic; + /// + /// + /// + /// + public override EventType ListenableEvents => EventType.Basic; - #endregion - #region Util + #endregion + #region Util - /// - /// Fetch the left child of n taking node-copying persistence into - /// account if relevant. - /// - /// - /// - private Node Left(Node n) + /// + /// Fetch the left child of n taking node-copying persistence into + /// account if relevant. + /// + /// + /// + private Node Left(Node n) + { + if (isSnapShot) { - if (isSnapShot) - { - if (n.lastgeneration >= generation && n.leftnode) - { - return n.oldref; - } + if (n.lastgeneration >= generation && n.leftnode) + { + return n.oldref; } - return n.left!; } + return n.left!; + } - private Node Right(Node n) + private Node Right(Node n) + { + if (isSnapShot) { - if (isSnapShot) - { - if (n.lastgeneration >= generation && !n.leftnode) - { - return n.oldref; - } + if (n.lastgeneration >= generation && !n.leftnode) + { + return n.oldref; } - return n.right!; } + return n.right!; + } - //This method should be called by methods that use the internal - //traversal stack, unless certain that there is room enough - private void StackCheck() + //This method should be called by methods that use the internal + //traversal stack, unless certain that there is room enough + private void StackCheck() + { + while (dirs!.Length < 2 * blackdepth) { - while (dirs!.Length < 2 * blackdepth) - { - dirs = new int[2 * dirs.Length]; - path = new Node[2 * dirs.Length]; - } + dirs = new int[2 * dirs.Length]; + path = new Node[2 * dirs.Length]; } + } - #endregion - - #region Node nested class + #endregion + #region Node nested class - /// - /// The type of node in a Red-Black binary tree - /// - private class Node - { - public bool red = true; - public T item; + /// + /// The type of node in a Red-Black binary tree + /// + private class Node + { + public bool red = true; - public Node? left; + public T item; - public Node? right; + public Node? left; - public int size = 1; + public Node? right; - //TODO: move everything into (separate) Extra - public int generation; + public int size = 1; - public int lastgeneration = -1; + //TODO: move everything into (separate) Extra + public int generation; - public Node? oldref; + public int lastgeneration = -1; - public bool leftnode; + public Node? oldref; - /// - /// Update a child pointer - /// - /// - /// - /// - /// - /// - /// True if node was *copied* - internal static bool Update(ref Node cursor, bool leftnode, Node child, int maxsnapid, int generation) - { - Node oldref = (leftnode ? cursor.left : cursor.right)!; + public bool leftnode; - if (child == oldref) - { - return false; - } + /// + /// Update a child pointer + /// + /// + /// + /// + /// + /// + /// True if node was *copied* + internal static bool Update(ref Node cursor, bool leftnode, Node child, int maxsnapid, int generation) + { + Node oldref = (leftnode ? cursor.left : cursor.right)!; - bool retval = false; + if (child == oldref) + { + return false; + } - if (cursor.generation <= maxsnapid) - { - if (cursor.lastgeneration == -1) - { - cursor.leftnode = leftnode; - cursor.lastgeneration = maxsnapid; - cursor.oldref = oldref!; - } - else if (cursor.leftnode != leftnode || cursor.lastgeneration < maxsnapid) - { - CopyNode(ref cursor, maxsnapid, generation); - retval = true; - } - } + bool retval = false; - if (leftnode) + if (cursor.generation <= maxsnapid) + { + if (cursor.lastgeneration == -1) { - cursor.left = child; + cursor.leftnode = leftnode; + cursor.lastgeneration = maxsnapid; + cursor.oldref = oldref!; } - else + else if (cursor.leftnode != leftnode || cursor.lastgeneration < maxsnapid) { - cursor.right = child; + CopyNode(ref cursor, maxsnapid, generation); + retval = true; } + } - return retval; + if (leftnode) + { + cursor.left = child; + } + else + { + cursor.right = child; } + return retval; + } - //If cursor.extra.lastgeneration==maxsnapid, the extra pointer will - //always be used in the old copy of cursor. Therefore, after - //making the clone, we should update the old copy by restoring - //the child pointer and setting extra to null. - //OTOH then we cannot clean up unused Extra objects unless we link - //them together in a doubly linked list. - public static bool CopyNode(ref Node cursor, int maxsnapid, int generation) - { - if (cursor.generation <= maxsnapid) - { - cursor = (Node)(cursor.MemberwiseClone()); - cursor.generation = generation; - cursor.lastgeneration = -1; - return true; - } - return false; + //If cursor.extra.lastgeneration==maxsnapid, the extra pointer will + //always be used in the old copy of cursor. Therefore, after + //making the clone, we should update the old copy by restoring + //the child pointer and setting extra to null. + //OTOH then we cannot clean up unused Extra objects unless we link + //them together in a doubly linked list. + public static bool CopyNode(ref Node cursor, int maxsnapid, int generation) + { + if (cursor.generation <= maxsnapid) + { + cursor = (Node)(cursor.MemberwiseClone()); + cursor.generation = generation; + cursor.lastgeneration = -1; + return true; } + + return false; } + } - #endregion + #endregion - #region Constructors + #region Constructors - /// - /// Create a red-black tree collection with natural comparer and item equalityComparer. - /// We assume that if T is comparable, its default equalityComparer - /// will be compatible with the comparer. - /// - /// If T is not comparable. - /// - public TreeSet() : this(SCG.Comparer.Default, EqualityComparer.Default) { } + /// + /// Create a red-black tree collection with natural comparer and item equalityComparer. + /// We assume that if T is comparable, its default equalityComparer + /// will be compatible with the comparer. + /// + /// If T is not comparable. + /// + public TreeSet() : this(SCG.Comparer.Default, EqualityComparer.Default) { } - /// - /// Create a red-black tree collection with an external comparer. - /// The itemequalityComparer will be a compatible - /// since the - /// default equalityComparer for T () - /// is unlikely to be compatible with the external comparer. This makes the - /// tree inadequate for use as item in a collection of unsequenced or sequenced sets or bags - /// ( and ) - /// - /// - /// The external comparer - public TreeSet(SCG.IComparer comparer) : this(comparer, new ComparerZeroHashCodeEqualityComparer(comparer)) { } + /// + /// Create a red-black tree collection with an external comparer. + /// The itemequalityComparer will be a compatible + /// since the + /// default equalityComparer for T () + /// is unlikely to be compatible with the external comparer. This makes the + /// tree inadequate for use as item in a collection of unsequenced or sequenced sets or bags + /// ( and ) + /// + /// + /// The external comparer + public TreeSet(SCG.IComparer comparer) : this(comparer, new ComparerZeroHashCodeEqualityComparer(comparer)) { } + /// + /// Create a red-black tree collection with an external comparer and an external + /// item equalityComparer, assumed consistent. + /// + /// The external comparer + /// The external item equalitySCG.Comparer + public TreeSet(SCG.IComparer comparer, SCG.IEqualityComparer equalityComparer) + : base(equalityComparer) + { + this.comparer = comparer ?? throw new NullReferenceException("Item comparer cannot be null"); + } + + #endregion + + #region TreeSet.Enumerator nested class + + /// + /// An enumerator for a red-black tree collection. Based on an explicit stack + /// of subtrees waiting to be enumerated. Currently only used for the tree set + /// enumerators (tree bag enumerators use an iterator block based enumerator). + /// + internal class Enumerator : SCG.IEnumerator + { + #region Private Fields + private readonly TreeSet tree; + private bool valid = false; + private readonly int stamp; + private T current; + private Node? cursor; + private Node[]? path; // stack of nodes + + private int level = 0; + #endregion /// - /// Create a red-black tree collection with an external comparer and an external - /// item equalityComparer, assumed consistent. + /// Create a tree enumerator /// - /// The external comparer - /// The external item equalitySCG.Comparer - public TreeSet(SCG.IComparer comparer, SCG.IEqualityComparer equalityComparer) - : base(equalityComparer) + /// The red-black tree to enumerate + public Enumerator(TreeSet tree) { - this.comparer = comparer ?? throw new NullReferenceException("Item comparer cannot be null"); + this.tree = tree; + stamp = tree.stamp; + path = new Node[2 * tree.blackdepth]; + cursor = new Node + { + right = tree.root + }; } - #endregion - - #region TreeSet.Enumerator nested class /// - /// An enumerator for a red-black tree collection. Based on an explicit stack - /// of subtrees waiting to be enumerated. Currently only used for the tree set - /// enumerators (tree bag enumerators use an iterator block based enumerator). + /// Undefined if enumerator is not valid (MoveNext hash been called returning true) /// - internal class Enumerator : SCG.IEnumerator + /// The current item of the enumerator. + public T Current { - #region Private Fields - private readonly TreeSet tree; - private bool valid = false; - private readonly int stamp; - private T current; - private Node? cursor; - private Node[]? path; // stack of nodes - - private int level = 0; - #endregion - /// - /// Create a tree enumerator - /// - /// The red-black tree to enumerate - public Enumerator(TreeSet tree) + get { - this.tree = tree; - stamp = tree.stamp; - path = new Node[2 * tree.blackdepth]; - cursor = new Node + if (valid) { - right = tree.root - }; + return current; + } + else + { + throw new InvalidOperationException(); + } } + } - /// - /// Undefined if enumerator is not valid (MoveNext hash been called returning true) - /// - /// The current item of the enumerator. - public T Current + //Maintain a stack of nodes that are roots of + //subtrees not completely exported yet. Invariant: + //The stack nodes together with their right subtrees + //consists of exactly the items we have not passed + //yet (the top of the stack holds current item). + /// + /// Move enumerator to next item in tree, or the first item if + /// this is the first call to MoveNext. + /// if underlying tree was modified. + /// + /// True if enumerator is valid now + public bool MoveNext() + { + tree.ModifyCheck(stamp); + if (cursor!.right != null) { - get + path![level] = cursor = cursor.right; + while (cursor.left != null) { - if (valid) - { - return current; - } - else - { - throw new InvalidOperationException(); - } + path[++level] = cursor = cursor.left; } } + else if (level == 0) + { + return valid = false; + } + else + { + cursor = path![--level]; + } + current = cursor.item; + return valid = true; + } - //Maintain a stack of nodes that are roots of - //subtrees not completely exported yet. Invariant: - //The stack nodes together with their right subtrees - //consists of exactly the items we have not passed - //yet (the top of the stack holds current item). - /// - /// Move enumerator to next item in tree, or the first item if - /// this is the first call to MoveNext. - /// if underlying tree was modified. - /// - /// True if enumerator is valid now - public bool MoveNext() + + #region IDisposable Members for Enumerator + + private bool disposed; + + + /// + /// Call Dispose(true) and then suppress finalization of this enumerator. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + + /// + /// Remove the internal data (notably the stack array). + /// + /// True if called from Dispose(), + /// false if called from the finalizer + protected virtual void Dispose(bool disposing) + { + if (!disposed) { - tree.ModifyCheck(stamp); - if (cursor!.right != null) - { - path![level] = cursor = cursor.right; - while (cursor.left != null) - { - path[++level] = cursor = cursor.left; - } - } - else if (level == 0) - { - return valid = false; - } - else + if (disposing) { - cursor = path![--level]; } - current = cursor.item; - return valid = true; + current = default; + cursor = null; + path = null; + disposed = true; } + } - #region IDisposable Members for Enumerator + /// + /// Finalizer for enumerator + /// + ~Enumerator() + { + Dispose(false); + } + #endregion - private bool disposed; + #region IEnumerator Members - /// - /// Call Dispose(true) and then suppress finalization of this enumerator. - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } + object System.Collections.IEnumerator.Current => Current!; + bool System.Collections.IEnumerator.MoveNext() + { + return MoveNext(); + } - /// - /// Remove the internal data (notably the stack array). - /// - /// True if called from Dispose(), - /// false if called from the finalizer - protected virtual void Dispose(bool disposing) - { - if (!disposed) - { - if (disposing) - { - } + void System.Collections.IEnumerator.Reset() + { + throw new NotImplementedException(); + } - current = default; - cursor = null; - path = null; - disposed = true; - } - } + #endregion + } + /// + /// An enumerator for a snapshot of a node copy persistent red-black tree + /// collection. + /// + internal class SnapEnumerator : SCG.IEnumerator + { + #region Private Fields + private TreeSet? tree; + private bool valid = false; + private readonly int stamp; + private T current; + private Node? cursor; + private Node[]? path; // stack of nodes + + private int level; + #endregion - /// - /// Finalizer for enumerator - /// - ~Enumerator() + /// + /// Create an enumerator for a snapshot of a node copy persistent red-black tree + /// collection + /// + /// The snapshot + public SnapEnumerator(TreeSet tree) + { + this.tree = tree; + stamp = tree.stamp; + path = new Node[2 * tree.blackdepth]; + cursor = new Node { - Dispose(false); - } - #endregion + right = tree.root + }; + } - #region IEnumerator Members + #region SCG.IEnumerator Members - object System.Collections.IEnumerator.Current => Current!; + /// + /// Move enumerator to next item in tree, or the first item if + /// this is the first call to MoveNext. + /// if underlying tree was modified. + /// + /// True if enumerator is valid now + public bool MoveNext() + { + tree!.ModifyCheck(stamp);//??? - bool System.Collections.IEnumerator.MoveNext() + + Node? next = tree.Right(cursor!); + + if (next != null) { - return MoveNext(); + path![level] = cursor = next; + next = tree.Left(cursor); + while (next != null) + { + path[++level] = cursor = next; + next = tree.Left(cursor); + } } - - void System.Collections.IEnumerator.Reset() + else if (level == 0) { - throw new NotImplementedException(); + return valid = false; + } + else + { + cursor = path![--level]; } - #endregion + current = cursor.item; + return valid = true; } + /// - /// An enumerator for a snapshot of a node copy persistent red-black tree - /// collection. + /// Undefined if enumerator is not valid (MoveNext hash been called returning true) /// - internal class SnapEnumerator : SCG.IEnumerator + /// The current value of the enumerator. + public T Current { - #region Private Fields - private TreeSet? tree; - private bool valid = false; - private readonly int stamp; - private T current; - private Node? cursor; - private Node[]? path; // stack of nodes - - private int level; - #endregion - - /// - /// Create an enumerator for a snapshot of a node copy persistent red-black tree - /// collection - /// - /// The snapshot - public SnapEnumerator(TreeSet tree) + get { - this.tree = tree; - stamp = tree.stamp; - path = new Node[2 * tree.blackdepth]; - cursor = new Node + if (valid) { - right = tree.root - }; + return current; + } + else + { + throw new InvalidOperationException(); + } } + } + #endregion - #region SCG.IEnumerator Members + #region IDisposable Members - /// - /// Move enumerator to next item in tree, or the first item if - /// this is the first call to MoveNext. - /// if underlying tree was modified. - /// - /// True if enumerator is valid now - public bool MoveNext() - { - tree!.ModifyCheck(stamp);//??? - - - Node? next = tree.Right(cursor!); - - if (next != null) - { - path![level] = cursor = next; - next = tree.Left(cursor); - while (next != null) - { - path[++level] = cursor = next; - next = tree.Left(cursor); - } - } - else if (level == 0) - { - return valid = false; - } - else - { - cursor = path![--level]; - } + void System.IDisposable.Dispose() + { + tree = null; + valid = false; + current = default; + cursor = null; + path = null; + } - current = cursor.item; - return valid = true; - } + #endregion + #region IEnumerator Members - /// - /// Undefined if enumerator is not valid (MoveNext hash been called returning true) - /// - /// The current value of the enumerator. - public T Current - { - get - { - if (valid) - { - return current; - } - else - { - throw new InvalidOperationException(); - } - } - } + object System.Collections.IEnumerator.Current => Current!; - #endregion + bool System.Collections.IEnumerator.MoveNext() + { + return MoveNext(); + } - #region IDisposable Members + void System.Collections.IEnumerator.Reset() + { + throw new NotImplementedException(); + } - void System.IDisposable.Dispose() - { - tree = null; - valid = false; - current = default; - cursor = null; - path = null; - } + #endregion + } - #endregion + #endregion - #region IEnumerator Members + #region IEnumerable Members - object System.Collections.IEnumerator.Current => Current!; + private SCG.IEnumerator GetEnumerator(Node? node, int origstamp) + { + if (node == null) + { + yield break; + } - bool System.Collections.IEnumerator.MoveNext() - { - return MoveNext(); - } + if (node.left != null) + { + SCG.IEnumerator child = GetEnumerator(node.left, origstamp); - void System.Collections.IEnumerator.Reset() + while (child.MoveNext()) { - throw new NotImplementedException(); + ModifyCheck(origstamp); + yield return child.Current; } - - #endregion } - #endregion - - #region IEnumerable Members - - private SCG.IEnumerator GetEnumerator(Node? node, int origstamp) + ModifyCheck(origstamp); + yield return node.item; + if (node.right != null) { - if (node == null) - { - yield break; - } - - if (node.left != null) - { - SCG.IEnumerator child = GetEnumerator(node.left, origstamp); - - while (child.MoveNext()) - { - ModifyCheck(origstamp); - yield return child.Current; - } - } + SCG.IEnumerator child = GetEnumerator(node.right, origstamp); - ModifyCheck(origstamp); - yield return node.item; - if (node.right != null) + while (child.MoveNext()) { - SCG.IEnumerator child = GetEnumerator(node.right, origstamp); - - while (child.MoveNext()) - { - ModifyCheck(origstamp); - yield return child.Current; - } + ModifyCheck(origstamp); + yield return child.Current; } } + } - /// - /// - /// - /// If tree is empty - /// - public override T Choose() + /// + /// + /// + /// If tree is empty + /// + public override T Choose() + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - - if (size == 0) - { - throw new NoSuchItemException(); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - return root!.item; + if (size == 0) + { + throw new NoSuchItemException(); } + return root!.item; + } + - /// - /// Create an enumerator for this tree - /// - /// The enumerator - public override SCG.IEnumerator GetEnumerator() + /// + /// Create an enumerator for this tree + /// + /// The enumerator + public override SCG.IEnumerator GetEnumerator() + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - if (isSnapShot) - { - return new SnapEnumerator(this); - } + if (isSnapShot) + { + return new SnapEnumerator(this); + } - return new Enumerator(this); + return new Enumerator(this); - } + } - #endregion + #endregion - #region ISink Members + #region ISink Members - /// - /// Add item to tree. If already there, return the found item in the second argument. - /// - /// Item to add - /// item found - /// whether item in node should be updated - /// true if found in bag, false if not found or tree is a set - /// True if item was added - private bool AddIterative(T item, ref T founditem, bool update, out bool wasfound) - { - wasfound = false; - if (root == null) + /// + /// Add item to tree. If already there, return the found item in the second argument. + /// + /// Item to add + /// item found + /// whether item in node should be updated + /// true if found in bag, false if not found or tree is a set + /// True if item was added + private bool AddIterative(T item, ref T founditem, bool update, out bool wasfound) + { + wasfound = false; + if (root == null) + { + root = new Node { - root = new Node - { - red = false - }; - blackdepth = 1; - root.item = item; - root.generation = generation; - return true; - } + red = false + }; + blackdepth = 1; + root.item = item; + root.generation = generation; + return true; + } - StackCheck(); + StackCheck(); - int level = 0; - Node cursor = root; + int level = 0; + Node cursor = root; - while (true) + while (true) + { + int comp = comparer!.Compare(cursor.item, item); + + if (comp == 0) { - int comp = comparer!.Compare(cursor.item, item); + founditem = cursor.item; - if (comp == 0) + bool nodeWasUpdated = update; + if (update) { - founditem = cursor.item; + Node.CopyNode(ref cursor, MaxSnapId, generation); + cursor.item = item; + } + - bool nodeWasUpdated = update; - if (update) + while (level-- > 0) + { + if (nodeWasUpdated) { - Node.CopyNode(ref cursor, MaxSnapId, generation); - cursor.item = item; + Node kid = cursor; + + cursor = path![level]!; + Node.Update(ref cursor!, dirs![level] > 0, kid, MaxSnapId, generation); + } + path![level] = null; + } - while (level-- > 0) - { - if (nodeWasUpdated) - { - Node kid = cursor; + if (update) + { + root = cursor; + } - cursor = path![level]!; - Node.Update(ref cursor!, dirs![level] > 0, kid, MaxSnapId, generation); + return false; - } + } - path![level] = null; - } + //else + Node? child = comp > 0 ? cursor.left : cursor.right; - if (update) - { - root = cursor; - } + if (child == null) + { + child = new Node + { + item = item, + generation = generation + }; + Node.Update(ref cursor, comp > 0, child, MaxSnapId, generation); - return false; + cursor.size++; - } + dirs![level] = comp; + break; + } + else + { + dirs![level] = comp; + path![level++] = cursor; + cursor = child; + } + } - //else - Node? child = comp > 0 ? cursor.left : cursor.right; + //We have just added the red node child to "cursor" + while (cursor.red) + { + //take one step up: + Node child = cursor; - if (child == null) - { - child = new Node - { - item = item, - generation = generation - }; - Node.Update(ref cursor, comp > 0, child, MaxSnapId, generation); + cursor = path![--level]!; + path[level] = null; + Node.Update(ref cursor!, dirs[level] > 0, child, MaxSnapId, generation); + cursor.size++; + int comp = dirs[level]; + Node? childsibling = comp > 0 ? cursor.right : cursor.left; - cursor.size++; + if (childsibling != null && childsibling.red) + { + //Promote + child.red = false; + Node.Update(ref cursor, comp < 0, childsibling, MaxSnapId, generation); + childsibling.red = false; - dirs![level] = comp; - break; + //color cursor red & take one step up the tree unless at root + if (level == 0) + { + root = cursor; + blackdepth++; + return true; } else { - dirs![level] = comp; - path![level++] = cursor; - cursor = child; + cursor.red = true; + child = cursor; + cursor = path[--level]!; + Node.Update(ref cursor!, dirs[level] > 0, child, MaxSnapId, generation); + path[level] = null; + cursor.size++; } } - - //We have just added the red node child to "cursor" - while (cursor.red) + else { - //take one step up: - Node child = cursor; + //ROTATE!!! + int childcomp = dirs[level + 1]; - cursor = path![--level]!; - path[level] = null; - Node.Update(ref cursor!, dirs[level] > 0, child, MaxSnapId, generation); - cursor.size++; - int comp = dirs[level]; - Node? childsibling = comp > 0 ? cursor.right : cursor.left; - - if (childsibling != null && childsibling.red) + cursor.red = true; + if (comp > 0) { - //Promote - child.red = false; - Node.Update(ref cursor, comp < 0, childsibling, MaxSnapId, generation); - childsibling.red = false; + if (childcomp > 0) + {//zagzag + Node.Update(ref cursor, true, child.right!, MaxSnapId, generation); + Node.Update(ref child, false, cursor, MaxSnapId, generation); - //color cursor red & take one step up the tree unless at root - if (level == 0) - { - root = cursor; - blackdepth++; - return true; + cursor = child; } else - { - cursor.red = true; - child = cursor; - cursor = path[--level]!; - Node.Update(ref cursor!, dirs[level] > 0, child, MaxSnapId, generation); - path[level] = null; - cursor.size++; + {//zagzig + Node badgrandchild = child.right!; + Node.Update(ref cursor, true, badgrandchild!.right!, MaxSnapId, generation); + Node.Update(ref child, false, badgrandchild.left!, MaxSnapId, generation); + Node.CopyNode(ref badgrandchild, MaxSnapId, generation); + + badgrandchild.left = child; + badgrandchild.right = cursor; + cursor = badgrandchild; } } else - { - //ROTATE!!! - int childcomp = dirs[level + 1]; - - cursor.red = true; - if (comp > 0) - { - if (childcomp > 0) - {//zagzag - Node.Update(ref cursor, true, child.right!, MaxSnapId, generation); - Node.Update(ref child, false, cursor, MaxSnapId, generation); + {//comp < 0 + if (childcomp < 0) + {//zigzig + Node.Update(ref cursor, false, child.left!, MaxSnapId, generation); + Node.Update(ref child, true, cursor, MaxSnapId, generation); - cursor = child; - } - else - {//zagzig - Node badgrandchild = child.right!; - Node.Update(ref cursor, true, badgrandchild!.right!, MaxSnapId, generation); - Node.Update(ref child, false, badgrandchild.left!, MaxSnapId, generation); - Node.CopyNode(ref badgrandchild, MaxSnapId, generation); - - badgrandchild.left = child; - badgrandchild.right = cursor; - cursor = badgrandchild; - } + cursor = child; } else - {//comp < 0 - if (childcomp < 0) - {//zigzig - Node.Update(ref cursor, false, child.left!, MaxSnapId, generation); - Node.Update(ref child, true, cursor, MaxSnapId, generation); - - cursor = child; - } - else - {//zigzag - Node badgrandchild = child.left!; - Node.Update(ref cursor, false, badgrandchild.left!, MaxSnapId, generation); - Node.Update(ref child, true, badgrandchild.right!, MaxSnapId, generation); - Node.CopyNode(ref badgrandchild, MaxSnapId, generation); - - badgrandchild.right = child; - badgrandchild.left = cursor; - cursor = badgrandchild; - } + {//zigzag + Node badgrandchild = child.left!; + Node.Update(ref cursor, false, badgrandchild.left!, MaxSnapId, generation); + Node.Update(ref child, true, badgrandchild.right!, MaxSnapId, generation); + Node.CopyNode(ref badgrandchild, MaxSnapId, generation); + + badgrandchild.right = child; + badgrandchild.left = cursor; + cursor = badgrandchild; } + } - cursor.red = false; - - Node n; + cursor.red = false; + Node n; - n = cursor.right!; - cursor.size = n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1; - n = cursor.left!; - n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1; - cursor.size += n.size + 1; - if (level == 0) - { - root = cursor; - return true; - } - else - { - child = cursor; - cursor = path![--level]!; - path[level] = null; - Node.Update(ref cursor!, dirs[level] > 0, child, MaxSnapId, generation); + n = cursor.right!; + cursor.size = n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1; + n = cursor.left!; + n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1; + cursor.size += n.size + 1; - cursor.size++; - break; - } + if (level == 0) + { + root = cursor; + return true; } - } - bool stillmore = true; - while (level > 0) - { - Node child = cursor; - - cursor = path![--level]!; - path[level] = null; - if (stillmore) + else { - stillmore = Node.Update(ref cursor!, dirs[level] > 0, child, MaxSnapId, generation); + child = cursor; + cursor = path![--level]!; + path[level] = null; + Node.Update(ref cursor!, dirs[level] > 0, child, MaxSnapId, generation); + + cursor.size++; + break; } + } + } + bool stillmore = true; + while (level > 0) + { + Node child = cursor; - cursor.size++; + cursor = path![--level]!; + path[level] = null; + if (stillmore) + { + stillmore = Node.Update(ref cursor!, dirs[level] > 0, child, MaxSnapId, generation); } - root = cursor; - return true; + cursor.size++; } + root = cursor; + return true; + } + - /// - /// Add an item to this collection if possible. If this collection has set - /// semantics, the item will be added if not already in the collection. If - /// bag semantics, the item will always be added. - /// - /// The item to add. - /// True if item was added. - public bool Add(T item) + /// + /// Add an item to this collection if possible. If this collection has set + /// semantics, the item will be added if not already in the collection. If + /// bag semantics, the item will always be added. + /// + /// The item to add. + /// True if item was added. + public bool Add(T item) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - UpdateCheck(); + UpdateCheck(); - //Note: blackdepth of the tree is set inside addIterative - T jtem = default; - if (!Add(item, ref jtem)) - { - return false; - } - - if (ActiveEvents != 0) - { - RaiseForAdd(jtem); - } - - return true; + //Note: blackdepth of the tree is set inside addIterative + T jtem = default; + if (!Add(item, ref jtem)) + { + return false; } - /// - /// Add an item to this collection if possible. If this collection has set - /// semantics, the item will be added if not already in the collection. If - /// bag semantics, the item will always be added. - /// - /// The item to add. - void SCG.ICollection.Add(T item) + if (ActiveEvents != 0) { - Add(item); + RaiseForAdd(jtem); } - private bool Add(T item, ref T j) - { + return true; + } - if (AddIterative(item, ref j, false, out bool wasFound)) - { - size++; - if (!wasFound) - { - j = item; - } + /// + /// Add an item to this collection if possible. If this collection has set + /// semantics, the item will be added if not already in the collection. If + /// bag semantics, the item will always be added. + /// + /// The item to add. + void SCG.ICollection.Add(T item) + { + Add(item); + } - return true; - } - else + private bool Add(T item, ref T j) + { + + if (AddIterative(item, ref j, false, out bool wasFound)) + { + size++; + if (!wasFound) { - return false; + j = item; } + + return true; + } + else + { + return false; } + } - /// - /// Add the elements from another collection with a more specialized item type - /// to this collection. If this - /// collection has set semantics, only items not already in the collection - /// will be added. - /// - /// The items to add - public void AddAll(SCG.IEnumerable items) + /// + /// Add the elements from another collection with a more specialized item type + /// to this collection. If this + /// collection has set semantics, only items not already in the collection + /// will be added. + /// + /// The items to add + public void AddAll(SCG.IEnumerable items) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - UpdateCheck(); + UpdateCheck(); - int c = 0; - T j = default; + int c = 0; + T j = default; - bool raiseAdded = (ActiveEvents & EventType.Added) != 0; - CircularQueue? wasAdded = raiseAdded ? new CircularQueue() : null; + bool raiseAdded = (ActiveEvents & EventType.Added) != 0; + CircularQueue? wasAdded = raiseAdded ? new CircularQueue() : null; - foreach (T i in items) + foreach (T i in items) + { + if (AddIterative(i, ref j, false, out bool tmp)) { - if (AddIterative(i, ref j, false, out bool tmp)) + c++; + if (raiseAdded) { - c++; - if (raiseAdded) - { - wasAdded!.Enqueue(tmp ? j : i); - } + wasAdded!.Enqueue(tmp ? j : i); } } + } - if (c == 0) - { - return; - } + if (c == 0) + { + return; + } - size += c; - //TODO: implement a RaiseForAddAll() method - if (raiseAdded) + size += c; + //TODO: implement a RaiseForAddAll() method + if (raiseAdded) + { + foreach (T item in wasAdded!) { - foreach (T item in wasAdded!) - { - RaiseItemsAdded(item, 1); - } + RaiseItemsAdded(item, 1); } + } - if (((ActiveEvents & EventType.Changed) != 0)) - { - RaiseCollectionChanged(); - } + if (((ActiveEvents & EventType.Changed) != 0)) + { + RaiseCollectionChanged(); } + } - /// - /// Add all the items from another collection with an enumeration order that - /// is increasing in the items. The idea is that the implementation may use - /// a faster algorithm to merge the two collections. - /// if the enumerated items turns out - /// not to be in increasing order. - /// - /// The collection to add. - public void AddSorted(SCG.IEnumerable items) + /// + /// Add all the items from another collection with an enumeration order that + /// is increasing in the items. The idea is that the implementation may use + /// a faster algorithm to merge the two collections. + /// if the enumerated items turns out + /// not to be in increasing order. + /// + /// The collection to add. + public void AddSorted(SCG.IEnumerable items) + { + if (size > 0) + { + AddAll(items); + } + else { - if (size > 0) + if (!isValid) { - AddAll(items); + throw new ViewDisposedException("Snapshot has been disposed"); } - else - { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - UpdateCheck(); - AddSorted(items, true, true); - } + UpdateCheck(); + AddSorted(items, true, true); } + } - #region add-sorted helpers + #region add-sorted helpers - //Create a RB tree from x+2^h-1 (x < 2^h, h>=1) nodes taken from a - //singly linked list of red nodes using only the right child refs. - //The x nodes at depth h+1 will be red, the rest black. - //(h is the blackdepth of the resulting tree) - private static Node MakeTreer(ref Node rest, int blackheight, int maxred, int red) + //Create a RB tree from x+2^h-1 (x < 2^h, h>=1) nodes taken from a + //singly linked list of red nodes using only the right child refs. + //The x nodes at depth h+1 will be red, the rest black. + //(h is the blackdepth of the resulting tree) + private static Node MakeTreer(ref Node rest, int blackheight, int maxred, int red) + { + if (blackheight == 1) { - if (blackheight == 1) - { - Node top = rest; + Node top = rest; + rest = rest.right!; + if (red > 0) + { + top.right = null; + rest.left = top; + top = rest; + top.size = 1 + red; rest = rest.right!; - if (red > 0) - { - top.right = null; - rest.left = top; - top = rest; - top.size = 1 + red; - rest = rest.right!; - red--; - } - - if (red > 0) - { + red--; + } - top.right = rest; - rest = rest.right!; - top.right!.right = null; - } - else - { - top.right = null; - } + if (red > 0) + { - top.red = false; - return top; + top.right = rest; + rest = rest.right!; + top.right!.right = null; } else { - maxred >>= 1; + top.right = null; + } - int lred = red > maxred ? maxred : red; - Node left = MakeTreer(ref rest, blackheight - 1, maxred, lred); - Node top = rest; + top.red = false; + return top; + } + else + { + maxred >>= 1; + + int lred = red > maxred ? maxred : red; + Node left = MakeTreer(ref rest, blackheight - 1, maxred, lred); + Node top = rest; + + rest = rest.right!; + top.left = left; + top.red = false; + top.right = MakeTreer(ref rest!, blackheight - 1, maxred, red - lred); + top.size = (maxred << 1) - 1 + red; + return top; + } + } - rest = rest.right!; - top.left = left; - top.red = false; - top.right = MakeTreer(ref rest!, blackheight - 1, maxred, red - lred); - top.size = (maxred << 1) - 1 + red; - return top; - } + private void AddSorted(SCG.IEnumerable items, bool safe, bool raise) + { + SCG.IEnumerator e = items.GetEnumerator(); + if (size > 0) + { + throw new InternalException("This can't happen"); } - private void AddSorted(SCG.IEnumerable items, bool safe, bool raise) + if (!e.MoveNext()) { - SCG.IEnumerator e = items.GetEnumerator(); - if (size > 0) - { - throw new InternalException("This can't happen"); - } + return; + } - if (!e.MoveNext()) - { - return; - } + //To count theCollect + Node head = new(), tail = head; + int z = 1; + T lastitem = tail.item = e.Current; - //To count theCollect - Node head = new Node(), tail = head; - int z = 1; - T lastitem = tail.item = e.Current; + while (e.MoveNext()) + { - while (e.MoveNext()) + z++; + tail.right = new Node(); + tail = tail.right; + tail.item = e.Current; + if (safe) { - - z++; - tail.right = new Node(); - tail = tail.right; - tail.item = e.Current; - if (safe) + if (comparer!.Compare(lastitem, tail.item) >= 0) { - if (comparer!.Compare(lastitem, tail.item) >= 0) - { - throw new ArgumentException("Argument not sorted"); - } - - lastitem = tail.item; + throw new ArgumentException("Argument not sorted"); } - tail.generation = generation; + lastitem = tail.item; } + tail.generation = generation; - int blackheight = 0, red = z, maxred = 1; + } - while (maxred <= red) - { - red -= maxred; - maxred <<= 1; - blackheight++; - } + int blackheight = 0, red = z, maxred = 1; - root = TreeSet.MakeTreer(ref head, blackheight, maxred, red); - blackdepth = blackheight; - size = z; + while (maxred <= red) + { + red -= maxred; + maxred <<= 1; + blackheight++; + } + root = TreeSet.MakeTreer(ref head, blackheight, maxred, red); + blackdepth = blackheight; + size = z; - if (raise) + + if (raise) + { + if ((ActiveEvents & EventType.Added) != 0) { - if ((ActiveEvents & EventType.Added) != 0) + CircularQueue wasAdded = new(); + foreach (T item in this) { - CircularQueue wasAdded = new CircularQueue(); - foreach (T item in this) - { - wasAdded.Enqueue(item); - } - - foreach (T item in wasAdded) - { - RaiseItemsAdded(item, 1); - } + wasAdded.Enqueue(item); } - if ((ActiveEvents & EventType.Changed) != 0) + + foreach (T item in wasAdded) { - RaiseCollectionChanged(); + RaiseItemsAdded(item, 1); } } - return; + if ((ActiveEvents & EventType.Changed) != 0) + { + RaiseCollectionChanged(); + } } + return; + } - #endregion + #endregion - /// - /// False since this tree has set semantics. - public bool AllowsDuplicates => false; + /// + /// False since this tree has set semantics. + public bool AllowsDuplicates => false; - /// - /// By convention this is true for any collection with set semantics. - /// - /// True if only one representative of a group of equal items - /// is kept in the collection together with the total count. - public virtual bool DuplicatesByCounting => true; + /// + /// By convention this is true for any collection with set semantics. + /// + /// True if only one representative of a group of equal items + /// is kept in the collection together with the total count. + public virtual bool DuplicatesByCounting => true; - #endregion + #endregion - #region IEditableCollection Members + #region IEditableCollection Members - /// - /// The value is symbolic indicating the type of asymptotic complexity - /// in terms of the size of this collection (worst-case or amortized as - /// relevant). - /// - /// Speed.Log - public Speed ContainsSpeed => Speed.Log; + /// + /// The value is symbolic indicating the type of asymptotic complexity + /// in terms of the size of this collection (worst-case or amortized as + /// relevant). + /// + /// Speed.Log + public Speed ContainsSpeed => Speed.Log; - /// - /// Check if this collection contains (an item equivalent to according to the - /// itemequalityComparer) a particular value. - /// - /// The value to check for. - /// True if the items is in this collection. - public bool Contains(T item) + /// + /// Check if this collection contains (an item equivalent to according to the + /// itemequalityComparer) a particular value. + /// + /// The value to check for. + /// True if the items is in this collection. + public bool Contains(T item) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - Node? next = root; - while (next != null) + Node? next = root; + while (next != null) + { + int comp = comparer!.Compare(next.item, item); + if (comp == 0) { - int comp = comparer!.Compare(next.item, item); - if (comp == 0) - { - return true; - } - - next = comp < 0 ? Right(next) : Left(next); + return true; } - return false; + next = comp < 0 ? Right(next) : Left(next); } + return false; + } - //Variant for dictionary use - //Will return the actual matching item in the ref argument. - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, return in the ref argument (a - /// binary copy of) the actual value found. - /// - /// The value to look for. - /// True if the items is in this collection. - public bool Find(ref T item) + + //Variant for dictionary use + //Will return the actual matching item in the ref argument. + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, return in the ref argument (a + /// binary copy of) the actual value found. + /// + /// The value to look for. + /// True if the items is in this collection. + public bool Find(ref T item) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - Node? next = root; - while (next != null) + Node? next = root; + while (next != null) + { + int comp = comparer!.Compare(next.item, item); + if (comp == 0) { - int comp = comparer!.Compare(next.item, item); - if (comp == 0) - { - item = next.item; - return true; - } - - next = comp < 0 ? Right(next) : Left(next); + item = next.item; + return true; } - return false; + next = comp < 0 ? Right(next) : Left(next); } + return false; + } - /// - /// Find or add the item to the tree. If the tree does not contain - /// an item equivalent to this item add it, else return the existing - /// one in the ref argument. - /// - /// - /// - /// True if item was found - public bool FindOrAdd(ref T item) - { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - UpdateCheck(); + /// + /// Find or add the item to the tree. If the tree does not contain + /// an item equivalent to this item add it, else return the existing + /// one in the ref argument. + /// + /// + /// + /// True if item was found + public bool FindOrAdd(ref T item) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); + } - //Note: blackdepth of the tree is set inside addIterative - if (AddIterative(item, ref item, false, out bool wasfound)) - { - size++; - if (ActiveEvents != 0 && !wasfound) - { - RaiseForAdd(item); - } + UpdateCheck(); - return wasfound; - } - else + //Note: blackdepth of the tree is set inside addIterative + if (AddIterative(item, ref item, false, out bool wasfound)) + { + size++; + if (ActiveEvents != 0 && !wasfound) { - return true; + RaiseForAdd(item); } + + return wasfound; } + else + { + return true; + } + } - //For dictionary use. - //If found, the matching entry will be updated with the new item. - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// to with a binary copy of the supplied value. If the collection has bag semantics, - /// this updates all equivalent copies in - /// the collection. - /// - /// Value to update. - /// True if the item was found and hence updated. - public bool Update(T item) + //For dictionary use. + //If found, the matching entry will be updated with the new item. + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// to with a binary copy of the supplied value. If the collection has bag semantics, + /// this updates all equivalent copies in + /// the collection. + /// + /// Value to update. + /// True if the item was found and hence updated. + public bool Update(T item) + { + return Update(item, out _); + } + + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// with a binary copy of the supplied value. If the collection has bag semantics, + /// this updates all equivalent copies in + /// the collection. + /// + /// + /// + /// + public bool Update(T item, out T olditem) + { + if (!isValid) { - return Update(item, out _); + throw new ViewDisposedException("Snapshot has been disposed"); } - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// with a binary copy of the supplied value. If the collection has bag semantics, - /// this updates all equivalent copies in - /// the collection. - /// - /// - /// - /// - public bool Update(T item, out T olditem) + UpdateCheck(); + StackCheck(); + + int level = 0; + Node? cursor = root; + while (cursor != null) { - if (!isValid) + int comp = comparer!.Compare(cursor.item, item); + if (comp == 0) { - throw new ViewDisposedException("Snapshot has been disposed"); - } + Node.CopyNode(ref cursor!, MaxSnapId, generation); + olditem = cursor.item; - UpdateCheck(); - StackCheck(); - - int level = 0; - Node? cursor = root; - while (cursor != null) - { - int comp = comparer!.Compare(cursor.item, item); - if (comp == 0) + cursor.item = item; + while (level > 0) { - Node.CopyNode(ref cursor!, MaxSnapId, generation); - olditem = cursor.item; - - cursor.item = item; - while (level > 0) - { - Node child = cursor; - - cursor = path![--level]; - path[level] = null; - Node.Update(ref cursor!, dirs![level] > 0, child, MaxSnapId, generation); + Node child = cursor; - } + cursor = path![--level]; + path[level] = null; + Node.Update(ref cursor!, dirs![level] > 0, child, MaxSnapId, generation); - root = cursor; + } - if (ActiveEvents != 0) - { - RaiseForUpdate(item, olditem); - } + root = cursor; - return true; + if (ActiveEvents != 0) + { + RaiseForUpdate(item, olditem); } - dirs![level] = comp; - path![level++] = cursor; - cursor = comp < 0 ? cursor.right : cursor.left; - } - olditem = default; - return false; + return true; + } + dirs![level] = comp; + path![level++] = cursor; + cursor = comp < 0 ? cursor.right : cursor.left; } + olditem = default; + return false; + } - /// - /// Check if this collection contains an item equivalent according to the - /// itemequalityComparer to a particular value. If so, update the item in the collection - /// with a binary copy of the supplied value; else add the value to the collection. - /// - /// NOTE: the bag implementation is currently wrong! ????? - /// - /// Value to add or update. - /// True if the item was found and updated (hence not added). - public bool UpdateOrAdd(T item) + + /// + /// Check if this collection contains an item equivalent according to the + /// itemequalityComparer to a particular value. If so, update the item in the collection + /// with a binary copy of the supplied value; else add the value to the collection. + /// + /// NOTE: the bag implementation is currently wrong! ????? + /// + /// Value to add or update. + /// True if the item was found and updated (hence not added). + public bool UpdateOrAdd(T item) + { + return UpdateOrAdd(item, out _); + } + + /// + /// + /// + /// + /// + /// + public bool UpdateOrAdd(T item, out T olditem) + { + if (!isValid) { - return UpdateOrAdd(item, out _); + throw new ViewDisposedException("Snapshot has been disposed"); } - /// - /// - /// - /// - /// - /// - public bool UpdateOrAdd(T item, out T olditem) + UpdateCheck(); + olditem = default; + + + //Note: blackdepth of the tree is set inside addIterative + if (AddIterative(item, ref olditem, true, out bool wasfound)) { - if (!isValid) + size++; + if (ActiveEvents != 0) { - throw new ViewDisposedException("Snapshot has been disposed"); + RaiseForAdd(wasfound ? olditem : item); } - UpdateCheck(); - olditem = default; - - - //Note: blackdepth of the tree is set inside addIterative - if (AddIterative(item, ref olditem, true, out bool wasfound)) + return wasfound; + } + else + { + if (ActiveEvents != 0) { - size++; - if (ActiveEvents != 0) - { - RaiseForAdd(wasfound ? olditem : item); - } - - return wasfound; + RaiseForUpdate(item, olditem, 1); } - else - { - if (ActiveEvents != 0) - { - RaiseForUpdate(item, olditem, 1); - } - return true; - } + return true; } + } - /// - /// Remove a particular item from this collection. If the collection has bag - /// semantics only one copy equivalent to the supplied item is removed. - /// - /// The value to remove. - /// True if the item was found (and removed). - public bool Remove(T item) + /// + /// Remove a particular item from this collection. If the collection has bag + /// semantics only one copy equivalent to the supplied item is removed. + /// + /// The value to remove. + /// True if the item was found (and removed). + public bool Remove(T item) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - UpdateCheck(); - if (root == null) - { - return false; - } + UpdateCheck(); + if (root == null) + { + return false; + } - bool retval = RemoveIterative(ref item, out _); - if (ActiveEvents != 0 && retval) - { - RaiseForRemove(item); - } + bool retval = RemoveIterative(ref item, out _); + if (ActiveEvents != 0 && retval) + { + RaiseForRemove(item); + } - return retval; + return retval; + } + + /// + /// Remove a particular item from this collection if found. If the collection + /// has bag semantics only one copy equivalent to the supplied item is removed, + /// which one is implementation dependent. + /// If an item was removed, report a binary copy of the actual item removed in + /// the argument. + /// + /// The value to remove. + /// The removed value. + /// True if the item was found (and removed). + public bool Remove(T item, out T removeditem) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } - /// - /// Remove a particular item from this collection if found. If the collection - /// has bag semantics only one copy equivalent to the supplied item is removed, - /// which one is implementation dependent. - /// If an item was removed, report a binary copy of the actual item removed in - /// the argument. - /// - /// The value to remove. - /// The removed value. - /// True if the item was found (and removed). - public bool Remove(T item, out T removeditem) + UpdateCheck(); + removeditem = item; + if (root == null) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + return false; + } - UpdateCheck(); - removeditem = item; - if (root == null) + bool retval = RemoveIterative(ref removeditem, out _); + if (ActiveEvents != 0 && retval) + { + RaiseForRemove(item); + } + + return retval; + } + + /// + /// + /// + /// input: item to remove; output: item actually removed + /// + /// + private bool RemoveIterative(ref T item, out int wasRemoved) + { + wasRemoved = 0; + //Stage 1: find item + StackCheck(); + + int level = 0, comp; + Node? cursor = root; + + while (true) + { + comp = comparer!.Compare(cursor!.item, item); + if (comp == 0) { - return false; + item = cursor.item; + + wasRemoved = 1; + + break; } - bool retval = RemoveIterative(ref removeditem, out _); - if (ActiveEvents != 0 && retval) + Node child = (comp > 0 ? cursor.left : cursor.right)!; + + if (child == null) { - RaiseForRemove(item); + return false; } - return retval; + dirs![level] = comp; + path![level++] = cursor; + cursor = child; } - /// - /// - /// - /// input: item to remove; output: item actually removed - /// - /// - private bool RemoveIterative(ref T item, out int wasRemoved) + return RemoveIterativePhase2(cursor, level); + } + + private bool RemoveIterativePhase2(Node cursor, int level) + { + if (size == 1) { - wasRemoved = 0; - //Stage 1: find item - StackCheck(); + ClearInner(); + return true; + } - int level = 0, comp; - Node? cursor = root; + //We are certain to remove one node: + size--; - while (true) + //Stage 2: if item's node has no null child, find predecessor + int level_of_item = level; + + if (cursor.left != null && cursor.right != null) + { + dirs![level] = 1; + path![level++] = cursor; + cursor = cursor.left; + while (cursor.right != null) { - comp = comparer!.Compare(cursor!.item, item); - if (comp == 0) - { - item = cursor.item; + dirs[level] = -1; + path[level++] = cursor; + cursor = cursor.right; + } + Node.CopyNode(ref path[level_of_item]!, MaxSnapId, generation); + path[level_of_item]!.item = cursor.item; - wasRemoved = 1; + } - break; - } + //Stage 3: splice out node to be removed + Node? newchild = cursor.right ?? cursor.left; + bool demote_or_rotate = newchild == null && !cursor.red; - Node child = (comp > 0 ? cursor.left : cursor.right)!; + //assert newchild.red + if (newchild != null) + { + newchild.red = false; + } - if (child == null) - { - return false; - } + if (level == 0) + { + root = newchild; + return true; + } - dirs![level] = comp; - path![level++] = cursor; - cursor = child; - } + level--; + cursor = path![level]!; + path[level] = null; - return RemoveIterativePhase2(cursor, level); - } + int comp = dirs![level]; + Node? childsibling; + Node.Update(ref cursor!, comp > 0, newchild!, MaxSnapId, generation); + + childsibling = comp > 0 ? cursor.right : cursor.left; + cursor.size--; + + //Stage 4: demote till we must rotate + Node? farnephew = null, nearnephew = null; - private bool RemoveIterativePhase2(Node cursor, int level) + while (demote_or_rotate) { - if (size == 1) + if (childsibling!.red) { - ClearInner(); - return true; + break; //rotate 2+? } - //We are certain to remove one node: - size--; - - //Stage 2: if item's node has no null child, find predecessor - int level_of_item = level; - - if (cursor.left != null && cursor.right != null) + farnephew = comp > 0 ? childsibling.right : childsibling.left; + if (farnephew != null && farnephew.red) { - dirs![level] = 1; - path![level++] = cursor; - cursor = cursor.left; - while (cursor.right != null) - { - dirs[level] = -1; - path[level++] = cursor; - cursor = cursor.right; - } - Node.CopyNode(ref path[level_of_item]!, MaxSnapId, generation); - path[level_of_item]!.item = cursor.item; - + break; //rotate 1b } - //Stage 3: splice out node to be removed - Node? newchild = cursor.right ?? cursor.left; - bool demote_or_rotate = newchild == null && !cursor.red; - - //assert newchild.red - if (newchild != null) + nearnephew = comp > 0 ? childsibling.left : childsibling.right; + if (nearnephew != null && nearnephew.red) { - newchild.red = false; + break; //rotate 1c } + //demote cursor + childsibling.red = true; if (level == 0) { - root = newchild; + cursor.red = false; + blackdepth--; + root = cursor; return true; } - - level--; - cursor = path![level]!; - path[level] = null; - - int comp = dirs![level]; - Node? childsibling; - Node.Update(ref cursor!, comp > 0, newchild!, MaxSnapId, generation); - - childsibling = comp > 0 ? cursor.right : cursor.left; - cursor.size--; - - //Stage 4: demote till we must rotate - Node? farnephew = null, nearnephew = null; - - while (demote_or_rotate) + else if (cursor.red) { - if (childsibling!.red) - { - break; //rotate 2+? - } + cursor.red = false; + demote_or_rotate = false; + break; //No rotation + } + else + { + Node child = cursor; - farnephew = comp > 0 ? childsibling.right : childsibling.left; - if (farnephew != null && farnephew.red) - { - break; //rotate 1b - } + cursor = path![--level]!; + path[level] = null; + comp = dirs[level]; + childsibling = comp > 0 ? cursor.right : cursor.left; + Node.Update(ref cursor, comp > 0, child, MaxSnapId, generation); + cursor.size--; + } + } - nearnephew = comp > 0 ? childsibling.left : childsibling.right; - if (nearnephew != null && nearnephew.red) - { - break; //rotate 1c - } + //Stage 5: rotate + if (demote_or_rotate) + { + //At start: + //parent = cursor (temporary for swapping nodes) + //childsibling is the sibling of the updated child (x) + //cursor is always the top of the subtree + Node parent = cursor; + + if (childsibling!.red) + {//Case 2 and perhaps more. + //The y.rank == px.rank >= x.rank+2 >=2 so both nephews are != null + //(and black). The grandnephews are children of nearnephew + Node neargrandnephew, fargrandnephew; - //demote cursor - childsibling.red = true; - if (level == 0) - { - cursor.red = false; - blackdepth--; - root = cursor; - return true; - } - else if (cursor.red) + if (comp > 0) { - cursor.red = false; - demote_or_rotate = false; - break; //No rotation + nearnephew = childsibling.left; + farnephew = childsibling.right; + neargrandnephew = nearnephew!.left!; + fargrandnephew = nearnephew.right!; } else { - Node child = cursor; - - cursor = path![--level]!; - path[level] = null; - comp = dirs[level]; - childsibling = comp > 0 ? cursor.right : cursor.left; - Node.Update(ref cursor, comp > 0, child, MaxSnapId, generation); - cursor.size--; + nearnephew = childsibling.right; + farnephew = childsibling.left; + neargrandnephew = nearnephew!.right!; + fargrandnephew = nearnephew.left!; } - } - //Stage 5: rotate - if (demote_or_rotate) - { - //At start: - //parent = cursor (temporary for swapping nodes) - //childsibling is the sibling of the updated child (x) - //cursor is always the top of the subtree - Node parent = cursor; - - if (childsibling!.red) - {//Case 2 and perhaps more. - //The y.rank == px.rank >= x.rank+2 >=2 so both nephews are != null - //(and black). The grandnephews are children of nearnephew - Node neargrandnephew, fargrandnephew; + if (fargrandnephew != null && fargrandnephew.red) + {//Case 2+1b + Node.CopyNode(ref nearnephew!, MaxSnapId, generation); + //The end result of this will always be e copy of parent + Node.Update(ref parent, comp < 0, neargrandnephew!, MaxSnapId, generation); + Node.Update(ref childsibling!, comp > 0, nearnephew, MaxSnapId, generation); if (comp > 0) { - nearnephew = childsibling.left; - farnephew = childsibling.right; - neargrandnephew = nearnephew!.left!; - fargrandnephew = nearnephew.right!; + nearnephew.left = parent; + parent.right = neargrandnephew; } else { - nearnephew = childsibling.right; - farnephew = childsibling.left; - neargrandnephew = nearnephew!.right!; - fargrandnephew = nearnephew.left!; - } - - if (fargrandnephew != null && fargrandnephew.red) - {//Case 2+1b - Node.CopyNode(ref nearnephew!, MaxSnapId, generation); - - //The end result of this will always be e copy of parent - Node.Update(ref parent, comp < 0, neargrandnephew!, MaxSnapId, generation); - Node.Update(ref childsibling!, comp > 0, nearnephew, MaxSnapId, generation); - if (comp > 0) - { - nearnephew.left = parent; - parent.right = neargrandnephew; - } - else - { - nearnephew.right = parent; - parent.left = neargrandnephew; - } - - cursor = childsibling; - childsibling.red = false; - nearnephew.red = true; - fargrandnephew.red = false; - cursor.size = parent.size; - nearnephew.size = cursor.size - 1 - farnephew!.size; - parent.size = nearnephew.size - 1 - fargrandnephew.size; + nearnephew.right = parent; + parent.left = neargrandnephew; } - else if (neargrandnephew != null && neargrandnephew.red) - {//Case 2+1c - Node.CopyNode(ref neargrandnephew, MaxSnapId, generation); - if (comp > 0) - { - Node.Update(ref childsibling!, true, neargrandnephew, MaxSnapId, generation); - Node.Update(ref nearnephew!, true, neargrandnephew.right!, MaxSnapId, generation); - Node.Update(ref parent, false, neargrandnephew.left!, MaxSnapId, generation); - neargrandnephew.left = parent; - neargrandnephew.right = nearnephew; - } - else - { - Node.Update(ref childsibling!, false, neargrandnephew, MaxSnapId, generation); - Node.Update(ref nearnephew!, false, neargrandnephew.left!, MaxSnapId, generation); - Node.Update(ref parent, true, neargrandnephew.right!, MaxSnapId, generation); - neargrandnephew.right = parent; - neargrandnephew.left = nearnephew; - } - cursor = childsibling; - childsibling.red = false; - cursor.size = parent.size; - parent.size = 1 + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size); - nearnephew.size = 1 + (nearnephew.left == null ? 0 : nearnephew.left.size) + (nearnephew.right == null ? 0 : nearnephew.right.size); - neargrandnephew.size = 1 + parent.size + nearnephew.size; - } - else - {//Case 2 only - Node.Update(ref parent, comp < 0, nearnephew, MaxSnapId, generation); - Node.Update(ref childsibling!, comp > 0, parent, MaxSnapId, generation); - - cursor = childsibling; - childsibling.red = false; - nearnephew.red = true; - cursor.size = parent.size; - parent.size -= farnephew!.size + 1; - } + cursor = childsibling; + childsibling.red = false; + nearnephew.red = true; + fargrandnephew.red = false; + cursor.size = parent.size; + nearnephew.size = cursor.size - 1 - farnephew!.size; + parent.size = nearnephew.size - 1 - fargrandnephew.size; } - else if (farnephew != null && farnephew.red) - {//Case 1b - nearnephew = comp > 0 ? childsibling.left : childsibling.right; - Node.Update(ref parent, comp < 0, nearnephew!, MaxSnapId, generation); - Node.CopyNode(ref childsibling!, MaxSnapId, generation); + else if (neargrandnephew != null && neargrandnephew.red) + {//Case 2+1c + Node.CopyNode(ref neargrandnephew, MaxSnapId, generation); if (comp > 0) { - childsibling.left = parent; - childsibling.right = farnephew; + Node.Update(ref childsibling!, true, neargrandnephew, MaxSnapId, generation); + Node.Update(ref nearnephew!, true, neargrandnephew.right!, MaxSnapId, generation); + Node.Update(ref parent, false, neargrandnephew.left!, MaxSnapId, generation); + neargrandnephew.left = parent; + neargrandnephew.right = nearnephew; } else { - childsibling.right = parent; - childsibling.left = farnephew; + Node.Update(ref childsibling!, false, neargrandnephew, MaxSnapId, generation); + Node.Update(ref nearnephew!, false, neargrandnephew.left!, MaxSnapId, generation); + Node.Update(ref parent, true, neargrandnephew.right!, MaxSnapId, generation); + neargrandnephew.right = parent; + neargrandnephew.left = nearnephew; } cursor = childsibling; - cursor.red = parent.red; - parent.red = false; - farnephew.red = false; - + childsibling.red = false; cursor.size = parent.size; - parent.size -= farnephew.size + 1; + parent.size = 1 + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size); + nearnephew.size = 1 + (nearnephew.left == null ? 0 : nearnephew.left.size) + (nearnephew.right == null ? 0 : nearnephew.right.size); + neargrandnephew.size = 1 + parent.size + nearnephew.size; } - else if (nearnephew != null && nearnephew.red) - {//Case 1c - Node.CopyNode(ref nearnephew!, MaxSnapId, generation); - if (comp > 0) - { - Node.Update(ref childsibling!, true, nearnephew.right!, MaxSnapId, generation); - Node.Update(ref parent, false, nearnephew.left!, MaxSnapId, generation); - - nearnephew.left = parent; - nearnephew.right = childsibling; - } - else - { - Node.Update(ref childsibling!, false, nearnephew.left!, MaxSnapId, generation); - Node.Update(ref parent, true, nearnephew.right!, MaxSnapId, generation); - - nearnephew.right = parent; - nearnephew.left = childsibling; - } + else + {//Case 2 only + Node.Update(ref parent, comp < 0, nearnephew, MaxSnapId, generation); + Node.Update(ref childsibling!, comp > 0, parent, MaxSnapId, generation); - cursor = nearnephew; - cursor.red = parent.red; - parent.red = false; + cursor = childsibling; + childsibling.red = false; + nearnephew.red = true; cursor.size = parent.size; - parent.size = 1 + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size); - childsibling.size = 1 + (childsibling.left == null ? 0 : childsibling.left.size) + (childsibling.right == null ? 0 : childsibling.right.size); + parent.size -= farnephew!.size + 1; + } + } + else if (farnephew != null && farnephew.red) + {//Case 1b + nearnephew = comp > 0 ? childsibling.left : childsibling.right; + Node.Update(ref parent, comp < 0, nearnephew!, MaxSnapId, generation); + Node.CopyNode(ref childsibling!, MaxSnapId, generation); + if (comp > 0) + { + childsibling.left = parent; + childsibling.right = farnephew; } else - {//Case 1a can't happen - throw new InternalException("Case 1a can't happen here"); + { + childsibling.right = parent; + childsibling.left = farnephew; } - //Resplice cursor: - if (level == 0) + cursor = childsibling; + cursor.red = parent.red; + parent.red = false; + farnephew.red = false; + + cursor.size = parent.size; + parent.size -= farnephew.size + 1; + } + else if (nearnephew != null && nearnephew.red) + {//Case 1c + Node.CopyNode(ref nearnephew!, MaxSnapId, generation); + if (comp > 0) { - root = cursor; + Node.Update(ref childsibling!, true, nearnephew.right!, MaxSnapId, generation); + Node.Update(ref parent, false, nearnephew.left!, MaxSnapId, generation); + + nearnephew.left = parent; + nearnephew.right = childsibling; } else { - Node swap = cursor; - - cursor = path[--level]!; - path[level] = null; - Node.Update(ref cursor!, dirs[level] > 0, swap, MaxSnapId, generation); + Node.Update(ref childsibling!, false, nearnephew.left!, MaxSnapId, generation); + Node.Update(ref parent, true, nearnephew.right!, MaxSnapId, generation); - cursor.size--; + nearnephew.right = parent; + nearnephew.left = childsibling; } + + cursor = nearnephew; + cursor.red = parent.red; + parent.red = false; + cursor.size = parent.size; + parent.size = 1 + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size); + childsibling.size = 1 + (childsibling.left == null ? 0 : childsibling.left.size) + (childsibling.right == null ? 0 : childsibling.right.size); + } + else + {//Case 1a can't happen + throw new InternalException("Case 1a can't happen here"); } - //Stage 6: fixup to the root - while (level > 0) + //Resplice cursor: + if (level == 0) { - Node child = cursor; + root = cursor; + } + else + { + Node swap = cursor; - cursor = path![--level]!; + cursor = path[--level]!; path[level] = null; - if (child != (dirs[level] > 0 ? cursor.left : cursor.right)) - { - Node.Update(ref cursor, dirs[level] > 0, child, MaxSnapId, generation); - } + Node.Update(ref cursor!, dirs[level] > 0, swap, MaxSnapId, generation); cursor.size--; } - - root = cursor; - return true; } - - /// - /// Remove all items from this collection. - /// - public void Clear() + //Stage 6: fixup to the root + while (level > 0) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - - UpdateCheck(); - if (size == 0) - { - return; - } + Node child = cursor; - int oldsize = size; - ClearInner(); - if ((ActiveEvents & EventType.Cleared) != 0) + cursor = path![--level]!; + path[level] = null; + if (child != (dirs[level] > 0 ? cursor.left : cursor.right)) { - RaiseCollectionCleared(true, oldsize); + Node.Update(ref cursor, dirs[level] > 0, child, MaxSnapId, generation); } - if ((ActiveEvents & EventType.Changed) != 0) - { - RaiseCollectionChanged(); - } + cursor.size--; } - private void ClearInner() + root = cursor; + return true; + } + + + /// + /// Remove all items from this collection. + /// + public void Clear() + { + if (!isValid) { - size = 0; - root = null; - blackdepth = 0; + throw new ViewDisposedException("Snapshot has been disposed"); } - /// - /// Remove all items in another collection from this one. If this collection - /// has bag semantics, take multiplicities into account. - /// - /// The items to remove. - public void RemoveAll(SCG.IEnumerable items) + UpdateCheck(); + if (size == 0) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - - UpdateCheck(); - - T jtem; - - bool mustRaise = (ActiveEvents & (EventType.Removed | EventType.Changed)) != 0; - RaiseForRemoveAllHandler? raiseHandler = mustRaise ? new RaiseForRemoveAllHandler(this) : null; - - foreach (T item in items) - { - if (root == null) - { - break; - } - - jtem = item; - if (RemoveIterative(ref jtem, out int junk) && mustRaise) - { - raiseHandler!.Remove(jtem); - } - } - if (mustRaise) - { - raiseHandler!.Raise(); - } + return; } - /// - /// Remove all items not in some other collection from this one. If this collection - /// has bag semantics, take multiplicities into account. - /// - /// The items to retain. - public void RetainAll(SCG.IEnumerable items) + int oldsize = size; + ClearInner(); + if ((ActiveEvents & EventType.Cleared) != 0) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + RaiseCollectionCleared(true, oldsize); + } - UpdateCheck(); + if ((ActiveEvents & EventType.Changed) != 0) + { + RaiseCollectionChanged(); + } + } - //A much more efficient version is possible if items is sorted like this. - //Well, it is unclear how efficient it would be. - //We could use a marking method!? -#warning how does this work together with persistence? - TreeSet t = (TreeSet)MemberwiseClone(); + private void ClearInner() + { + size = 0; + root = null; + blackdepth = 0; + } - T jtem = default; - t.ClearInner(); - foreach (T item in items) - { - if (ContainsCount(item) > t.ContainsCount(item)) - { - t.Add(item, ref jtem); - } - } + /// + /// Remove all items in another collection from this one. If this collection + /// has bag semantics, take multiplicities into account. + /// + /// The items to remove. + public void RemoveAll(SCG.IEnumerable items) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); + } - if (size == t.size) - { - return; - } + UpdateCheck(); -#warning improve (mainly for bag) by using a Node iterator instead of ItemMultiplicities() - CircularQueue>? wasRemoved = null; - if ((ActiveEvents & EventType.Removed) != 0) - { - wasRemoved = new CircularQueue>(); - SCG.IEnumerator> ie = ItemMultiplicities().GetEnumerator(); - foreach (System.Collections.Generic.KeyValuePair p in t.ItemMultiplicities()) - { - //We know p.Key is in this! - while (ie.MoveNext()) - { - if (comparer!.Compare(ie.Current.Key, p.Key) == 0) - { + T jtem; - break; - } - else - { - wasRemoved.Enqueue(ie.Current); - } - } - } - while (ie.MoveNext()) - { - wasRemoved.Enqueue(ie.Current); - } - } + bool mustRaise = (ActiveEvents & (EventType.Removed | EventType.Changed)) != 0; + RaiseForRemoveAllHandler? raiseHandler = mustRaise ? new RaiseForRemoveAllHandler(this) : null; - root = t.root; - size = t.size; - blackdepth = t.blackdepth; - if (wasRemoved != null) + foreach (T item in items) + { + if (root == null) { - foreach (System.Collections.Generic.KeyValuePair p in wasRemoved) - { - RaiseItemsRemoved(p.Key, p.Value); - } + break; } - if ((ActiveEvents & EventType.Changed) != 0) + jtem = item; + if (RemoveIterative(ref jtem, out int junk) && mustRaise) { - RaiseCollectionChanged(); + raiseHandler!.Remove(jtem); } } - - /// - /// Check if this collection contains all the values in another collection. - /// If this collection has bag semantics (AllowsDuplicates==true) - /// the check is made with respect to multiplicities, else multiplicities - /// are not taken into account. - /// - /// The - /// True if all values in itemsis in this collection. - public bool ContainsAll(SCG.IEnumerable items) + if (mustRaise) { - //TODO: fix bag implementation - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - //This is worst-case O(m*logn) - foreach (T item in items) - { - if (!Contains(item)) - { - return false; - } - } + raiseHandler!.Raise(); + } + } - return true; + /// + /// Remove all items not in some other collection from this one. If this collection + /// has bag semantics, take multiplicities into account. + /// + /// The items to retain. + public void RetainAll(SCG.IEnumerable items) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } + UpdateCheck(); - //Higher order: - /// - /// Create a new indexed sorted collection consisting of the items of this - /// indexed sorted collection satisfying a certain predicate. - /// - /// The filter delegate defining the predicate. - /// The new indexed sorted collection. - public IIndexedSorted FindAll(Func filter) + //A much more efficient version is possible if items is sorted like this. + //Well, it is unclear how efficient it would be. + //We could use a marking method!? +#warning how does this work together with persistence? + TreeSet t = (TreeSet)MemberwiseClone(); + + T jtem = default; + t.ClearInner(); + foreach (T item in items) { - if (!isValid) + if (ContainsCount(item) > t.ContainsCount(item)) { - throw new ViewDisposedException("Snapshot has been disposed"); + t.Add(item, ref jtem); } + } - TreeSet res = new TreeSet(comparer!); - SCG.IEnumerator e = GetEnumerator(); - Node? head = null, tail = null; - int z = 0; + if (size == t.size) + { + return; + } - while (e.MoveNext()) +#warning improve (mainly for bag) by using a Node iterator instead of ItemMultiplicities() + CircularQueue>? wasRemoved = null; + if ((ActiveEvents & EventType.Removed) != 0) + { + wasRemoved = new CircularQueue>(); + SCG.IEnumerator> ie = ItemMultiplicities().GetEnumerator(); + foreach (System.Collections.Generic.KeyValuePair p in t.ItemMultiplicities()) { - T thisitem = e.Current; - - if (filter(thisitem)) + //We know p.Key is in this! + while (ie.MoveNext()) { - if (head == null) + if (comparer!.Compare(ie.Current.Key, p.Key) == 0) { - head = tail = new Node(); + + break; } else { - - tail!.right = new Node(); - tail = tail.right; + wasRemoved.Enqueue(ie.Current); } - - tail.item = thisitem; - z++; } } - - - if (z == 0) + while (ie.MoveNext()) { - return res; + wasRemoved.Enqueue(ie.Current); } + } - int blackheight = 0, red = z, maxred = 1; - - while (maxred <= red) + root = t.root; + size = t.size; + blackdepth = t.blackdepth; + if (wasRemoved != null) + { + foreach (System.Collections.Generic.KeyValuePair p in wasRemoved) { - red -= maxred; - maxred <<= 1; - blackheight++; + RaiseItemsRemoved(p.Key, p.Value); } - - res.root = TreeSet.MakeTreer(ref head!, blackheight, maxred, red); - res.blackdepth = blackheight; - res.size = z; - - return res; } + if ((ActiveEvents & EventType.Changed) != 0) + { + RaiseCollectionChanged(); + } + } - /// - /// Create a new indexed sorted collection consisting of the results of - /// mapping all items of this list. - /// if the map is not increasing over - /// the items of this collection (with respect to the two given comparison - /// relations). - /// - /// The delegate definging the map. - /// The comparion relation to use for the result. - /// The new sorted collection. - public IIndexedSorted Map(Func mapper, SCG.IComparer c) + /// + /// Check if this collection contains all the values in another collection. + /// If this collection has bag semantics (AllowsDuplicates==true) + /// the check is made with respect to multiplicities, else multiplicities + /// are not taken into account. + /// + /// The + /// True if all values in itemsis in this collection. + public bool ContainsAll(SCG.IEnumerable items) + { + //TODO: fix bag implementation + if (!isValid) { - if (!isValid) + throw new ViewDisposedException("Snapshot has been disposed"); + } + //This is worst-case O(m*logn) + foreach (T item in items) + { + if (!Contains(item)) { - throw new ViewDisposedException("Snapshot has been disposed"); + return false; } + } - TreeSet res = new TreeSet(c); + return true; + } - if (size == 0) - { - return res; - } - SCG.IEnumerator e = GetEnumerator(); - TreeSet.Node? head = null, tail = null; - V oldv = default; - int z = 0; + //Higher order: + /// + /// Create a new indexed sorted collection consisting of the items of this + /// indexed sorted collection satisfying a certain predicate. + /// + /// The filter delegate defining the predicate. + /// The new indexed sorted collection. + public IIndexedSorted FindAll(Func filter) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); + } - while (e.MoveNext()) - { - T thisitem = e.Current; + TreeSet res = new(comparer!); + SCG.IEnumerator e = GetEnumerator(); + Node? head = null, tail = null; + int z = 0; - V newv = mapper(thisitem); + while (e.MoveNext()) + { + T thisitem = e.Current; + if (filter(thisitem)) + { if (head == null) { - head = tail = new TreeSet.Node(); - z++; + head = tail = new Node(); } else { - int comp = c.Compare(oldv, newv); - - if (comp >= 0) - { - throw new ArgumentException("mapper not monotonic"); - } - tail!.right = new TreeSet.Node(); + tail!.right = new Node(); tail = tail.right; - z++; } - tail.item = oldv = newv; + tail.item = thisitem; + z++; } + } - int blackheight = 0, red = z, maxred = 1; - - while (maxred <= red) - { - red -= maxred; - maxred <<= 1; - blackheight++; - } - - res.root = TreeSet.MakeTreer(ref head!, blackheight, maxred, red); - res.blackdepth = blackheight; - res.size = size; + if (z == 0) + { return res; } + int blackheight = 0, red = z, maxred = 1; - //below is the bag utility stuff - /// - /// Count the number of items of the collection equal to a particular value. - /// Returns 0 if and only if the value is not in the collection. - /// - /// The value to count. - /// The number of copies found. - public int ContainsCount(T item) + while (maxred <= red) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - - //Since we are strictly not AllowsDuplicates we just do - return Contains(item) ? 1 : 0; - + red -= maxred; + maxred <<= 1; + blackheight++; } + res.root = TreeSet.MakeTreer(ref head!, blackheight, maxred, red); + res.blackdepth = blackheight; + res.size = z; + return res; + } - /// - /// - /// - /// - public virtual ICollectionValue UniqueItems() + + /// + /// Create a new indexed sorted collection consisting of the results of + /// mapping all items of this list. + /// if the map is not increasing over + /// the items of this collection (with respect to the two given comparison + /// relations). + /// + /// The delegate definging the map. + /// The comparion relation to use for the result. + /// The new sorted collection. + public IIndexedSorted Map(Func mapper, SCG.IComparer c) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - return this; + TreeSet res = new(c); + if (size == 0) + { + return res; } + SCG.IEnumerator e = GetEnumerator(); + TreeSet.Node? head = null, tail = null; + V oldv = default; + int z = 0; - /// - /// - /// - /// - public virtual ICollectionValue> ItemMultiplicities() + while (e.MoveNext()) { - if (!isValid) + T thisitem = e.Current; + + V newv = mapper(thisitem); + + if (head == null) { - throw new ViewDisposedException("Snapshot has been disposed"); + head = tail = new TreeSet.Node(); + z++; } + else + { + int comp = c.Compare(oldv, newv); + + if (comp >= 0) + { + throw new ArgumentException("mapper not monotonic"); + } - return new MultiplicityOne(this); + tail!.right = new TreeSet.Node(); + tail = tail.right; + z++; + } + tail.item = oldv = newv; } - /// - /// Remove all items equivalent to a given value. - /// - /// The value to remove. - public void RemoveAllCopies(T item) - { - Remove(item); + int blackheight = 0, red = z, maxred = 1; + while (maxred <= red) + { + red -= maxred; + maxred <<= 1; + blackheight++; } - #endregion + res.root = TreeSet.MakeTreer(ref head!, blackheight, maxred, red); + res.blackdepth = blackheight; + res.size = size; + return res; + } - #region IIndexed Members - private Node FindNode(int i) + //below is the bag utility stuff + /// + /// Count the number of items of the collection equal to a particular value. + /// Returns 0 if and only if the value is not in the collection. + /// + /// The value to count. + /// The number of copies found. + public int ContainsCount(T item) + { + if (!isValid) { - if (isSnapShot) - { - throw new NotSupportedException("Indexing not supported for snapshots"); - } - - Node? next = root; - - if (i >= 0 && i < size) - { - while (true) - { - int j = next!.left == null ? 0 : next.left.size; + throw new ViewDisposedException("Snapshot has been disposed"); + } - if (i > j) - { + //Since we are strictly not AllowsDuplicates we just do + return Contains(item) ? 1 : 0; - i -= j + 1; + } - next = next.right; - } - else if (i == j) - { - return next; - } - else - { - next = next.left; - } - } - } - throw new IndexOutOfRangeException(); + /// + /// + /// + /// + public virtual ICollectionValue UniqueItems() + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } + return this; - /// - /// if i is negative or - /// >= the size of the collection. - /// - /// The i'th item of this list. - /// the index to lookup - public T this[int i] => FindNode(i).item; - - /// - /// - /// - /// - public virtual Speed IndexingSpeed => Speed.Log; + } - //TODO: return -upper instead of -1 in case of not found - /// - /// Searches for an item in this indexed collection going forwards from the start. - /// - /// Item to search for. - /// Index of first occurrence from start of the item - /// if found, else the two-complement - /// (always negative) of the index at which the item would be put if it was added. - public int IndexOf(T item) + /// + /// + /// + /// + public virtual ICollectionValue> ItemMultiplicities() + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - - return IndexOf(item, out _); + throw new ViewDisposedException("Snapshot has been disposed"); } + return new MultiplicityOne(this); - private int IndexOf(T item, out int upper) - { - if (isSnapShot) - { - throw new NotSupportedException("Indexing not supported for snapshots"); - } + } - int ind = 0; Node? next = root; + /// + /// Remove all items equivalent to a given value. + /// + /// The value to remove. + public void RemoveAllCopies(T item) + { - while (next != null) - { - int comp = comparer!.Compare(item, next.item); + Remove(item); - if (comp < 0) - { - next = next.left!; - } - else - { - int leftcnt = next.left == null ? 0 : next.left.size; + } - if (comp == 0) - { + #endregion - return upper = ind + leftcnt; + #region IIndexed Members - } - else - { + private Node FindNode(int i) + { + if (isSnapShot) + { + throw new NotSupportedException("Indexing not supported for snapshots"); + } - ind = ind + 1 + leftcnt; + Node? next = root; - next = next.right!; - } + if (i >= 0 && i < size) + { + while (true) + { + int j = next!.left == null ? 0 : next.left.size; + + if (i > j) + { + + i -= j + 1; + + next = next.right; + } + else if (i == j) + { + return next; + } + else + { + next = next.left; } } - upper = ~ind; - return ~ind; } + throw new IndexOutOfRangeException(); - /// - /// Searches for an item in the tree going backwards from the end. - /// - /// Item to search for. - /// Index of last occurrence from the end of item if found, - /// else the two-complement (always negative) of the index at which - /// the item would be put if it was added. - public int LastIndexOf(T item) - { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + } - //We have AllowsDuplicates==false for the set - return IndexOf(item); - } + /// + /// if i is negative or + /// >= the size of the collection. + /// + /// The i'th item of this list. + /// the index to lookup + public T this[int i] => FindNode(i).item; + + /// + /// + /// + /// + public virtual Speed IndexingSpeed => Speed.Log; - /// - /// Remove the item at a specific position of the list. - /// if i is negative or - /// >= the size of the collection. - /// - /// The index of the item to remove. - /// The removed item. - public T RemoveAt(int i) + //TODO: return -upper instead of -1 in case of not found + /// + /// Searches for an item in this indexed collection going forwards from the start. + /// + /// Item to search for. + /// Index of first occurrence from start of the item + /// if found, else the two-complement + /// (always negative) of the index at which the item would be put if it was added. + public int IndexOf(T item) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - UpdateCheck(); - T retval = RemoveAtInner(i); - if (ActiveEvents != 0) - { - RaiseForRemove(retval); - } + return IndexOf(item, out _); + } - return retval; - } - private T RemoveAtInner(int i) + private int IndexOf(T item, out int upper) + { + if (isSnapShot) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new NotSupportedException("Indexing not supported for snapshots"); + } - UpdateCheck(); - if (i < 0 || i >= size) - { - throw new IndexOutOfRangeException("Index out of range for sequenced collectionvalue"); - } + int ind = 0; Node? next = root; + + while (next != null) + { + int comp = comparer!.Compare(item, next.item); - //We must follow the pattern of removeIterative() - while (dirs!.Length < 2 * blackdepth) + if (comp < 0) { - dirs = new int[2 * dirs.Length]; - path = new Node[2 * dirs.Length]; + next = next.left!; } - - int level = 0; - Node? cursor = root; - - while (true) + else { - int j = cursor!.left == null ? 0 : cursor.left.size; + int leftcnt = next.left == null ? 0 : next.left.size; - if (i > j) + if (comp == 0) { - i -= j + 1; + return upper = ind + leftcnt; - dirs[level] = -1; - path![level++] = cursor; - cursor = cursor.right; - } - else if (i == j) - { - break; } else { - dirs[level] = 1; - path![level++] = cursor; - cursor = cursor.left; + + ind = ind + 1 + leftcnt; + + next = next.right!; } } + } + upper = ~ind; + return ~ind; + } - T retval = cursor.item; + /// + /// Searches for an item in the tree going backwards from the end. + /// + /// Item to search for. + /// Index of last occurrence from the end of item if found, + /// else the two-complement (always negative) of the index at which + /// the item would be put if it was added. + public int LastIndexOf(T item) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); + } - RemoveIterativePhase2(cursor, level); - return retval; + //We have AllowsDuplicates==false for the set + return IndexOf(item); + + } + + + /// + /// Remove the item at a specific position of the list. + /// if i is negative or + /// >= the size of the collection. + /// + /// The index of the item to remove. + /// The removed item. + public T RemoveAt(int i) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); + } + UpdateCheck(); + T retval = RemoveAtInner(i); + if (ActiveEvents != 0) + { + RaiseForRemove(retval); } + return retval; + } - /// - /// Remove all items in an index interval. - /// ???. - /// - /// The index of the first item to remove. - /// The number of items to remove. - public void RemoveInterval(int start, int count) + private T RemoveAtInner(int i) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - if (start < 0 || count < 0 || start + count > size) - { - throw new ArgumentOutOfRangeException(); - } + UpdateCheck(); + if (i < 0 || i >= size) + { + throw new IndexOutOfRangeException("Index out of range for sequenced collectionvalue"); + } - UpdateCheck(); + //We must follow the pattern of removeIterative() + while (dirs!.Length < 2 * blackdepth) + { + dirs = new int[2 * dirs.Length]; + path = new Node[2 * dirs.Length]; + } - if (count == 0) - { - return; - } + int level = 0; + Node? cursor = root; - //This is terrible for large count. We should split the tree at - //the endpoints of the range and fuse the parts! - //We really need good internal destructive split and catenate functions! - //Alternative for large counts: rebuild tree using maketree() - for (int i = 0; i < count; i++) + while (true) + { + int j = cursor!.left == null ? 0 : cursor.left.size; + + if (i > j) { - RemoveAtInner(start); - } - if ((ActiveEvents & EventType.Cleared) != 0) + i -= j + 1; + + dirs[level] = -1; + path![level++] = cursor; + cursor = cursor.right; + } + else if (i == j) { - RaiseCollectionCleared(false, count); + break; } - - if ((ActiveEvents & EventType.Changed) != 0) + else { - RaiseCollectionChanged(); + dirs[level] = 1; + path![level++] = cursor; + cursor = cursor.left; } } + T retval = cursor.item; - /// - /// . - /// - /// The directed collection of items in a specific index interval. - /// The starting index of the interval (inclusive). - /// The length of the interval. - public IDirectedCollectionValue this[int start, int count] + + RemoveIterativePhase2(cursor, level); + return retval; + + } + + + /// + /// Remove all items in an index interval. + /// ???. + /// + /// The index of the first item to remove. + /// The number of items to remove. + public void RemoveInterval(int start, int count) + { + if (!isValid) { - get - { - CheckRange(start, count); - return new Interval(this, start, count, true); - } + throw new ViewDisposedException("Snapshot has been disposed"); } - #region Interval nested class - private class Interval : DirectedCollectionValueBase, IDirectedCollectionValue + if (start < 0 || count < 0 || start + count > size) { - private readonly int start, length, stamp; - private readonly bool forwards; - private readonly TreeSet tree; + throw new ArgumentOutOfRangeException(); + } + UpdateCheck(); - internal Interval(TreeSet tree, int start, int count, bool forwards) - { - if (tree.isSnapShot) - { - throw new NotSupportedException("Indexing not supported for snapshots"); - } + if (count == 0) + { + return; + } - this.start = start; length = count; this.forwards = forwards; - this.tree = tree; stamp = tree.stamp; - } + //This is terrible for large count. We should split the tree at + //the endpoints of the range and fuse the parts! + //We really need good internal destructive split and catenate functions! + //Alternative for large counts: rebuild tree using maketree() + for (int i = 0; i < count; i++) + { + RemoveAtInner(start); + } - public override bool IsEmpty => length == 0; + if ((ActiveEvents & EventType.Cleared) != 0) + { + RaiseCollectionCleared(false, count); + } + + if ((ActiveEvents & EventType.Changed) != 0) + { + RaiseCollectionChanged(); + } + } - public override int Count => length; + /// + /// . + /// + /// The directed collection of items in a specific index interval. + /// The starting index of the interval (inclusive). + /// The length of the interval. + public IDirectedCollectionValue this[int start, int count] + { + get + { + CheckRange(start, count); + return new Interval(this, start, count, true); + } + } - public override Speed CountSpeed => Speed.Constant; + #region Interval nested class + private class Interval : DirectedCollectionValueBase, IDirectedCollectionValue + { + private readonly int start, length, stamp; + private readonly bool forwards; + private readonly TreeSet tree; - public override T Choose() + internal Interval(TreeSet tree, int start, int count, bool forwards) + { + if (tree.isSnapShot) { - if (length == 0) - { - throw new NoSuchItemException(); - } - - return tree[start]; + throw new NotSupportedException("Indexing not supported for snapshots"); } - public override SCG.IEnumerator GetEnumerator() + this.start = start; length = count; this.forwards = forwards; + this.tree = tree; stamp = tree.stamp; + } + + public override bool IsEmpty => length == 0; + + public override int Count => length; + + + public override Speed CountSpeed => Speed.Constant; + + + public override T Choose() + { + if (length == 0) { - tree.ModifyCheck(stamp); + throw new NoSuchItemException(); + } - Node? cursor = tree.root; - Node[] path = new Node[2 * tree.blackdepth]; - int level = 0, totaltogo = length; + return tree[start]; + } - if (totaltogo == 0) - { - yield break; - } + public override SCG.IEnumerator GetEnumerator() + { + tree.ModifyCheck(stamp); - if (forwards) + Node? cursor = tree.root; + Node[] path = new Node[2 * tree.blackdepth]; + int level = 0, totaltogo = length; + + if (totaltogo == 0) + { + yield break; + } + + if (forwards) + { + int i = start; + + while (true) { - int i = start; + int j = cursor!.left == null ? 0 : cursor.left.size; - while (true) + if (i > j) { - int j = cursor!.left == null ? 0 : cursor.left.size; - - if (i > j) - { - i -= j + 1; + i -= j + 1; - cursor = cursor.right; - } - else if (i == j) - { + cursor = cursor.right; + } + else if (i == j) + { - break; - } // i < j, start point tree[start] is in left subtree - else - { - path[level++] = cursor; - cursor = cursor.left; - } + break; + } // i < j, start point tree[start] is in left subtree + else + { + path[level++] = cursor; + cursor = cursor.left; } + } - T current = cursor.item; + T current = cursor.item; - while (totaltogo-- > 0) - { - yield return current; - tree.ModifyCheck(stamp); + while (totaltogo-- > 0) + { + yield return current; + tree.ModifyCheck(stamp); - if (cursor.right != null) - { - path[level] = cursor = cursor.right; - while (cursor.left != null) - { - path[++level] = cursor = cursor.left; - } - } - else if (level == 0) - { - yield break; - } - else + if (cursor.right != null) + { + path[level] = cursor = cursor.right; + while (cursor.left != null) { - cursor = path[--level]; + path[++level] = cursor = cursor.left; } + } + else if (level == 0) + { + yield break; + } + else + { + cursor = path[--level]; + } - current = cursor.item; + current = cursor.item; - } } - else // backwards + } + else // backwards + { + int i = start + length - 1; + + while (true) { - int i = start + length - 1; + int j = cursor!.left == null ? 0 : cursor.left.size; - while (true) + if (i > j) { - int j = cursor!.left == null ? 0 : cursor.left.size; - - if (i > j) - { - i -= j + 1; + i -= j + 1; - path[level++] = cursor; - cursor = cursor.right; - } - else if (i == j) - { + path[level++] = cursor; + cursor = cursor.right; + } + else if (i == j) + { - break; - } - else // i <= j, end point tree[start+count-1] is in left subtree - { - cursor = cursor.left; - } + break; + } + else // i <= j, end point tree[start+count-1] is in left subtree + { + cursor = cursor.left; } + } - T current = cursor.item; + T current = cursor.item; - while (totaltogo-- > 0) - { - yield return current; - tree.ModifyCheck(stamp); + while (totaltogo-- > 0) + { + yield return current; + tree.ModifyCheck(stamp); - if (cursor.left != null) - { - path[level] = cursor = cursor.left; - while (cursor.right != null) - { - path[++level] = cursor = cursor.right; - } - } - else if (level == 0) - { - yield break; - } - else + if (cursor.left != null) + { + path[level] = cursor = cursor.left; + while (cursor.right != null) { - cursor = path[--level]; + path[++level] = cursor = cursor.right; } - - current = cursor.item; - } - } + else if (level == 0) + { + yield break; + } + else + { + cursor = path[--level]; + } + current = cursor.item; + } } - public override IDirectedCollectionValue Backwards() - { return new Interval(tree, start, length, !forwards); } + } - IDirectedEnumerable C5.IDirectedEnumerable.Backwards() - { return Backwards(); } + public override IDirectedCollectionValue Backwards() + { return new Interval(tree, start, length, !forwards); } - public override Direction Direction => forwards ? Direction.Forwards : Direction.Backwards; - } - #endregion - - /// - /// Create a collection containing the same items as this collection, but - /// whose enumerator will enumerate the items backwards. The new collection - /// will become invalid if the original is modified. Method typically used as in - /// foreach (T x in coll.Backwards()) {...} - /// - /// The backwards collection. - public override IDirectedCollectionValue Backwards() { return RangeAll().Backwards(); } + IDirectedEnumerable C5.IDirectedEnumerable.Backwards() + { return Backwards(); } - IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } + public override Direction Direction => forwards ? Direction.Forwards : Direction.Backwards; + } + #endregion - #endregion + /// + /// Create a collection containing the same items as this collection, but + /// whose enumerator will enumerate the items backwards. The new collection + /// will become invalid if the original is modified. Method typically used as in + /// foreach (T x in coll.Backwards()) {...} + /// + /// The backwards collection. + public override IDirectedCollectionValue Backwards() { return RangeAll().Backwards(); } - #region PriorityQueue Members - /// - /// The comparer object supplied at creation time for this collection - /// - /// The comparer - public SCG.IComparer Comparer => comparer!; + IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } + #endregion - /// - /// Find the current least item of this priority queue. - /// - /// The least item. - public T FindMin() - { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + #region PriorityQueue Members - if (size == 0) - { - throw new NoSuchItemException(); - } + /// + /// The comparer object supplied at creation time for this collection + /// + /// The comparer + public SCG.IComparer Comparer => comparer!; - Node cursor = root!, next = Left(cursor!); - while (next != null) - { - cursor = next; - next = Left(cursor); - } + /// + /// Find the current least item of this priority queue. + /// + /// The least item. + public T FindMin() + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); + } - return cursor!.item; + if (size == 0) + { + throw new NoSuchItemException(); } + Node cursor = root!, next = Left(cursor!); - /// - /// Remove the least item from this priority queue. - /// - /// The removed item. - public T DeleteMin() + while (next != null) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - - UpdateCheck(); + cursor = next; + next = Left(cursor); + } - //persistence guard? - if (size == 0) - { - throw new NoSuchItemException(); - } + return cursor!.item; + } - //We must follow the pattern of removeIterative() - StackCheck(); - T retval = DeleteMinInner(); - if (ActiveEvents != 0) - { - RaiseItemsRemoved(retval, 1); - RaiseCollectionChanged(); - } - return retval; + /// + /// Remove the least item from this priority queue. + /// + /// The removed item. + public T DeleteMin() + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } - private T DeleteMinInner() - { - int level = 0; - Node? cursor = root; + UpdateCheck(); - while (cursor!.left != null) - { - dirs![level] = 1; - path![level++] = cursor; - cursor = cursor.left; - } + //persistence guard? + if (size == 0) + { + throw new NoSuchItemException(); + } - T retval = cursor.item; + //We must follow the pattern of removeIterative() + StackCheck(); - RemoveIterativePhase2(cursor, level); - return retval; + T retval = DeleteMinInner(); + if (ActiveEvents != 0) + { + RaiseItemsRemoved(retval, 1); + RaiseCollectionChanged(); } + return retval; + } + private T DeleteMinInner() + { + int level = 0; + Node? cursor = root; - /// - /// Find the current largest item of this priority queue. - /// - /// The largest item. - public T FindMax() + while (cursor!.left != null) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + dirs![level] = 1; + path![level++] = cursor; + cursor = cursor.left; + } - if (size == 0) - { - throw new NoSuchItemException(); - } + T retval = cursor.item; - Node? cursor = root, next = Right(cursor!); + RemoveIterativePhase2(cursor, level); + return retval; + } - while (next != null) - { - cursor = next; - next = Right(cursor); - } - return cursor!.item; + /// + /// Find the current largest item of this priority queue. + /// + /// The largest item. + public T FindMax() + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } - - /// - /// Remove the largest item from this priority queue. - /// - /// The removed item. - public T DeleteMax() + if (size == 0) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - //persistence guard? - UpdateCheck(); - if (size == 0) - { - throw new NoSuchItemException(); - } - - //We must follow the pattern of removeIterative() - StackCheck(); - - T retval = DeleteMaxInner(); - if (ActiveEvents != 0) - { - RaiseItemsRemoved(retval, 1); - RaiseCollectionChanged(); - } - return retval; + throw new NoSuchItemException(); } - private T DeleteMaxInner() + Node? cursor = root, next = Right(cursor!); + + while (next != null) { - int level = 0; - Node? cursor = root; + cursor = next; + next = Right(cursor); + } - while (cursor!.right != null) - { - dirs![level] = -1; - path![level++] = cursor; - cursor = cursor.right; - } + return cursor!.item; + } - T retval = cursor.item; - RemoveIterativePhase2(cursor, level); - return retval; + /// + /// Remove the largest item from this priority queue. + /// + /// The removed item. + public T DeleteMax() + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } - #endregion - - #region ISorted Members - - /// - /// Find the strict predecessor of item in the sorted collection, - /// that is, the greatest item in the collection smaller than the item. - /// - /// The item to find the predecessor for. - /// The predecessor, if any; otherwise the default value for T. - /// True if item has a predecessor; otherwise false. - public bool TryPredecessor(T item, out T res) + //persistence guard? + UpdateCheck(); + if (size == 0) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - - Node? cursor = root, bestsofar = null; + throw new NoSuchItemException(); + } - while (cursor != null) - { - int comp = comparer!.Compare(cursor.item, item); + //We must follow the pattern of removeIterative() + StackCheck(); - if (comp < 0) - { - bestsofar = cursor; - cursor = Right(cursor); - } - else if (comp == 0) - { - cursor = Left(cursor); - while (cursor != null) - { - bestsofar = cursor; - cursor = Right(cursor); - } - } - else - { - cursor = Left(cursor); - } - } - if (bestsofar == null) - { - res = default; - return false; - } - else - { - res = bestsofar.item; - return true; - } + T retval = DeleteMaxInner(); + if (ActiveEvents != 0) + { + RaiseItemsRemoved(retval, 1); + RaiseCollectionChanged(); } + return retval; + } + private T DeleteMaxInner() + { + int level = 0; + Node? cursor = root; - /// - /// Find the strict successor of item in the sorted collection, - /// that is, the least item in the collection greater than the supplied value. - /// - /// The item to find the successor for. - /// The successor, if any; otherwise the default value for T. - /// True if item has a successor; otherwise false. - public bool TrySuccessor(T item, out T res) + while (cursor!.right != null) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + dirs![level] = -1; + path![level++] = cursor; + cursor = cursor.right; + } - Node? cursor = root, bestsofar = null; + T retval = cursor.item; - while (cursor != null) - { - int comp = comparer!.Compare(cursor.item, item); + RemoveIterativePhase2(cursor, level); + return retval; + } + #endregion - if (comp > 0) - { - bestsofar = cursor; - cursor = Left(cursor); - } - else if (comp == 0) - { - cursor = Right(cursor); - while (cursor != null) - { - bestsofar = cursor; - cursor = Left(cursor); - } - } - else - { - cursor = Right(cursor); - } - } + #region ISorted Members - if (bestsofar == null) - { - res = default; - return false; - } - else - { - res = bestsofar.item; - return true; - } + /// + /// Find the strict predecessor of item in the sorted collection, + /// that is, the greatest item in the collection smaller than the item. + /// + /// The item to find the predecessor for. + /// The predecessor, if any; otherwise the default value for T. + /// True if item has a predecessor; otherwise false. + public bool TryPredecessor(T item, out T res) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } + Node? cursor = root, bestsofar = null; - /// - /// Find the weak predecessor of item in the sorted collection, - /// that is, the greatest item in the collection smaller than or equal to the item. - /// - /// The item to find the weak predecessor for. - /// The weak predecessor, if any; otherwise the default value for T. - /// True if item has a weak predecessor; otherwise false. - public bool TryWeakPredecessor(T item, out T res) + while (cursor != null) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + int comp = comparer!.Compare(cursor.item, item); - Node? cursor = root, bestsofar = null; - - while (cursor != null) + if (comp < 0) { - int comp = comparer!.Compare(cursor.item, item); - - if (comp < 0) - { - bestsofar = cursor; - cursor = Right(cursor); - } - else if (comp == 0) - { - res = cursor.item; - return true; - } - else - { - cursor = Left(cursor); - } + bestsofar = cursor; + cursor = Right(cursor); } - if (bestsofar == null) + else if (comp == 0) { - res = default; - return false; + cursor = Left(cursor); + while (cursor != null) + { + bestsofar = cursor; + cursor = Right(cursor); + } } else { - res = bestsofar.item; - return true; + cursor = Left(cursor); } } + if (bestsofar == null) + { + res = default; + return false; + } + else + { + res = bestsofar.item; + return true; + } + } - /// - /// Find the weak successor of item in the sorted collection, - /// that is, the least item in the collection greater than or equal to the supplied value. - /// - /// The item to find the weak successor for. - /// The weak successor, if any; otherwise the default value for T. - /// True if item has a weak successor; otherwise false. - public bool TryWeakSuccessor(T item, out T res) + /// + /// Find the strict successor of item in the sorted collection, + /// that is, the least item in the collection greater than the supplied value. + /// + /// The item to find the successor for. + /// The successor, if any; otherwise the default value for T. + /// True if item has a successor; otherwise false. + public bool TrySuccessor(T item, out T res) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - Node? cursor = root, bestsofar = null; + Node? cursor = root, bestsofar = null; - while (cursor != null) - { - int comp = comparer!.Compare(cursor.item, item); + while (cursor != null) + { + int comp = comparer!.Compare(cursor.item, item); - if (comp == 0) - { - res = cursor.item; - return true; - } - else if (comp > 0) + if (comp > 0) + { + bestsofar = cursor; + cursor = Left(cursor); + } + else if (comp == 0) + { + cursor = Right(cursor); + while (cursor != null) { bestsofar = cursor; cursor = Left(cursor); } - else - { - cursor = Right(cursor); - } - } - - if (bestsofar == null) - { - res = default; - return false; } else { - res = bestsofar.item; - return true; + cursor = Right(cursor); } } + if (bestsofar == null) + { + res = default; + return false; + } + else + { + res = bestsofar.item; + return true; + } + } + - /// - /// Find the strict predecessor in the sorted collection of a particular value, - /// i.e. the largest item in the collection less than the supplied value. - /// - /// if no such element exists (the - /// supplied value is less than or equal to the minimum of this collection.) - /// The item to find the predecessor for. - /// The predecessor. - public T Predecessor(T item) + /// + /// Find the weak predecessor of item in the sorted collection, + /// that is, the greatest item in the collection smaller than or equal to the item. + /// + /// The item to find the weak predecessor for. + /// The weak predecessor, if any; otherwise the default value for T. + /// True if item has a weak predecessor; otherwise false. + public bool TryWeakPredecessor(T item, out T res) + { + if (!isValid) { - if (TryPredecessor(item, out T res)) - { - return res; - } - else - { - throw new NoSuchItemException(); - } + throw new ViewDisposedException("Snapshot has been disposed"); } + Node? cursor = root, bestsofar = null; - /// - /// Find the weak predecessor in the sorted collection of a particular value, - /// i.e. the largest item in the collection less than or equal to the supplied value. - /// - /// if no such element exists (the - /// supplied value is less than the minimum of this collection.) - /// The item to find the weak predecessor for. - /// The weak predecessor. - public T WeakPredecessor(T item) + while (cursor != null) { - if (TryWeakPredecessor(item, out T res)) + int comp = comparer!.Compare(cursor.item, item); + + if (comp < 0) + { + bestsofar = cursor; + cursor = Right(cursor); + } + else if (comp == 0) { - return res; + res = cursor.item; + return true; } else { - throw new NoSuchItemException(); + cursor = Left(cursor); } } + if (bestsofar == null) + { + res = default; + return false; + } + else + { + res = bestsofar.item; + return true; + } + } - /// - /// Find the strict successor in the sorted collection of a particular value, - /// i.e. the least item in the collection greater than the supplied value. - /// - /// if no such element exists (the - /// supplied value is greater than or equal to the maximum of this collection.) - /// The item to find the successor for. - /// The successor. - public T Successor(T item) + /// + /// Find the weak successor of item in the sorted collection, + /// that is, the least item in the collection greater than or equal to the supplied value. + /// + /// The item to find the weak successor for. + /// The weak successor, if any; otherwise the default value for T. + /// True if item has a weak successor; otherwise false. + public bool TryWeakSuccessor(T item, out T res) + { + if (!isValid) { - if (TrySuccessor(item, out T res)) - { - return res; - } - else - { - throw new NoSuchItemException(); - } + throw new ViewDisposedException("Snapshot has been disposed"); } + Node? cursor = root, bestsofar = null; - /// - /// Find the weak successor in the sorted collection of a particular value, - /// i.e. the least item in the collection greater than or equal to the supplied value. - /// if no such element exists (the - /// supplied value is greater than the maximum of this collection.) - /// - /// The item to find the weak successor for. - /// The weak successor. - public T WeakSuccessor(T item) + while (cursor != null) { - if (TryWeakSuccessor(item, out T res)) + int comp = comparer!.Compare(cursor.item, item); + + if (comp == 0) { - return res; + res = cursor.item; + return true; + } + else if (comp > 0) + { + bestsofar = cursor; + cursor = Left(cursor); } else { - throw new NoSuchItemException(); + cursor = Right(cursor); } } + if (bestsofar == null) + { + res = default; + return false; + } + else + { + res = bestsofar.item; + return true; + } + } + - /// - /// Query this sorted collection for items greater than or equal to a supplied value. - /// - /// The lower bound (inclusive). - /// The result directed collection. - public IDirectedCollectionValue RangeFrom(T bot) + /// + /// Find the strict predecessor in the sorted collection of a particular value, + /// i.e. the largest item in the collection less than the supplied value. + /// + /// if no such element exists (the + /// supplied value is less than or equal to the minimum of this collection.) + /// The item to find the predecessor for. + /// The predecessor. + public T Predecessor(T item) + { + if (TryPredecessor(item, out T res)) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + return res; + } + else + { + throw new NoSuchItemException(); + } + } - return new Range(this, true, bot, false, default, Direction.Forwards); + + /// + /// Find the weak predecessor in the sorted collection of a particular value, + /// i.e. the largest item in the collection less than or equal to the supplied value. + /// + /// if no such element exists (the + /// supplied value is less than the minimum of this collection.) + /// The item to find the weak predecessor for. + /// The weak predecessor. + public T WeakPredecessor(T item) + { + if (TryWeakPredecessor(item, out T res)) + { + return res; } + else + { + throw new NoSuchItemException(); + } + } - /// - /// Query this sorted collection for items between two supplied values. - /// - /// The lower bound (inclusive). - /// The upper bound (exclusive). - /// The result directed collection. - public IDirectedCollectionValue RangeFromTo(T bot, T top) + /// + /// Find the strict successor in the sorted collection of a particular value, + /// i.e. the least item in the collection greater than the supplied value. + /// + /// if no such element exists (the + /// supplied value is greater than or equal to the maximum of this collection.) + /// The item to find the successor for. + /// The successor. + public T Successor(T item) + { + if (TrySuccessor(item, out T res)) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + return res; + } + else + { + throw new NoSuchItemException(); + } + } + - return new Range(this, true, bot, true, top, Direction.Forwards); + /// + /// Find the weak successor in the sorted collection of a particular value, + /// i.e. the least item in the collection greater than or equal to the supplied value. + /// if no such element exists (the + /// supplied value is greater than the maximum of this collection.) + /// + /// The item to find the weak successor for. + /// The weak successor. + public T WeakSuccessor(T item) + { + if (TryWeakSuccessor(item, out T res)) + { + return res; + } + else + { + throw new NoSuchItemException(); } + } - /// - /// Query this sorted collection for items less than a supplied value. - /// - /// The upper bound (exclusive). - /// The result directed collection. - public IDirectedCollectionValue RangeTo(T top) + /// + /// Query this sorted collection for items greater than or equal to a supplied value. + /// + /// The lower bound (inclusive). + /// The result directed collection. + public IDirectedCollectionValue RangeFrom(T bot) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - return new Range(this, false, default, true, top, Direction.Forwards); + return new Range(this, true, bot, false, default, Direction.Forwards); + } + + + /// + /// Query this sorted collection for items between two supplied values. + /// + /// The lower bound (inclusive). + /// The upper bound (exclusive). + /// The result directed collection. + public IDirectedCollectionValue RangeFromTo(T bot, T top) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } + return new Range(this, true, bot, true, top, Direction.Forwards); + } + - /// - /// Create a directed collection with the same items as this collection. - /// - /// The result directed collection. - public IDirectedCollectionValue RangeAll() + /// + /// Query this sorted collection for items less than a supplied value. + /// + /// The upper bound (exclusive). + /// The result directed collection. + public IDirectedCollectionValue RangeTo(T top) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } + + return new Range(this, false, default, true, top, Direction.Forwards); + } + - return new Range(this, false, default, false, default, Direction.Forwards); + /// + /// Create a directed collection with the same items as this collection. + /// + /// The result directed collection. + public IDirectedCollectionValue RangeAll() + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } + return new Range(this, false, default, false, default, Direction.Forwards); + } + - IDirectedEnumerable ISorted.RangeFrom(T bot) { return RangeFrom(bot); } + IDirectedEnumerable ISorted.RangeFrom(T bot) { return RangeFrom(bot); } - IDirectedEnumerable ISorted.RangeFromTo(T bot, T top) { return RangeFromTo(bot, top); } + IDirectedEnumerable ISorted.RangeFromTo(T bot, T top) { return RangeFromTo(bot, top); } - IDirectedEnumerable ISorted.RangeTo(T top) { return RangeTo(top); } + IDirectedEnumerable ISorted.RangeTo(T top) { return RangeTo(top); } - //Utility for CountXxxx. Actually always called with strict = true. - private int CountTo(T item, bool strict) + //Utility for CountXxxx. Actually always called with strict = true. + private int CountTo(T item, bool strict) + { + if (isSnapShot) { - if (isSnapShot) - { - throw new NotSupportedException("Indexing not supported for snapshots"); - } + throw new NotSupportedException("Indexing not supported for snapshots"); + } - int ind = 0; Node? next = root; + int ind = 0; Node? next = root; - while (next != null) + while (next != null) + { + int comp = comparer!.Compare(item, next.item); + if (comp < 0) + { + next = next.left; + } + else { - int comp = comparer!.Compare(item, next.item); - if (comp < 0) + int leftcnt = next.left == null ? 0 : next.left.size; + + if (comp == 0) { - next = next.left; + return strict ? ind + leftcnt : ind + leftcnt + 1; } else { - int leftcnt = next.left == null ? 0 : next.left.size; - - if (comp == 0) - { - return strict ? ind + leftcnt : ind + leftcnt + 1; - } - else - { - ind = ind + 1 + leftcnt; - next = next.right; - } - + ind = ind + 1 + leftcnt; + next = next.right; } + } + } + + //if we get here, we are at the same side of the whole collection: + return ind; + + } - //if we get here, we are at the same side of the whole collection: - return ind; + /// + /// Perform a search in the sorted collection for the ranges in which a + /// non-increasing (i.e. weakly decreasing) function from the item type to + /// int is + /// negative, zero respectively positive. If the supplied cut function is + /// not non-increasing, the result of this call is undefined. + /// + /// The cut function T to int, given + /// as an IComparable<T> object, where the cut function is + /// the c.CompareTo(T that) method. + /// Returns the largest item in the collection, where the + /// cut function is positive (if any). + /// True if the cut function is positive somewhere + /// on this collection. + /// Returns the least item in the collection, where the + /// cut function is negative (if any). + /// True if the cut function is negative somewhere + /// on this collection. + /// + public bool Cut(IComparable c, out T low, out bool lowIsValid, out T high, out bool highIsValid) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } + Node? cursor = root, lbest = null, rbest = null; + bool res = false; - /// - /// Perform a search in the sorted collection for the ranges in which a - /// non-increasing (i.e. weakly decreasing) function from the item type to - /// int is - /// negative, zero respectively positive. If the supplied cut function is - /// not non-increasing, the result of this call is undefined. - /// - /// The cut function T to int, given - /// as an IComparable<T> object, where the cut function is - /// the c.CompareTo(T that) method. - /// Returns the largest item in the collection, where the - /// cut function is positive (if any). - /// True if the cut function is positive somewhere - /// on this collection. - /// Returns the least item in the collection, where the - /// cut function is negative (if any). - /// True if the cut function is negative somewhere - /// on this collection. - /// - public bool Cut(IComparable c, out T low, out bool lowIsValid, out T high, out bool highIsValid) + while (cursor != null) { - if (!isValid) + int comp = c.CompareTo(cursor.item); + + if (comp > 0) { - throw new ViewDisposedException("Snapshot has been disposed"); + lbest = cursor; + cursor = Right(cursor); } - - Node? cursor = root, lbest = null, rbest = null; - bool res = false; - - while (cursor != null) + else if (comp < 0) { - int comp = c.CompareTo(cursor.item); + rbest = cursor; + cursor = Left(cursor); + } + else + { + res = true; - if (comp > 0) - { - lbest = cursor; - cursor = Right(cursor); - } - else if (comp < 0) + Node tmp = Left(cursor); + + while (tmp != null && c.CompareTo(tmp.item) == 0) { - rbest = cursor; - cursor = Left(cursor); + tmp = Left(tmp); } - else - { - res = true; - - Node tmp = Left(cursor); - while (tmp != null && c.CompareTo(tmp.item) == 0) - { - tmp = Left(tmp); - } - - if (tmp != null) + if (tmp != null) + { + lbest = tmp; + tmp = Right(tmp); + while (tmp != null) { - lbest = tmp; - tmp = Right(tmp); - while (tmp != null) + if (c.CompareTo(tmp.item) > 0) { - if (c.CompareTo(tmp.item) > 0) - { - lbest = tmp; - tmp = Right(tmp); - } - else - { - tmp = Left(tmp); - } + lbest = tmp; + tmp = Right(tmp); + } + else + { + tmp = Left(tmp); } } + } - tmp = Right(cursor); - while (tmp != null && c.CompareTo(tmp.item) == 0) - { - tmp = Right(tmp); - } + tmp = Right(cursor); + while (tmp != null && c.CompareTo(tmp.item) == 0) + { + tmp = Right(tmp); + } - if (tmp != null) + if (tmp != null) + { + rbest = tmp; + tmp = Left(tmp); + while (tmp != null) { - rbest = tmp; - tmp = Left(tmp); - while (tmp != null) + if (c.CompareTo(tmp.item) < 0) { - if (c.CompareTo(tmp.item) < 0) - { - rbest = tmp; - tmp = Left(tmp); - } - else - { - tmp = Right(tmp); - } + rbest = tmp; + tmp = Left(tmp); + } + else + { + tmp = Right(tmp); } } - - break; } - } - if (highIsValid = (rbest != null)) - { - high = rbest!.item; - } - else - { - high = default; + break; } + } - if (lowIsValid = (lbest != null)) - { - low = lbest!.item; - } - else - { - low = default; - } + if (highIsValid = (rbest != null)) + { + high = rbest!.item; + } + else + { + high = default; + } - return res; + if (lowIsValid = (lbest != null)) + { + low = lbest!.item; + } + else + { + low = default; } + return res; + } - /// - /// Determine the number of items at or above a supplied threshold. - /// - /// The lower bound (inclusive) - /// The number of matching items. - public int CountFrom(T bot) - { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - return size - CountTo(bot, true); + /// + /// Determine the number of items at or above a supplied threshold. + /// + /// The lower bound (inclusive) + /// The number of matching items. + public int CountFrom(T bot) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } + return size - CountTo(bot, true); + } - /// - /// Determine the number of items between two supplied thresholds. - /// - /// The lower bound (inclusive) - /// The upper bound (exclusive) - /// The number of matching items. - public int CountFromTo(T bot, T top) - { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - if (comparer!.Compare(bot, top) >= 0) - { - return 0; - } + /// + /// Determine the number of items between two supplied thresholds. + /// + /// The lower bound (inclusive) + /// The upper bound (exclusive) + /// The number of matching items. + public int CountFromTo(T bot, T top) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); + } - return CountTo(top, true) - CountTo(bot, true); + if (comparer!.Compare(bot, top) >= 0) + { + return 0; } + return CountTo(top, true) - CountTo(bot, true); + } - /// - /// Determine the number of items below a supplied threshold. - /// - /// The upper bound (exclusive) - /// The number of matching items. - public int CountTo(T top) - { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } - return CountTo(top, true); + /// + /// Determine the number of items below a supplied threshold. + /// + /// The upper bound (exclusive) + /// The number of matching items. + public int CountTo(T top) + { + if (!isValid) + { + throw new ViewDisposedException("Snapshot has been disposed"); } + return CountTo(top, true); + } + - /// - /// Remove all items of this collection above or at a supplied threshold. - /// - /// The lower threshold (inclusive). - public void RemoveRangeFrom(T low) + /// + /// Remove all items of this collection above or at a supplied threshold. + /// + /// The lower threshold (inclusive). + public void RemoveRangeFrom(T low) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - UpdateCheck(); + UpdateCheck(); - int count = CountFrom(low); + int count = CountFrom(low); - if (count == 0) - { - return; - } + if (count == 0) + { + return; + } - StackCheck(); - CircularQueue? wasRemoved = (ActiveEvents & EventType.Removed) != 0 ? new CircularQueue() : null; + StackCheck(); + CircularQueue? wasRemoved = (ActiveEvents & EventType.Removed) != 0 ? new CircularQueue() : null; - for (int i = 0; i < count; i++) - { - T item = DeleteMaxInner(); - wasRemoved?.Enqueue(item); - } - if (wasRemoved != null) - { - RaiseForRemoveAll(wasRemoved); - } - else if ((ActiveEvents & EventType.Changed) != 0) - { - RaiseCollectionChanged(); - } + for (int i = 0; i < count; i++) + { + T item = DeleteMaxInner(); + wasRemoved?.Enqueue(item); + } + if (wasRemoved != null) + { + RaiseForRemoveAll(wasRemoved); + } + else if ((ActiveEvents & EventType.Changed) != 0) + { + RaiseCollectionChanged(); } + } - /// - /// Remove all items of this collection between two supplied thresholds. - /// - /// The lower threshold (inclusive). - /// The upper threshold (exclusive). - public void RemoveRangeFromTo(T low, T hi) + /// + /// Remove all items of this collection between two supplied thresholds. + /// + /// The lower threshold (inclusive). + /// The upper threshold (exclusive). + public void RemoveRangeFromTo(T low, T hi) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - UpdateCheck(); + UpdateCheck(); - int count = CountFromTo(low, hi); + int count = CountFromTo(low, hi); - if (count == 0) - { - return; - } + if (count == 0) + { + return; + } - CircularQueue? wasRemoved = (ActiveEvents & EventType.Removed) != 0 ? new CircularQueue() : null; - for (int i = 0; i < count; i++) - { - T item = Predecessor(hi); - RemoveIterative(ref item, out _); - wasRemoved?.Enqueue(item); - } - if (wasRemoved != null) - { - RaiseForRemoveAll(wasRemoved); - } - else if ((ActiveEvents & EventType.Changed) != 0) - { - RaiseCollectionChanged(); - } + CircularQueue? wasRemoved = (ActiveEvents & EventType.Removed) != 0 ? new CircularQueue() : null; + for (int i = 0; i < count; i++) + { + T item = Predecessor(hi); + RemoveIterative(ref item, out _); + wasRemoved?.Enqueue(item); + } + if (wasRemoved != null) + { + RaiseForRemoveAll(wasRemoved); } + else if ((ActiveEvents & EventType.Changed) != 0) + { + RaiseCollectionChanged(); + } + } - /// - /// Remove all items of this collection below a supplied threshold. - /// - /// The upper threshold (exclusive). - public void RemoveRangeTo(T hi) + /// + /// Remove all items of this collection below a supplied threshold. + /// + /// The upper threshold (exclusive). + public void RemoveRangeTo(T hi) + { + if (!isValid) { - if (!isValid) - { - throw new ViewDisposedException("Snapshot has been disposed"); - } + throw new ViewDisposedException("Snapshot has been disposed"); + } - UpdateCheck(); + UpdateCheck(); - int count = CountTo(hi); + int count = CountTo(hi); - if (count == 0) - { - return; - } + if (count == 0) + { + return; + } - StackCheck(); - CircularQueue? wasRemoved = (ActiveEvents & EventType.Removed) != 0 ? new CircularQueue() : null; + StackCheck(); + CircularQueue? wasRemoved = (ActiveEvents & EventType.Removed) != 0 ? new CircularQueue() : null; - for (int i = 0; i < count; i++) - { - T item = DeleteMinInner(); - wasRemoved?.Enqueue(item); - } - if (wasRemoved != null) - { - RaiseForRemoveAll(wasRemoved); - } - else if ((ActiveEvents & EventType.Changed) != 0) - { - RaiseCollectionChanged(); - } + for (int i = 0; i < count; i++) + { + T item = DeleteMinInner(); + wasRemoved?.Enqueue(item); + } + if (wasRemoved != null) + { + RaiseForRemoveAll(wasRemoved); + } + else if ((ActiveEvents & EventType.Changed) != 0) + { + RaiseCollectionChanged(); } + } - #endregion + #endregion - #region IPersistent Members - private int MaxSnapId => snapList == null ? -1 : FindLastLiveSnapShot(); + #region IPersistent Members + private int MaxSnapId => snapList == null ? -1 : FindLastLiveSnapShot(); - private int FindLastLiveSnapShot() + private int FindLastLiveSnapShot() + { + if (snapList == null) { - if (snapList == null) - { - return -1; - } - - SnapRef? lastLiveSnapRef = snapList.Prev; - object? _snapshot = null; - while (lastLiveSnapRef != null && (_snapshot = lastLiveSnapRef.Tree.Target) == null) - { - lastLiveSnapRef = lastLiveSnapRef.Prev; - } - - if (lastLiveSnapRef == null) - { - snapList = null; - return -1; - } - if (snapList.Prev != lastLiveSnapRef) - { - snapList.Prev = lastLiveSnapRef; - lastLiveSnapRef.Next = snapList; - } - return ((TreeSet)_snapshot!).generation; + return -1; } - private class SnapRef + SnapRef? lastLiveSnapRef = snapList.Prev; + object? _snapshot = null; + while (lastLiveSnapRef != null && (_snapshot = lastLiveSnapRef.Tree.Target) == null) { - public SnapRef? Prev, Next; - public WeakReference Tree; - public SnapRef(TreeSet tree) { Tree = new WeakReference(tree); } - public void Dispose() - { - Next!.Prev = Prev; - if (Prev != null) - { - Prev.Next = Next; - } + lastLiveSnapRef = lastLiveSnapRef.Prev; + } - Next = Prev = null; - } + if (lastLiveSnapRef == null) + { + snapList = null; + return -1; } + if (snapList.Prev != lastLiveSnapRef) + { + snapList.Prev = lastLiveSnapRef; + lastLiveSnapRef.Next = snapList; + } + return ((TreeSet)_snapshot!).generation; + } - /// - /// If this tree is a snapshot, remove registration in base tree - /// + private class SnapRef + { + public SnapRef? Prev, Next; + public WeakReference Tree; + public SnapRef(TreeSet tree) { Tree = new WeakReference(tree); } public void Dispose() { - if (!isValid) + Next!.Prev = Prev; + if (Prev != null) { - return; + Prev.Next = Next; } - if (isSnapShot) - { - snapList!.Dispose(); - SnapDispose(); - } - else + Next = Prev = null; + } + } + + /// + /// If this tree is a snapshot, remove registration in base tree + /// + public void Dispose() + { + if (!isValid) + { + return; + } + + if (isSnapShot) + { + snapList!.Dispose(); + SnapDispose(); + } + else + { + if (snapList != null) { - if (snapList != null) + SnapRef someSnapRef = snapList.Prev!; + while (someSnapRef != null) { - SnapRef someSnapRef = snapList.Prev!; - while (someSnapRef != null) + if (someSnapRef.Tree.Target is TreeSet lastsnap) { - if (someSnapRef.Tree.Target is TreeSet lastsnap) - { - lastsnap.SnapDispose(); - } - - someSnapRef = someSnapRef.Prev!; + lastsnap.SnapDispose(); } + + someSnapRef = someSnapRef.Prev!; } - snapList = null; - Clear(); } - + snapList = null; + Clear(); } - private void SnapDispose() + } + + private void SnapDispose() + { + root = null; + dirs = null; + path = null; + comparer = null; + isValid = false; + snapList = null; + } + + /// + /// Make a (read-only) snapshot of this collection. + /// + /// The snapshot. + public ISorted Snapshot() + { + if (isSnapShot) { - root = null; - dirs = null; - path = null; - comparer = null; - isValid = false; - snapList = null; + throw new InvalidOperationException("Cannot snapshot a snapshot"); } - /// - /// Make a (read-only) snapshot of this collection. - /// - /// The snapshot. - public ISorted Snapshot() - { - if (isSnapShot) - { - throw new InvalidOperationException("Cannot snapshot a snapshot"); - } + TreeSet res = (TreeSet)MemberwiseClone(); + SnapRef newSnapRef = new(res); + res.isReadOnlyBase = true; + res.isSnapShot = true; + res.snapList = newSnapRef; - TreeSet res = (TreeSet)MemberwiseClone(); - SnapRef newSnapRef = new SnapRef(res); - res.isReadOnlyBase = true; - res.isSnapShot = true; - res.snapList = newSnapRef; + FindLastLiveSnapShot(); + snapList ??= new SnapRef(this); - FindLastLiveSnapShot(); - snapList ??= new SnapRef(this); + SnapRef lastLiveSnapRef = snapList.Prev!; - SnapRef lastLiveSnapRef = snapList.Prev!; + newSnapRef.Prev = lastLiveSnapRef; + if (lastLiveSnapRef != null) + { + lastLiveSnapRef.Next = newSnapRef; + } - newSnapRef.Prev = lastLiveSnapRef; - if (lastLiveSnapRef != null) - { - lastLiveSnapRef.Next = newSnapRef; - } + newSnapRef.Next = snapList; + snapList.Prev = newSnapRef; - newSnapRef.Next = snapList; - snapList.Prev = newSnapRef; + generation++; - generation++; + return res; + } - return res; - } + #endregion - #endregion + #region TreeSet.Range nested class - #region TreeSet.Range nested class + internal class Range : DirectedCollectionValueBase, IDirectedCollectionValue + { + private int stamp; + private readonly int size; + private readonly TreeSet basis; - internal class Range : DirectedCollectionValueBase, IDirectedCollectionValue - { - private int stamp; - private readonly int size; - private readonly TreeSet basis; + private readonly T lowend, highend; - private readonly T lowend, highend; + private readonly bool haslowend, hashighend; + private Direction direction; - private readonly bool haslowend, hashighend; - private Direction direction; + public Range(TreeSet basis, bool haslowend, T lowend, bool hashighend, T highend, Direction direction) + { + this.basis = basis; + stamp = basis.stamp; - public Range(TreeSet basis, bool haslowend, T lowend, bool hashighend, T highend, Direction direction) + //lowind will be const; should we cache highind? + this.lowend = lowend; //Inclusive + this.highend = highend;//Exclusive + this.haslowend = haslowend; + this.hashighend = hashighend; + this.direction = direction; + if (!basis.isSnapShot) { - this.basis = basis; - stamp = basis.stamp; - - //lowind will be const; should we cache highind? - this.lowend = lowend; //Inclusive - this.highend = highend;//Exclusive - this.haslowend = haslowend; - this.hashighend = hashighend; - this.direction = direction; - if (!basis.isSnapShot) - { - size = haslowend ? - (hashighend ? basis.CountFromTo(lowend, highend) : basis.CountFrom(lowend)) : - (hashighend ? basis.CountTo(highend) : basis.Count); - } + size = haslowend ? + (hashighend ? basis.CountFromTo(lowend, highend) : basis.CountFrom(lowend)) : + (hashighend ? basis.CountTo(highend) : basis.Count); } + } - #region IEnumerable Members + #region IEnumerable Members - #region TreeSet.Range.Enumerator nested class + #region TreeSet.Range.Enumerator nested class - internal class Enumerator : SCG.IEnumerator - { - #region Private Fields - private bool valid = false, ready = true; + internal class Enumerator : SCG.IEnumerator + { + #region Private Fields + private bool valid = false, ready = true; + + private SCG.IComparer? comparer; + + private T current; - private SCG.IComparer? comparer; - private T current; + private Node? cursor; + + private Node[]? path; // stack of nodes + private int level = 0; - private Node? cursor; + private Range? range; - private Node[]? path; // stack of nodes + private readonly bool forwards; - private int level = 0; + #endregion + public Enumerator(Range range) + { + comparer = range.basis.comparer; + path = new Node[2 * range.basis.blackdepth]; + this.range = range; + forwards = range.direction == Direction.Forwards; + cursor = new Node(); + if (forwards) + { + cursor.right = range.basis.root; + } + else + { + cursor.left = range.basis.root; + } - private Range? range; + range.basis.ModifyCheck(range.stamp); + } - private readonly bool forwards; + private int Compare(T i1, T i2) + { + return comparer!.Compare(i1, i2); + } - #endregion - public Enumerator(Range range) + /// + /// Undefined if enumerator is not valid (MoveNext hash been called returning true) + /// + /// The current value of the enumerator. + public T Current + { + get { - comparer = range.basis.comparer; - path = new Node[2 * range.basis.blackdepth]; - this.range = range; - forwards = range.direction == Direction.Forwards; - cursor = new Node(); - if (forwards) + if (valid) { - cursor.right = range.basis.root; + return current; } else { - cursor.left = range.basis.root; + throw new InvalidOperationException(); } - - range.basis.ModifyCheck(range.stamp); } + } - private int Compare(T i1, T i2) - { - return comparer!.Compare(i1, i2); - } - /// - /// Undefined if enumerator is not valid (MoveNext hash been called returning true) - /// - /// The current value of the enumerator. - public T Current + //Maintain a stack of nodes that are roots of + //subtrees not completely exported yet. Invariant: + //The stack nodes together with their right subtrees + //consists of exactly the items we have not passed + //yet (the top of the stack holds current item). + /// + /// Move enumerator to next item in tree, or the first item if + /// this is the first call to MoveNext. + /// if underlying tree was modified. + /// + /// True if enumerator is valid now + public bool MoveNext() + { + range!.basis.ModifyCheck(range.stamp); + if (!ready) { - get - { - if (valid) - { - return current; - } - else - { - throw new InvalidOperationException(); - } - } + return false; } - - //Maintain a stack of nodes that are roots of - //subtrees not completely exported yet. Invariant: - //The stack nodes together with their right subtrees - //consists of exactly the items we have not passed - //yet (the top of the stack holds current item). - /// - /// Move enumerator to next item in tree, or the first item if - /// this is the first call to MoveNext. - /// if underlying tree was modified. - /// - /// True if enumerator is valid now - public bool MoveNext() + if (forwards) { - range!.basis.ModifyCheck(range.stamp); - if (!ready) - { - return false; - } - - if (forwards) + if (!valid && range.haslowend) { - if (!valid && range.haslowend) + cursor = cursor!.right; + while (cursor != null) { - cursor = cursor!.right; - while (cursor != null) + int comp = Compare(cursor.item, range.lowend); + + if (comp > 0) { - int comp = Compare(cursor.item, range.lowend); - - if (comp > 0) - { - path![level++] = cursor; - cursor = range.basis.Left(cursor); - - } - else if (comp < 0) - { - cursor = range.basis.Right(cursor); - - } - else - { - path![level] = cursor; - break; - } + path![level++] = cursor; + cursor = range.basis.Left(cursor); + } + else if (comp < 0) + { + cursor = range.basis.Right(cursor); - if (cursor == null) + } + else { - if (level == 0) - { - return valid = ready = false; - } - else - { - cursor = path![--level]; - } + path![level] = cursor; + break; } } - else if (range.basis.Right(cursor!) != null) - { - path![level] = cursor = range.basis.Right(cursor!); - Node next = range.basis.Left(cursor); - - while (next != null) + if (cursor == null) + { + if (level == 0) { - path[++level] = cursor = next; - next = range.basis.Left(cursor); + return valid = ready = false; + } + else + { + cursor = path![--level]; } } + } + else if (range.basis.Right(cursor!) != null) + { + path![level] = cursor = range.basis.Right(cursor!); - else if (level == 0) - { - return valid = ready = false; - } - else - { - cursor = path![--level]; - } + Node next = range.basis.Left(cursor); - current = cursor.item; - if (range.hashighend && Compare(current, range.highend) >= 0) + while (next != null) { - return valid = ready = false; + path[++level] = cursor = next; + next = range.basis.Left(cursor); } + } - return valid = true; + else if (level == 0) + { + return valid = ready = false; } else { - if (!valid && range.hashighend) - { - cursor = cursor!.left; - while (cursor != null) - { - int comp = Compare(cursor.item, range.highend); + cursor = path![--level]; + } - if (comp < 0) - { - path![level++] = cursor; - cursor = range.basis.Right(cursor); + current = cursor.item; + if (range.hashighend && Compare(current, range.highend) >= 0) + { + return valid = ready = false; + } - } - else - { - cursor = range.basis.Left(cursor); + return valid = true; + } + else + { + if (!valid && range.hashighend) + { + cursor = cursor!.left; + while (cursor != null) + { + int comp = Compare(cursor.item, range.highend); - } - } + if (comp < 0) + { + path![level++] = cursor; + cursor = range.basis.Right(cursor); - if (cursor == null) + } + else { - if (level == 0) - { - return valid = ready = false; - } - else - { - cursor = path![--level]; - } + cursor = range.basis.Left(cursor); + } } - else if (range.basis.Left(cursor!) != null) - { - path![level] = cursor = range.basis.Left(cursor!); - - Node next = range.basis.Right(cursor); - while (next != null) + if (cursor == null) + { + if (level == 0) + { + return valid = ready = false; + } + else { - path[++level] = cursor = next; - next = range.basis.Right(cursor); + cursor = path![--level]; } } + } + else if (range.basis.Left(cursor!) != null) + { + path![level] = cursor = range.basis.Left(cursor!); - else if (level == 0) - { - return valid = ready = false; - } - else - { - cursor = path![--level]; - } + Node next = range.basis.Right(cursor); - current = cursor.item; - if (range.haslowend && Compare(current, range.lowend) < 0) + while (next != null) { - return valid = ready = false; + path[++level] = cursor = next; + next = range.basis.Right(cursor); } + } - return valid = true; + else if (level == 0) + { + return valid = ready = false; + } + else + { + cursor = path![--level]; } - } + current = cursor.item; + if (range.haslowend && Compare(current, range.lowend) < 0) + { + return valid = ready = false; + } - public void Dispose() - { - comparer = null; - current = default; - cursor = null; - path = null; - range = null; + return valid = true; } + } - #region IEnumerator Members - object System.Collections.IEnumerator.Current => Current!; + public void Dispose() + { + comparer = null; + current = default; + cursor = null; + path = null; + range = null; + } - bool System.Collections.IEnumerator.MoveNext() - { - return MoveNext(); - } + #region IEnumerator Members - void System.Collections.IEnumerator.Reset() - { - throw new NotImplementedException(); - } + object System.Collections.IEnumerator.Current => Current!; - #endregion + bool System.Collections.IEnumerator.MoveNext() + { + return MoveNext(); + } + + void System.Collections.IEnumerator.Reset() + { + throw new NotImplementedException(); } #endregion + } + #endregion - public override T Choose() - { - if (size == 0) - { - throw new NoSuchItemException(); - } - return lowend; + public override T Choose() + { + if (size == 0) + { + throw new NoSuchItemException(); } - public override SCG.IEnumerator GetEnumerator() { return new Enumerator(this); } + return lowend; + } + public override SCG.IEnumerator GetEnumerator() { return new Enumerator(this); } - public override Direction Direction => direction; + public override Direction Direction => direction; - #endregion - #region Utility + #endregion - /* bool inside(T item) - { - return (!haslowend || basis.comparer!.Compare(item, lowend) >= 0) && (!hashighend || basis.comparer!.Compare(item, highend) < 0); - } */ + #region Utility + /* bool inside(T item) + { + return (!haslowend || basis.comparer!.Compare(item, lowend) >= 0) && (!hashighend || basis.comparer!.Compare(item, highend) < 0); + } */ - /* void checkstamp() - { - if (stamp < basis.stamp) - throw new CollectionModifiedException(); - } */ + /* void checkstamp() + { + if (stamp < basis.stamp) + throw new CollectionModifiedException(); + } */ - // void syncstamp() { stamp = basis.stamp; } - #endregion + // void syncstamp() { stamp = basis.stamp; } - public override IDirectedCollectionValue Backwards() - { - Range b = (Range)MemberwiseClone(); + #endregion - b.direction = direction == Direction.Forwards ? Direction.Backwards : Direction.Forwards; - return b; - } + public override IDirectedCollectionValue Backwards() + { + Range b = (Range)MemberwiseClone(); + + b.direction = direction == Direction.Forwards ? Direction.Backwards : Direction.Forwards; + return b; + } - IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } + IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } - public override bool IsEmpty => size == 0; + public override bool IsEmpty => size == 0; - public override int Count => size; + public override int Count => size; - //TODO: check that this is correct - public override Speed CountSpeed => Speed.Constant; + //TODO: check that this is correct + public override Speed CountSpeed => Speed.Constant; - } + } - #endregion + #endregion - #region Diagnostics - /// - /// Display this node on the console, and recursively its subnodes. - /// - /// Node to display - /// Indentation - private void MiniDump(Node? n, string space) + #region Diagnostics + /// + /// Display this node on the console, and recursively its subnodes. + /// + /// Node to display + /// Indentation + private void MiniDump(Node? n, string space) + { + if (n == null) { - if (n == null) - { - // System.Logger.Log(space + "null"); - } - else - { - MiniDump(n.right, space + " "); - Logger.Log(string.Format("{0} {4} (size={1}, items={8}, h={2}, gen={3}, id={6}){7}", space + n.item, - n.size, + // System.Logger.Log(space + "null"); + } + else + { + MiniDump(n.right, space + " "); + Logger.Log(string.Format("{0} {4} (size={1}, items={8}, h={2}, gen={3}, id={6}){7}", space + n.item, +n.size, - 0, - n.generation, - n.red ? "RED" : "BLACK", - 0, - 0, +0, +n.generation, +n.red ? "RED" : "BLACK", + 0, + 0, - n.lastgeneration == -1 ? "" : string.Format(" [extra: lg={0}, c={1}, i={2}]", n.lastgeneration, n.leftnode ? "L" : "R", n.oldref == null ? "()" : "" + n.oldref.item), +n.lastgeneration == -1 ? "" : string.Format(" [extra: lg={0}, c={1}, i={2}]", n.lastgeneration, n.leftnode ? "L" : "R", n.oldref == null ? "()" : "" + n.oldref.item), - 1 +1 )); - MiniDump(n.left, space + " "); - } + MiniDump(n.left, space + " "); } + } - /// - /// Print the tree structure to the console stdout. - /// - public void Dump() { Dump(""); } + /// + /// Print the tree structure to the console stdout. + /// + public void Dump() { Dump(""); } - /// - /// Print the tree structure to the console stdout. - /// - public void Dump(string msg) - { - Logger.Log(string.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4})", msg, size, blackdepth, - 0 - , - generation + /// + /// Print the tree structure to the console stdout. + /// + public void Dump(string msg) + { + Logger.Log(string.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4})", msg, size, blackdepth, + 0 + , +generation )); - MiniDump(root, ""); - CheckInner(); - Logger.Log("<<<<<<<<<<<<<<<<<<<"); - } + MiniDump(root, ""); + CheckInner(); + Logger.Log("<<<<<<<<<<<<<<<<<<<"); + } - /// - /// Display this tree on the console. - /// - /// Identifying string of this call to dump - /// Extra (error)message to include - private void Dump(string msg, string err) - { - Logger.Log(string.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4})", msg, size, blackdepth, - 0 - , - generation + /// + /// Display this tree on the console. + /// + /// Identifying string of this call to dump + /// Extra (error)message to include + private void Dump(string msg, string err) + { + Logger.Log(string.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4})", msg, size, blackdepth, + 0 + , +generation )); - MiniDump(root, ""); Logger.Log(err); - Logger.Log("<<<<<<<<<<<<<<<<<<<"); - } + MiniDump(root, ""); Logger.Log(err); + Logger.Log("<<<<<<<<<<<<<<<<<<<"); + } - /// - /// Print warning m on logger if b is false. - /// - /// Condition that should hold - /// Place (used for id display) - /// Message - /// b - private bool Massert(bool b, Node n, string m) + /// + /// Print warning m on logger if b is false. + /// + /// Condition that should hold + /// Place (used for id display) + /// Message + /// b + private bool Massert(bool b, Node n, string m) + { + if (!b) { - if (!b) - { - Logger.Log(string.Format("*** Node (item={0}, id={1}): {2}", n.item, - 0 - , m)); - } - - return b; + Logger.Log(string.Format("*** Node (item={0}, id={1}): {2}", n.item, + 0 + , m)); } - private bool RbMiniCheck(Node n, bool redp, out T min, out T max, out int blackheight) - {//Red-Black invariant - bool res = true; - - res = Massert(!(n.red && redp), n, "RED parent of RED node") && res; - res = Massert(n.left == null || n.right != null || n.left.red, n, "Left child black, but right child empty") && res; - res = Massert(n.right == null || n.left != null || n.right.red, n, "Right child black, but left child empty") && res; - bool sb = n.size == (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1; + return b; + } - res = Massert(sb, n, "Bad size") && res; - min = max = n.item; + private bool RbMiniCheck(Node n, bool redp, out T min, out T max, out int blackheight) + {//Red-Black invariant + bool res = true; - T otherext; - int lbh = 0, rbh = 0; + res = Massert(!(n.red && redp), n, "RED parent of RED node") && res; + res = Massert(n.left == null || n.right != null || n.left.red, n, "Left child black, but right child empty") && res; + res = Massert(n.right == null || n.left != null || n.right.red, n, "Right child black, but left child empty") && res; + bool sb = n.size == (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1; - if (n.left != null) - { - res = RbMiniCheck(n.left, n.red, out min, out otherext, out lbh) && res; - res = Massert(comparer!.Compare(n.item, otherext) > 0, n, "Value not > all left children") && res; - } + res = Massert(sb, n, "Bad size") && res; + min = max = n.item; - if (n.right != null) - { - res = RbMiniCheck(n.right, n.red, out otherext, out max, out rbh) && res; - res = Massert(comparer!.Compare(n.item, otherext) < 0, n, "Value not < all right children") && res; - } + T otherext; + int lbh = 0, rbh = 0; - res = Massert(rbh == lbh, n, "Different blackheights of children") && res; - blackheight = n.red ? rbh : rbh + 1; - return res; + if (n.left != null) + { + res = RbMiniCheck(n.left, n.red, out min, out otherext, out lbh) && res; + res = Massert(comparer!.Compare(n.item, otherext) > 0, n, "Value not > all left children") && res; } - private bool RbMiniSnapCheck(Node n, out int size, out T min, out T max) + if (n.right != null) { - bool res = true; + res = RbMiniCheck(n.right, n.red, out otherext, out max, out rbh) && res; + res = Massert(comparer!.Compare(n.item, otherext) < 0, n, "Value not < all right children") && res; + } - min = max = n.item; + res = Massert(rbh == lbh, n, "Different blackheights of children") && res; + blackheight = n.red ? rbh : rbh + 1; + return res; + } - int lsz = 0, rsz = 0; - T otherext; + private bool RbMiniSnapCheck(Node n, out int size, out T min, out T max) + { + bool res = true; - Node? child = (n.lastgeneration >= generation && n.leftnode) ? n.oldref : n.left; - if (child != null) - { - res = RbMiniSnapCheck(child, out lsz, out min, out otherext) && res; - res = Massert(comparer!.Compare(n.item, otherext) > 0, n, "Value not > all left children") && res; - } + min = max = n.item; + int lsz = 0, rsz = 0; + T otherext; - child = (n.lastgeneration >= generation && !n.leftnode) ? n.oldref : n.right; - if (child != null) - { - res = RbMiniSnapCheck(child, out rsz, out otherext, out max) && res; - res = Massert(comparer!.Compare(n.item, otherext) < 0, n, "Value not < all right children") && res; - } + Node? child = (n.lastgeneration >= generation && n.leftnode) ? n.oldref : n.left; + if (child != null) + { + res = RbMiniSnapCheck(child, out lsz, out min, out otherext) && res; + res = Massert(comparer!.Compare(n.item, otherext) > 0, n, "Value not > all left children") && res; + } - size = 1 + lsz + rsz; - return res; + child = (n.lastgeneration >= generation && !n.leftnode) ? n.oldref : n.right; + if (child != null) + { + res = RbMiniSnapCheck(child, out rsz, out otherext, out max) && res; + res = Massert(comparer!.Compare(n.item, otherext) < 0, n, "Value not < all right children") && res; } - /// - /// Checks red-black invariant. Dumps tree to console if bad - /// - /// Title of dump - /// false if invariant violation - public bool Check(string name) - { - System.Text.StringBuilder e = new System.Text.StringBuilder(); + size = 1 + lsz + rsz; - if (!CheckInner()) - { - return true; - } - else - { - Dump(name, e.ToString()); - return false; - } - } + return res; + } + /// + /// Checks red-black invariant. Dumps tree to console if bad + /// + /// Title of dump + /// false if invariant violation + public bool Check(string name) + { + System.Text.StringBuilder e = new(); - /// - /// Checks red-black invariant. Dumps tree to console if bad - /// - /// false if invariant violation - public bool Check() + if (!CheckInner()) { - //return check(""); - //Logger.Log("bamse"); - if (!isValid) - { - return true; - } + return true; + } + else + { + Dump(name, e.ToString()); + return false; + } + } - return Check("-"); + + /// + /// Checks red-black invariant. Dumps tree to console if bad + /// + /// false if invariant violation + public bool Check() + { + //return check(""); + //Logger.Log("bamse"); + if (!isValid) + { + return true; } - private bool CheckInner() + return Check("-"); + } + + private bool CheckInner() + { + if (root != null) { - if (root != null) + if (isSnapShot) { - if (isSnapShot) - { - //Logger.Log("Im'a snapshot"); - bool rv = RbMiniSnapCheck(root, out int thesize, out _, out _); + //Logger.Log("Im'a snapshot"); + bool rv = RbMiniSnapCheck(root, out int thesize, out _, out _); - rv = Massert(size == thesize, root, "bad snapshot size") && rv; - return !rv; - } - bool res = RbMiniCheck(root, false, out _, out _, out int blackheight); - res = Massert(blackheight == blackdepth, root, "bad blackh/d") && res; - res = Massert(!root.red, root, "root is red") && res; - res = Massert(root.size == size, root, "count!=root.size") && res; - return !res; - } - else - { - return false; + rv = Massert(size == thesize, root, "bad snapshot size") && rv; + return !rv; } + bool res = RbMiniCheck(root, false, out _, out _, out int blackheight); + res = Massert(blackheight == blackdepth, root, "bad blackh/d") && res; + res = Massert(!root.red, root, "root is red") && res; + res = Massert(root.size == size, root, "count!=root.size") && res; + return !res; + } + else + { + return false; } - #endregion } + #endregion } diff --git a/C5/WeakViewList.cs b/C5/WeakViewList.cs index 50f86358..f01a54cd 100644 --- a/C5/WeakViewList.cs +++ b/C5/WeakViewList.cs @@ -4,72 +4,71 @@ using System; using SCG = System.Collections.Generic; -namespace C5 +namespace C5; + +#region View List Nested class +/// +/// This class is shared between the linked list and array list implementations. +/// +/// +internal class WeakViewList where V : class { - #region View List Nested class - /// - /// This class is shared between the linked list and array list implementations. - /// - /// - internal class WeakViewList where V : class - { - private Node? start; + private Node? start; - internal class Node + internal class Node + { + internal WeakReference weakview; internal Node? prev; internal Node next; + internal Node(V view) { weakview = new WeakReference(view); } + } + internal Node Add(V view) + { + Node newNode = new(view); + if (start != null) { start.prev = newNode; newNode.next = start; } + start = newNode; + return newNode; + } + internal void Remove(Node n) + { + if (n == start) { - internal WeakReference weakview; internal Node? prev; internal Node next; - internal Node(V view) { weakview = new WeakReference(view); } + start = start!.next; if (start != null) + { + start.prev = null; + } } - internal Node Add(V view) + else { - Node newNode = new Node(view); - if (start != null) { start.prev = newNode; newNode.next = start; } - start = newNode; - return newNode; + n.prev!.next = n.next; if (n.next != null) + { + n.next.prev = n.prev; + } } - internal void Remove(Node n) + } + /// + /// Note that it is safe to call views.Remove(view.myWeakReference) if view + /// is the currently yielded object + /// + /// + public SCG.IEnumerator GetEnumerator() + { + Node n = start!; + while (n != null) { - if (n == start) + //V view = n.weakview.Target as V; //This provokes a bug in the beta1 verifyer + object o = n.weakview.Target; + V view = o is V ? (V)o : null; + if (view == null) { - start = start!.next; if (start != null) - { - start.prev = null; - } + Remove(n); } else { - n.prev!.next = n.next; if (n.next != null) - { - n.next.prev = n.prev; - } + yield return view; } - } - /// - /// Note that it is safe to call views.Remove(view.myWeakReference) if view - /// is the currently yielded object - /// - /// - public SCG.IEnumerator GetEnumerator() - { - Node n = start!; - while (n != null) - { - //V view = n.weakview.Target as V; //This provokes a bug in the beta1 verifyer - object o = n.weakview.Target; - V view = o is V ? (V)o : null; - if (view == null) - { - Remove(n); - } - else - { - yield return view; - } - n = n.next; - } + n = n.next; } } +} - #endregion -} \ No newline at end of file +#endregion diff --git a/C5/WrappedArray.cs b/C5/WrappedArray.cs index 4ad8464f..55314744 100644 --- a/C5/WrappedArray.cs +++ b/C5/WrappedArray.cs @@ -4,897 +4,920 @@ using System; using System.Text; using SCG = System.Collections.Generic; -namespace C5 + +namespace C5; + +/// +/// An advanced interface to operations on an array. The array is viewed as an +/// of fixed size, and so all operations that would change the +/// size of the array will be invalid (and throw +/// +/// +public class WrappedArray : IList, SCG.IList { + private class InnerList : ArrayList + { + internal InnerList(T[] array) { this.array = array; size = array.Length; } + } + + private readonly ArrayList innerlist; + + //TODO: remember a ref to the wrapped array in WrappedArray to save a little on indexing? + private readonly WrappedArray? underlying; + + /// + /// + /// + /// + public WrappedArray(T[] wrappedarray) { innerlist = new InnerList(wrappedarray); } + + //for views + private WrappedArray(ArrayList arraylist, WrappedArray underlying) { innerlist = arraylist; this.underlying = underlying; } + + #region IList Members + + /// + /// + /// + /// + public T First => innerlist.First; + + /// + /// + /// + /// + public T Last => innerlist.Last; + /// - /// An advanced interface to operations on an array. The array is viewed as an - /// of fixed size, and so all operations that would change the - /// size of the array will be invalid (and throw + /// /// - /// - public class WrappedArray : IList, SCG.IList + /// + /// + public T this[int index] { - private class InnerList : ArrayList - { - internal InnerList(T[] array) { this.array = array; size = array.Length; } - } + get => innerlist[index]; + set => innerlist[index] = value; + } - private readonly ArrayList innerlist; + /// + /// + /// + /// + /// + public IList FindAll(Func filter) { return innerlist.FindAll(filter); } - //TODO: remember a ref to the wrapped array in WrappedArray to save a little on indexing? - private readonly WrappedArray? underlying; + /// + /// + /// + /// + /// + /// + public IList Map(Func mapper) { return innerlist.Map(mapper); } - /// - /// - /// - /// - public WrappedArray(T[] wrappedarray) { innerlist = new InnerList(wrappedarray); } + /// + /// + /// + /// + /// + /// + /// + public IList Map(Func mapper, SCG.IEqualityComparer equalityComparer) { return innerlist.Map(mapper, equalityComparer); } - //for views - private WrappedArray(ArrayList arraylist, WrappedArray underlying) { innerlist = arraylist; this.underlying = underlying; } + /// + /// ???? should we throw NotRelevantException + /// + /// + public bool FIFO + { + get => throw new FixedSizeCollectionException(); + set => throw new FixedSizeCollectionException(); + } - #region IList Members + /// + /// + /// + public virtual bool IsFixedSize => true; - /// - /// - /// - /// - public T First => innerlist.First; + /// + /// + /// + /// + /// + public void Insert(int index, T item) + { + throw new FixedSizeCollectionException(); + } - /// - /// - /// - /// - public T Last => innerlist.Last; + /// + /// + /// + /// + /// + public void Insert(IList pointer, T item) + { + throw new FixedSizeCollectionException(); + } - /// - /// - /// - /// - /// - public T this[int index] - { - get => innerlist[index]; - set => innerlist[index] = value; - } + /// + /// + /// + /// + public void InsertFirst(T item) + { + throw new FixedSizeCollectionException(); + } - /// - /// - /// - /// - /// - public IList FindAll(Func filter) { return innerlist.FindAll(filter); } - - /// - /// - /// - /// - /// - /// - public IList Map(Func mapper) { return innerlist.Map(mapper); } - - /// - /// - /// - /// - /// - /// - /// - public IList Map(Func mapper, SCG.IEqualityComparer equalityComparer) { return innerlist.Map(mapper, equalityComparer); } - - /// - /// ???? should we throw NotRelevantException - /// - /// - public bool FIFO - { - get => throw new FixedSizeCollectionException(); - set => throw new FixedSizeCollectionException(); - } + /// + /// + /// + /// + public void InsertLast(T item) + { + throw new FixedSizeCollectionException(); + } - /// - /// - /// - public virtual bool IsFixedSize => true; - - /// - /// - /// - /// - /// - public void Insert(int index, T item) - { - throw new FixedSizeCollectionException(); - } + /// + /// + /// + /// + /// + public void InsertAll(int i, System.Collections.Generic.IEnumerable items) + { + throw new FixedSizeCollectionException(); + } - /// - /// - /// - /// - /// - public void Insert(IList pointer, T item) - { - throw new FixedSizeCollectionException(); - } + /// + /// + /// + /// + public T Remove() + { + throw new FixedSizeCollectionException(); + } - /// - /// - /// - /// - public void InsertFirst(T item) - { - throw new FixedSizeCollectionException(); - } + /// + /// + /// + /// + public T RemoveFirst() + { + throw new FixedSizeCollectionException(); + } - /// - /// - /// - /// - public void InsertLast(T item) - { - throw new FixedSizeCollectionException(); - } + /// + /// + /// + /// + public T RemoveLast() + { + throw new FixedSizeCollectionException(); + } - /// - /// - /// - /// - /// - public void InsertAll(int i, System.Collections.Generic.IEnumerable items) - { - throw new FixedSizeCollectionException(); - } + /// + /// + /// + /// + /// + /// + public IList? View(int start, int count) + { + return new WrappedArray((ArrayList)innerlist.View(start, count)!, underlying ?? this); + } - /// - /// - /// - /// - public T Remove() - { - throw new FixedSizeCollectionException(); - } + /// + /// + /// + /// + /// + public IList? ViewOf(T item) + { + return new WrappedArray((ArrayList)innerlist.ViewOf(item)!, underlying ?? this); + } - /// - /// - /// - /// - public T RemoveFirst() - { - throw new FixedSizeCollectionException(); - } + /// + /// + /// + /// + /// + public IList? LastViewOf(T item) + { + return new WrappedArray((ArrayList)innerlist.LastViewOf(item)!, underlying ?? this); + } - /// - /// - /// - /// - public T RemoveLast() - { - throw new FixedSizeCollectionException(); - } + /// + /// + /// + /// + public IList? Underlying => underlying; - /// - /// - /// - /// - /// - /// - public IList? View(int start, int count) - { - return new WrappedArray((ArrayList)innerlist.View(start, count)!, underlying ?? this); - } + /// + /// + /// + /// + public int Offset => innerlist.Offset; - /// - /// - /// - /// - /// - public IList? ViewOf(T item) - { - return new WrappedArray((ArrayList)innerlist.ViewOf(item)!, underlying ?? this); - } + /// + /// + /// + /// + public bool IsValid => innerlist.IsValid; - /// - /// - /// - /// - /// - public IList? LastViewOf(T item) - { - return new WrappedArray((ArrayList)innerlist.LastViewOf(item)!, underlying ?? this); - } + /// + /// + /// + /// + /// + public IList Slide(int offset) { return innerlist.Slide(offset); } - /// - /// - /// - /// - public IList? Underlying => underlying; - - /// - /// - /// - /// - public int Offset => innerlist.Offset; - - /// - /// - /// - /// - public bool IsValid => innerlist.IsValid; - - /// - /// - /// - /// - /// - public IList Slide(int offset) { return innerlist.Slide(offset); } - - /// - /// - /// - /// - /// - /// - public IList Slide(int offset, int size) { return innerlist.Slide(offset, size); } - - /// - /// - /// - /// - /// - public bool TrySlide(int offset) { return innerlist.TrySlide(offset); } - - /// - /// - /// - /// - /// - /// - public bool TrySlide(int offset, int size) { return innerlist.TrySlide(offset, size); } - - /// - /// - /// - /// - /// - public IList? Span(IList otherView) { return innerlist.Span(((WrappedArray)otherView).innerlist); } - - /// - /// - /// - public void Reverse() { innerlist.Reverse(); } - - /// - /// - /// - /// - public bool IsSorted() { return innerlist.IsSorted(); } - - /// - /// - /// - /// - /// - public bool IsSorted(SCG.IComparer comparer) { return innerlist.IsSorted(comparer); } - - /// - /// - /// - public void Sort() { innerlist.Sort(); } - - /// - /// - /// - /// - public void Sort(SCG.IComparer comparer) { innerlist.Sort(comparer); } - - /// - /// - /// - public void Shuffle() { innerlist.Shuffle(); } - - /// - /// - /// - /// - public void Shuffle(Random rnd) { innerlist.Shuffle(rnd); } - - #endregion - - #region IIndexed Members - - /// - /// - /// - /// - public Speed IndexingSpeed => Speed.Constant; - - /// - /// - /// - /// - /// - /// - public IDirectedCollectionValue this[int start, int count] => innerlist[start, count]; - - /// - /// - /// - /// - /// - public int IndexOf(T item) { return innerlist.IndexOf(item); } - - /// - /// - /// - /// - /// - public int LastIndexOf(T item) { return innerlist.LastIndexOf(item); } - - /// - /// - /// - /// - /// - public int FindIndex(Func predicate) { return innerlist.FindIndex(predicate); } - - /// - /// - /// - /// - /// - public int FindLastIndex(Func predicate) { return innerlist.FindLastIndex(predicate); } - - /// - /// - /// - /// - /// - public T RemoveAt(int i) { throw new FixedSizeCollectionException(); } - - /// - /// - /// - /// - /// - public void RemoveInterval(int start, int count) { throw new FixedSizeCollectionException(); } - - #endregion - - #region ISequenced Members - - /// - /// - /// - /// - public int GetSequencedHashCode() { return innerlist.GetSequencedHashCode(); } - - /// - /// - /// - /// - /// - public bool SequencedEquals(ISequenced that) { return innerlist.SequencedEquals(that); } - - #endregion - - #region ICollection Members - /// - /// - /// - /// - public Speed ContainsSpeed => Speed.Linear; - - /// - /// - /// - /// - public int GetUnsequencedHashCode() { return innerlist.GetUnsequencedHashCode(); } - - /// - /// - /// - /// - /// - public bool UnsequencedEquals(ICollection that) { return innerlist.UnsequencedEquals(that); } - - /// - /// - /// - /// - /// - public bool Contains(T item) { return innerlist.Contains(item); } - - /// - /// - /// - /// - /// - public int ContainsCount(T item) { return innerlist.ContainsCount(item); } - - /// - /// - /// - /// - public ICollectionValue UniqueItems() { return innerlist.UniqueItems(); } - - /// - /// - /// - /// - public ICollectionValue> ItemMultiplicities() { return innerlist.ItemMultiplicities(); } - - /// - /// - /// - /// - /// - public bool ContainsAll(System.Collections.Generic.IEnumerable items) - { return innerlist.ContainsAll(items); } - - /// - /// - /// - /// - /// - public bool Find(ref T item) { return innerlist.Find(ref item); } - - /// - /// - /// - /// - /// - public bool FindOrAdd(ref T item) { throw new FixedSizeCollectionException(); } - - /// - /// - /// - /// - /// - public bool Update(T item) { throw new FixedSizeCollectionException(); } - - /// - /// - /// - /// - /// - /// - public bool Update(T item, out T olditem) { throw new FixedSizeCollectionException(); } - - /// - /// - /// - /// - /// - public bool UpdateOrAdd(T item) { throw new FixedSizeCollectionException(); } - - /// - /// - /// - /// - /// - /// - public bool UpdateOrAdd(T item, out T olditem) { throw new FixedSizeCollectionException(); } - - /// - /// - /// - /// - /// - public bool Remove(T item) { throw new FixedSizeCollectionException(); } - - /// - /// - /// - /// - /// - /// - public bool Remove(T item, out T removeditem) { throw new FixedSizeCollectionException(); } - - /// - /// - /// - /// - public void RemoveAllCopies(T item) { throw new FixedSizeCollectionException(); } - - /// - /// - /// - /// - public void RemoveAll(System.Collections.Generic.IEnumerable items) { throw new FixedSizeCollectionException(); } - - /// - /// - /// - public void Clear() { throw new FixedSizeCollectionException(); } - - /// - /// - /// - /// - public void RetainAll(System.Collections.Generic.IEnumerable items) { throw new FixedSizeCollectionException(); } - - #endregion - - #region IExtensible Members - - /// - /// - /// - /// - public bool IsReadOnly => true; - - /// - /// - /// - /// - public bool AllowsDuplicates => true; - - /// - /// - /// - /// - public SCG.IEqualityComparer EqualityComparer => innerlist.EqualityComparer; - - /// - /// - /// - /// - public bool DuplicatesByCounting => false; - - /// - /// - /// - /// - /// - public bool Add(T item) - { - throw new FixedSizeCollectionException(); - } + /// + /// + /// + /// + /// + /// + public IList Slide(int offset, int size) { return innerlist.Slide(offset, size); } - /// - /// - /// - /// - public void AddAll(System.Collections.Generic.IEnumerable items) - { - throw new FixedSizeCollectionException(); - } + /// + /// + /// + /// + /// + public bool TrySlide(int offset) { return innerlist.TrySlide(offset); } - /// - /// - /// - /// - public bool Check() - { - return innerlist.Check() && (underlying == null || underlying.innerlist == innerlist.Underlying); - } + /// + /// + /// + /// + /// + /// + public bool TrySlide(int offset, int size) { return innerlist.TrySlide(offset, size); } - #endregion - - #region ICollectionValue Members - /// - /// No listeners may be installed - /// - /// 0 - public virtual EventType ListenableEvents => 0; - - /// - /// No listeners ever installed - /// - /// 0 - public virtual EventType ActiveEvents => 0; - - /// - /// - /// - /// - public event CollectionChangedHandler CollectionChanged - { - add { throw new UnlistenableEventException(); } - remove { throw new UnlistenableEventException(); } - } + /// + /// + /// + /// + /// + public IList? Span(IList otherView) { return innerlist.Span(((WrappedArray)otherView).innerlist); } - /// - /// - /// - /// - public event CollectionClearedHandler CollectionCleared - { - add { throw new UnlistenableEventException(); } - remove { throw new UnlistenableEventException(); } - } + /// + /// + /// + public void Reverse() { innerlist.Reverse(); } - /// - /// - /// - /// - public event ItemsAddedHandler ItemsAdded - { - add { throw new UnlistenableEventException(); } - remove { throw new UnlistenableEventException(); } - } + /// + /// + /// + /// + public bool IsSorted() { return innerlist.IsSorted(); } - /// - /// - /// - /// - public event ItemInsertedHandler ItemInserted - { - add { throw new UnlistenableEventException(); } - remove { throw new UnlistenableEventException(); } - } + /// + /// + /// + /// + /// + public bool IsSorted(SCG.IComparer comparer) { return innerlist.IsSorted(comparer); } - /// - /// - /// - /// - public event ItemsRemovedHandler ItemsRemoved - { - add { throw new UnlistenableEventException(); } - remove { throw new UnlistenableEventException(); } - } + /// + /// + /// + public void Sort() { innerlist.Sort(); } - /// - /// - /// - /// - public event ItemRemovedAtHandler ItemRemovedAt - { - add { throw new UnlistenableEventException(); } - remove { throw new UnlistenableEventException(); } - } + /// + /// + /// + /// + public void Sort(SCG.IComparer comparer) { innerlist.Sort(comparer); } - /// - /// - /// - /// - public bool IsEmpty => innerlist.IsEmpty; - - /// - /// - /// - /// - public int Count => innerlist.Count; - - /// - /// - /// - /// - public Speed CountSpeed => innerlist.CountSpeed; - - /// - /// - /// - /// - /// - public void CopyTo(T[] array, int index) { innerlist.CopyTo(array, index); } - - /// - /// - /// - /// - public T[] ToArray() { return innerlist.ToArray(); } - - /// - /// - /// - /// - public void Apply(Action action) { innerlist.Apply(action); } - - /// - /// - /// - /// - /// - public bool Exists(Func predicate) { return innerlist.Exists(predicate); } - - /// - /// - /// - /// - /// - /// - public bool Find(Func predicate, out T item) { return innerlist.Find(predicate, out item); } - - /// - /// - /// - /// - /// - public bool All(Func predicate) { return innerlist.All(predicate); } - - /// - /// - /// - /// - public T Choose() { return innerlist.Choose(); } - - /// - /// - /// - /// - /// - public SCG.IEnumerable Filter(Func filter) { return innerlist.Filter(filter); } - - #endregion - - #region IEnumerable Members - - /// - /// - /// - /// - public SCG.IEnumerator GetEnumerator() { return innerlist.GetEnumerator(); } - #endregion - - #region IShowable Members - - /// - /// - /// - /// - /// - /// - /// - public bool Show(StringBuilder stringbuilder, ref int rest, IFormatProvider? formatProvider) - { return innerlist.Show(stringbuilder, ref rest, formatProvider); } - - #endregion - - #region IFormattable Members - - /// - /// - /// - /// - public override string ToString() { return innerlist.ToString(); } - - - /// - /// - /// - /// - /// - /// - public virtual string ToString(string format, IFormatProvider formatProvider) { return innerlist.ToString(format, formatProvider); } - - #endregion - - #region IDirectedCollectionValue Members - - /// - /// - /// - /// - public IDirectedCollectionValue Backwards() { return innerlist.Backwards(); } - - /// - /// - /// - /// - /// - /// - public bool FindLast(Func predicate, out T item) { return innerlist.FindLast(predicate, out item); } - - #endregion - - #region IDirectedEnumerable Members - - IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } - - /// - /// - /// - /// - public Direction Direction => Direction.Forwards; - - #endregion - - #region IDisposable Members - - /// - /// Dispose this if a view else operation is illegal - /// - /// If not a view - public void Dispose() - { - if (underlying == null) - { - throw new FixedSizeCollectionException(); - } - else - { - innerlist.Dispose(); - } - } + /// + /// + /// + public void Shuffle() { innerlist.Shuffle(); } + + /// + /// + /// + /// + public void Shuffle(Random rnd) { innerlist.Shuffle(rnd); } + + #endregion + + #region IIndexed Members - #endregion + /// + /// + /// + /// + public Speed IndexingSpeed => Speed.Constant; + + /// + /// + /// + /// + /// + /// + public IDirectedCollectionValue this[int start, int count] => innerlist[start, count]; + + /// + /// + /// + /// + /// + public int IndexOf(T item) { return innerlist.IndexOf(item); } + + /// + /// + /// + /// + /// + public int LastIndexOf(T item) { return innerlist.LastIndexOf(item); } + + /// + /// + /// + /// + /// + public int FindIndex(Func predicate) { return innerlist.FindIndex(predicate); } + + /// + /// + /// + /// + /// + public int FindLastIndex(Func predicate) { return innerlist.FindLastIndex(predicate); } + + /// + /// + /// + /// + /// + public T RemoveAt(int i) { throw new FixedSizeCollectionException(); } + + /// + /// + /// + /// + /// + public void RemoveInterval(int start, int count) { throw new FixedSizeCollectionException(); } + + #endregion + + #region ISequenced Members + + /// + /// + /// + /// + public int GetSequencedHashCode() { return innerlist.GetSequencedHashCode(); } - #region System.Collections.Generic.IList Members + /// + /// + /// + /// + /// + public bool SequencedEquals(ISequenced that) { return innerlist.SequencedEquals(that); } + + #endregion + + #region ICollection Members + /// + /// + /// + /// + public Speed ContainsSpeed => Speed.Linear; + + /// + /// + /// + /// + public int GetUnsequencedHashCode() { return innerlist.GetUnsequencedHashCode(); } + + /// + /// + /// + /// + /// + public bool UnsequencedEquals(ICollection that) { return innerlist.UnsequencedEquals(that); } + + /// + /// + /// + /// + /// + public bool Contains(T item) { return innerlist.Contains(item); } + + /// + /// + /// + /// + /// + public int ContainsCount(T item) { return innerlist.ContainsCount(item); } + + /// + /// + /// + /// + public ICollectionValue UniqueItems() { return innerlist.UniqueItems(); } + + /// + /// + /// + /// + public ICollectionValue> ItemMultiplicities() { return innerlist.ItemMultiplicities(); } + + /// + /// + /// + /// + /// + public bool ContainsAll(System.Collections.Generic.IEnumerable items) + { return innerlist.ContainsAll(items); } - void System.Collections.Generic.IList.RemoveAt(int index) + /// + /// + /// + /// + /// + public bool Find(ref T item) { return innerlist.Find(ref item); } + + /// + /// + /// + /// + /// + public bool FindOrAdd(ref T item) { throw new FixedSizeCollectionException(); } + + /// + /// + /// + /// + /// + public bool Update(T item) { throw new FixedSizeCollectionException(); } + + /// + /// + /// + /// + /// + /// + public bool Update(T item, out T olditem) { throw new FixedSizeCollectionException(); } + + /// + /// + /// + /// + /// + public bool UpdateOrAdd(T item) { throw new FixedSizeCollectionException(); } + + /// + /// + /// + /// + /// + /// + public bool UpdateOrAdd(T item, out T olditem) { throw new FixedSizeCollectionException(); } + + /// + /// + /// + /// + /// + public bool Remove(T item) { throw new FixedSizeCollectionException(); } + + /// + /// + /// + /// + /// + /// + public bool Remove(T item, out T removeditem) { throw new FixedSizeCollectionException(); } + + /// + /// + /// + /// + public void RemoveAllCopies(T item) { throw new FixedSizeCollectionException(); } + + /// + /// + /// + /// + public void RemoveAll(System.Collections.Generic.IEnumerable items) { throw new FixedSizeCollectionException(); } + + /// + /// + /// + public void Clear() { throw new FixedSizeCollectionException(); } + + /// + /// + /// + /// + public void RetainAll(System.Collections.Generic.IEnumerable items) { throw new FixedSizeCollectionException(); } + + #endregion + + #region IExtensible Members + + /// + /// + /// + /// + public bool IsReadOnly => true; + + /// + /// + /// + /// + public bool AllowsDuplicates => true; + + /// + /// + /// + /// + public SCG.IEqualityComparer EqualityComparer => innerlist.EqualityComparer; + + /// + /// + /// + /// + public bool DuplicatesByCounting => false; + + /// + /// + /// + /// + /// + public bool Add(T item) + { + throw new FixedSizeCollectionException(); + } + + /// + /// + /// + /// + public void AddAll(System.Collections.Generic.IEnumerable items) + { + throw new FixedSizeCollectionException(); + } + + /// + /// + /// + /// + public bool Check() + { + return innerlist.Check() && (underlying == null || underlying.innerlist == innerlist.Underlying); + } + + #endregion + + #region ICollectionValue Members + /// + /// No listeners may be installed + /// + /// 0 + public virtual EventType ListenableEvents => 0; + + /// + /// No listeners ever installed + /// + /// 0 + public virtual EventType ActiveEvents => 0; + + /// + /// + /// + /// + public event CollectionChangedHandler CollectionChanged + { + add { throw new UnlistenableEventException(); } + remove { throw new UnlistenableEventException(); } + } + + /// + /// + /// + /// + public event CollectionClearedHandler CollectionCleared + { + add { throw new UnlistenableEventException(); } + remove { throw new UnlistenableEventException(); } + } + + /// + /// + /// + /// + public event ItemsAddedHandler ItemsAdded + { + add { throw new UnlistenableEventException(); } + remove { throw new UnlistenableEventException(); } + } + + /// + /// + /// + /// + public event ItemInsertedHandler ItemInserted + { + add { throw new UnlistenableEventException(); } + remove { throw new UnlistenableEventException(); } + } + + /// + /// + /// + /// + public event ItemsRemovedHandler ItemsRemoved + { + add { throw new UnlistenableEventException(); } + remove { throw new UnlistenableEventException(); } + } + + /// + /// + /// + /// + public event ItemRemovedAtHandler ItemRemovedAt + { + add { throw new UnlistenableEventException(); } + remove { throw new UnlistenableEventException(); } + } + + /// + /// + /// + /// + public bool IsEmpty => innerlist.IsEmpty; + + /// + /// + /// + /// + public int Count => innerlist.Count; + + /// + /// + /// + /// + public Speed CountSpeed => innerlist.CountSpeed; + + /// + /// + /// + /// + /// + public void CopyTo(T[] array, int index) { innerlist.CopyTo(array, index); } + + /// + /// + /// + /// + public T[] ToArray() { return [.. innerlist]; } + + /// + /// + /// + /// + public void Apply(Action action) { innerlist.Apply(action); } + + /// + /// + /// + /// + /// + public bool Exists(Func predicate) { return innerlist.Exists(predicate); } + + /// + /// + /// + /// + /// + /// + public bool Find(Func predicate, out T item) { return innerlist.Find(predicate, out item); } + + /// + /// + /// + /// + /// + public bool All(Func predicate) { return innerlist.All(predicate); } + + /// + /// + /// + /// + public T Choose() { return innerlist.Choose(); } + + /// + /// + /// + /// + /// + public SCG.IEnumerable Filter(Func filter) { return innerlist.Filter(filter); } + + #endregion + + #region IEnumerable Members + + /// + /// + /// + /// + public SCG.IEnumerator GetEnumerator() { return innerlist.GetEnumerator(); } + #endregion + + #region IShowable Members + + /// + /// + /// + /// + /// + /// + /// + public bool Show(StringBuilder stringbuilder, ref int rest, IFormatProvider? formatProvider) + { return innerlist.Show(stringbuilder, ref rest, formatProvider); } + + #endregion + + #region IFormattable Members + + /// + /// + /// + /// + public override string ToString() { return innerlist.ToString(); } + + + /// + /// + /// + /// + /// + /// + public virtual string ToString(string? format, IFormatProvider? formatProvider) { return innerlist.ToString(format, formatProvider); } + + #endregion + + #region IDirectedCollectionValue Members + + /// + /// + /// + /// + public IDirectedCollectionValue Backwards() { return innerlist.Backwards(); } + + /// + /// + /// + /// + /// + /// + public bool FindLast(Func predicate, out T item) { return innerlist.FindLast(predicate, out item); } + + #endregion + + #region IDirectedEnumerable Members + + IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } + + /// + /// + /// + /// + public Direction Direction => Direction.Forwards; + + #endregion + + #region IDisposable Members + + /// + /// Dispose this if a view else operation is illegal + /// + /// If not a view + public void Dispose() + { + GC.SuppressFinalize(this); + + if (underlying == null) { throw new FixedSizeCollectionException(); } - - void System.Collections.Generic.ICollection.Add(T item) + else { - throw new FixedSizeCollectionException(); + innerlist.Dispose(); } + } - #endregion + #endregion - #region System.Collections.ICollection Members + #region System.Collections.Generic.IList Members - bool System.Collections.ICollection.IsSynchronized => false; + void System.Collections.Generic.IList.RemoveAt(int index) + { + throw new FixedSizeCollectionException(); + } - [Obsolete] - Object System.Collections.ICollection.SyncRoot => ((System.Collections.IList)innerlist).SyncRoot; + void System.Collections.Generic.ICollection.Add(T item) + { + throw new FixedSizeCollectionException(); + } - void System.Collections.ICollection.CopyTo(Array arr, int index) - { - if (index < 0 || index + Count > arr.Length) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - - foreach (T item in this) - { - arr.SetValue(item, index++); - } - } + #endregion - #endregion + #region System.Collections.ICollection Members - #region System.Collections.IList Members + bool System.Collections.ICollection.IsSynchronized => false; - Object System.Collections.IList.this[int index] - { - get => this[index]!; - set => this[index] = (T)value; - } + [Obsolete] + object System.Collections.ICollection.SyncRoot => ((System.Collections.IList)innerlist).SyncRoot; - int System.Collections.IList.Add(Object o) + void System.Collections.ICollection.CopyTo(Array arr, int index) + { + if (index < 0 || index + Count > arr.Length) { - bool added = Add((T)o); - // What position to report if item not added? SC.IList.Add doesn't say - return added ? Count - 1 : -1; + throw new ArgumentOutOfRangeException(nameof(index)); } - bool System.Collections.IList.Contains(Object o) + foreach (T item in this) { - return Contains((T)o); + arr.SetValue(item, index++); } + } - int System.Collections.IList.IndexOf(Object o) - { - return Math.Max(-1, IndexOf((T)o)); - } + #endregion - void System.Collections.IList.Insert(int index, Object o) - { - Insert(index, (T)o); - } + #region System.Collections.IList Members - void System.Collections.IList.Remove(Object o) + object? System.Collections.IList.this[int index] + { + get => this[index]!; + set { - Remove((T)o); - } + if (value is null && default(T) is not null) throw new ArgumentNullException(nameof(value)); + if (value is not T) throw new ArgumentException("Wrong type", nameof(value)); - void System.Collections.IList.RemoveAt(int index) - { - RemoveAt(index); + this[index] = (T)value; } + } - #endregion + int System.Collections.IList.Add(object? value) + { + if (value is null && default(T) is not null) throw new ArgumentNullException(nameof(value)); + if (value is not T) throw new ArgumentException("Wrong type", nameof(value)); - #region IEnumerable Members + bool added = Add((T)value); + // What position to report if item not added? SC.IList.Add doesn't say + return added ? Count - 1 : -1; + } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } + bool System.Collections.IList.Contains(object? value) + { + if (value is null && default(T) is not null) return false; + if (value is not T) return false; + + return Contains((T)value); + } + + int System.Collections.IList.IndexOf(object? value) + { + if (value is null && default(T) is not null) return -1; + if (value is not T) return -1; + + return Math.Max(-1, IndexOf((T)value)); + } + + void System.Collections.IList.Insert(int index, object? value) + { + if (value is null && default(T) is not null) throw new ArgumentNullException(nameof(value)); + if (value is not T) throw new ArgumentException("Wrong type", nameof(value)); - #endregion + Insert(index, (T)value); } + + void System.Collections.IList.Remove(object? value) + { + if (value is null && default(T) is not null) return; + if (value is not T) return; + + Remove((T)value); + } + + void System.Collections.IList.RemoveAt(int index) + { + RemoveAt(index); + } + + #endregion + + #region IEnumerable Members + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + + #endregion } \ No newline at end of file diff --git a/C5/Wrappers/GuardedCollection.cs b/C5/Wrappers/GuardedCollection.cs index badfa9fe..5c7e8985 100644 --- a/C5/Wrappers/GuardedCollection.cs +++ b/C5/Wrappers/GuardedCollection.cs @@ -1,256 +1,256 @@ -using System; - -namespace C5 +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +namespace C5; + +/// +/// A read-only wrapper for an , +/// +/// Suitable for wrapping hash tables, +/// and +/// +public class GuardedCollection : GuardedCollectionValue, ICollection { + #region Fields + + private readonly ICollection collection; + + #endregion + + #region Constructor + /// - /// A read-only wrapper for an , - /// - /// Suitable for wrapping hash tables, - /// and + /// Wrap an ICollection<T> in a read-only wrapper /// - public class GuardedCollection : GuardedCollectionValue, ICollection + /// the collection to wrap + public GuardedCollection(ICollection collection) + : base(collection) { - #region Fields - - private readonly ICollection collection; - - #endregion - - #region Constructor - - /// - /// Wrap an ICollection<T> in a read-only wrapper - /// - /// the collection to wrap - public GuardedCollection(ICollection collection) - : base(collection) - { - this.collection = collection; - } - - #endregion - - #region ICollection Members - - /// - /// (This is a read-only wrapper) - /// - /// True - public virtual bool IsReadOnly => true; - - - /// - /// Speed of wrapped collection - public virtual Speed ContainsSpeed => collection.ContainsSpeed; - - /// - /// - /// - /// - public virtual int GetUnsequencedHashCode() - { return collection.GetUnsequencedHashCode(); } - - /// - /// - /// - /// - /// - public virtual bool UnsequencedEquals(ICollection that) - { return collection.UnsequencedEquals(that); } - - - /// - /// Check if an item is in the wrapped collection - /// - /// The item - /// True if found - public virtual bool Contains(T item) { return collection.Contains(item); } - - - /// - /// Count the number of times an item appears in the wrapped collection - /// - /// The item - /// The number of copies - public virtual int ContainsCount(T item) { return collection.ContainsCount(item); } - - /// - /// - /// - /// - public virtual ICollectionValue UniqueItems() { return new GuardedCollectionValue(collection.UniqueItems()); } - - /// - /// - /// - /// - public virtual ICollectionValue> ItemMultiplicities() { return new GuardedCollectionValue>(collection.ItemMultiplicities()); } - - /// - /// Check if all items in the argument is in the wrapped collection - /// - /// The items - /// True if so - public virtual bool ContainsAll(System.Collections.Generic.IEnumerable items) { return collection.ContainsAll(items); } - - /// - /// Search for an item in the wrapped collection - /// - /// On entry the item to look for, on exit the equivalent item found (if any) - /// - public virtual bool Find(ref T item) { return collection.Find(ref item); } - - - /// - /// - /// since this is a read-only wrapper - /// - /// - public virtual bool FindOrAdd(ref T item) - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - - - /// - /// - /// since this is a read-only wrapper - /// - /// - public virtual bool Update(T item) - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - - - /// - /// - /// since this is a read-only wrapper - /// - /// - /// - public virtual bool Update(T item, out T olditem) - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - - - /// - /// - /// since this is a read-only wrapper - /// - /// - public virtual bool UpdateOrAdd(T item) - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - - - /// - /// - /// since this is a read-only wrapper - /// - /// - /// - public virtual bool UpdateOrAdd(T item, out T olditem) - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - - /// - /// - /// since this is a read-only wrapper - /// - /// - public virtual bool Remove(T item) - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - - - /// - /// - /// since this is a read-only wrapper - /// The value to remove. - /// The removed value. - /// - public virtual bool Remove(T item, out T removeditem) - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - - - /// - /// - /// since this is a read-only wrapper - /// - public virtual void RemoveAllCopies(T item) - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - - - /// - /// - /// since this is a read-only wrapper - /// - public virtual void RemoveAll(System.Collections.Generic.IEnumerable items) - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - - /// - /// - /// since this is a read-only wrapper - public virtual void Clear() - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - - - /// - /// - /// since this is a read-only wrapper - /// - public virtual void RetainAll(System.Collections.Generic.IEnumerable items) - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - - /// - /// Check wrapped collection for internal consistency - /// - /// True if check passed - public virtual bool Check() { return collection.Check(); } - - #endregion - - #region IExtensible Members - - /// - /// False if wrapped collection has set semantics - public virtual bool AllowsDuplicates => collection.AllowsDuplicates; - - //TODO: the equalityComparer should be guarded - /// - /// - /// - /// - public virtual System.Collections.Generic.IEqualityComparer EqualityComparer => collection.EqualityComparer; - - /// - /// By convention this is true for any collection with set semantics. - /// - /// True if only one representative of a group of equal items - /// is kept in the collection together with the total count. - public virtual bool DuplicatesByCounting => collection.DuplicatesByCounting; - - - /// - /// True if wrapped collection is empty - public override bool IsEmpty => collection.IsEmpty; - - - /// - /// - /// since this is a read-only wrapper - /// - /// - public virtual bool Add(T item) - { throw new ReadOnlyCollectionException(); } - - /// - /// - /// since this is a read-only wrapper - /// - void System.Collections.Generic.ICollection.Add(T item) - { throw new ReadOnlyCollectionException(); } - - /// - /// - /// since this is a read-only wrapper - /// - public virtual void AddAll(System.Collections.Generic.IEnumerable items) - { throw new ReadOnlyCollectionException(); } - - #endregion + this.collection = collection; } + + #endregion + + #region ICollection Members + + /// + /// (This is a read-only wrapper) + /// + /// True + public virtual bool IsReadOnly => true; + + + /// + /// Speed of wrapped collection + public virtual Speed ContainsSpeed => collection.ContainsSpeed; + + /// + /// + /// + /// + public virtual int GetUnsequencedHashCode() + { return collection.GetUnsequencedHashCode(); } + + /// + /// + /// + /// + /// + public virtual bool UnsequencedEquals(ICollection that) + { return collection.UnsequencedEquals(that); } + + + /// + /// Check if an item is in the wrapped collection + /// + /// The item + /// True if found + public virtual bool Contains(T item) { return collection.Contains(item); } + + + /// + /// Count the number of times an item appears in the wrapped collection + /// + /// The item + /// The number of copies + public virtual int ContainsCount(T item) { return collection.ContainsCount(item); } + + /// + /// + /// + /// + public virtual ICollectionValue UniqueItems() { return new GuardedCollectionValue(collection.UniqueItems()); } + + /// + /// + /// + /// + public virtual ICollectionValue> ItemMultiplicities() { return new GuardedCollectionValue>(collection.ItemMultiplicities()); } + + /// + /// Check if all items in the argument is in the wrapped collection + /// + /// The items + /// True if so + public virtual bool ContainsAll(System.Collections.Generic.IEnumerable items) { return collection.ContainsAll(items); } + + /// + /// Search for an item in the wrapped collection + /// + /// On entry the item to look for, on exit the equivalent item found (if any) + /// + public virtual bool Find(ref T item) { return collection.Find(ref item); } + + + /// + /// + /// since this is a read-only wrapper + /// + /// + public virtual bool FindOrAdd(ref T item) + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + + + /// + /// + /// since this is a read-only wrapper + /// + /// + public virtual bool Update(T item) + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + + + /// + /// + /// since this is a read-only wrapper + /// + /// + /// + public virtual bool Update(T item, out T olditem) + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + + + /// + /// + /// since this is a read-only wrapper + /// + /// + public virtual bool UpdateOrAdd(T item) + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + + + /// + /// + /// since this is a read-only wrapper + /// + /// + /// + public virtual bool UpdateOrAdd(T item, out T olditem) + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + + /// + /// + /// since this is a read-only wrapper + /// + /// + public virtual bool Remove(T item) + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + + + /// + /// + /// since this is a read-only wrapper + /// The value to remove. + /// The removed value. + /// + public virtual bool Remove(T item, out T removeditem) + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + + + /// + /// + /// since this is a read-only wrapper + /// + public virtual void RemoveAllCopies(T item) + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + + + /// + /// + /// since this is a read-only wrapper + /// + public virtual void RemoveAll(System.Collections.Generic.IEnumerable items) + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + + /// + /// + /// since this is a read-only wrapper + public virtual void Clear() + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + + + /// + /// + /// since this is a read-only wrapper + /// + public virtual void RetainAll(System.Collections.Generic.IEnumerable items) + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + + /// + /// Check wrapped collection for internal consistency + /// + /// True if check passed + public virtual bool Check() { return collection.Check(); } + + #endregion + + #region IExtensible Members + + /// + /// False if wrapped collection has set semantics + public virtual bool AllowsDuplicates => collection.AllowsDuplicates; + + //TODO: the equalityComparer should be guarded + /// + /// + /// + /// + public virtual System.Collections.Generic.IEqualityComparer EqualityComparer => collection.EqualityComparer; + + /// + /// By convention this is true for any collection with set semantics. + /// + /// True if only one representative of a group of equal items + /// is kept in the collection together with the total count. + public virtual bool DuplicatesByCounting => collection.DuplicatesByCounting; + + + /// + /// True if wrapped collection is empty + public override bool IsEmpty => collection.IsEmpty; + + + /// + /// + /// since this is a read-only wrapper + /// + /// + public virtual bool Add(T item) + { throw new ReadOnlyCollectionException(); } + + /// + /// + /// since this is a read-only wrapper + /// + void System.Collections.Generic.ICollection.Add(T item) + { throw new ReadOnlyCollectionException(); } + + /// + /// + /// since this is a read-only wrapper + /// + public virtual void AddAll(System.Collections.Generic.IEnumerable items) + { throw new ReadOnlyCollectionException(); } + + #endregion } \ No newline at end of file diff --git a/C5/Wrappers/GuardedCollectionValue.cs b/C5/Wrappers/GuardedCollectionValue.cs index 75ef21d1..75b86bc4 100644 --- a/C5/Wrappers/GuardedCollectionValue.cs +++ b/C5/Wrappers/GuardedCollectionValue.cs @@ -1,251 +1,253 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// A read-only wrapper for an ICollectionValue<T> +/// +/// This is mainly interesting as a base of other guard classes +/// +public class GuardedCollectionValue : GuardedEnumerable, ICollectionValue { + #region Events /// - /// A read-only wrapper for an ICollectionValue<T> - /// - /// This is mainly interesting as a base of other guard classes + /// The ListenableEvents value of the wrapped collection + /// + /// + public virtual EventType ListenableEvents => collectionvalue.ListenableEvents; + + /// + /// The ActiveEvents value of the wrapped collection /// - public class GuardedCollectionValue : GuardedEnumerable, ICollectionValue + /// + public virtual EventType ActiveEvents => collectionvalue.ActiveEvents; + + private ProxyEventBlock? eventBlock; + /// + /// The change event. Will be raised for every change operation on the collection. + /// + public event CollectionChangedHandler CollectionChanged { - #region Events - /// - /// The ListenableEvents value of the wrapped collection - /// - /// - public virtual EventType ListenableEvents => collectionvalue.ListenableEvents; - - /// - /// The ActiveEvents value of the wrapped collection - /// - /// - public virtual EventType ActiveEvents => collectionvalue.ActiveEvents; - - private ProxyEventBlock? eventBlock; - /// - /// The change event. Will be raised for every change operation on the collection. - /// - public event CollectionChangedHandler CollectionChanged + add { (eventBlock ??= new ProxyEventBlock(this, collectionvalue)).CollectionChanged += value; } + remove { - add { (eventBlock ??= new ProxyEventBlock(this, collectionvalue)).CollectionChanged += value; } - remove + if (eventBlock != null) { - if (eventBlock != null) - { - eventBlock.CollectionChanged -= value; - } + eventBlock.CollectionChanged -= value; } } + } - /// - /// The change event. Will be raised for every change operation on the collection. - /// - public event CollectionClearedHandler CollectionCleared + /// + /// The change event. Will be raised for every change operation on the collection. + /// + public event CollectionClearedHandler CollectionCleared + { + add { (eventBlock ??= new ProxyEventBlock(this, collectionvalue)).CollectionCleared += value; } + remove { - add { (eventBlock ??= new ProxyEventBlock(this, collectionvalue)).CollectionCleared += value; } - remove + if (eventBlock != null) { - if (eventBlock != null) - { - eventBlock.CollectionCleared -= value; - } + eventBlock.CollectionCleared -= value; } } + } - /// - /// The item added event. Will be raised for every individual addition to the collection. - /// - public event ItemsAddedHandler ItemsAdded + /// + /// The item added event. Will be raised for every individual addition to the collection. + /// + public event ItemsAddedHandler ItemsAdded + { + add { (eventBlock ??= new ProxyEventBlock(this, collectionvalue)).ItemsAdded += value; } + remove { - add { (eventBlock ??= new ProxyEventBlock(this, collectionvalue)).ItemsAdded += value; } - remove + if (eventBlock != null) { - if (eventBlock != null) - { - eventBlock.ItemsAdded -= value; - } + eventBlock.ItemsAdded -= value; } } + } - /// - /// The item added event. Will be raised for every individual addition to the collection. - /// - public event ItemInsertedHandler ItemInserted + /// + /// The item added event. Will be raised for every individual addition to the collection. + /// + public event ItemInsertedHandler ItemInserted + { + add { (eventBlock ??= new ProxyEventBlock(this, collectionvalue)).ItemInserted += value; } + remove { - add { (eventBlock ??= new ProxyEventBlock(this, collectionvalue)).ItemInserted += value; } - remove + if (eventBlock != null) { - if (eventBlock != null) - { - eventBlock.ItemInserted -= value; - } + eventBlock.ItemInserted -= value; } } + } - /// - /// The item removed event. Will be raised for every individual removal from the collection. - /// - public event ItemsRemovedHandler ItemsRemoved + /// + /// The item removed event. Will be raised for every individual removal from the collection. + /// + public event ItemsRemovedHandler ItemsRemoved + { + add { (eventBlock ??= new ProxyEventBlock(this, collectionvalue)).ItemsRemoved += value; } + remove { - add { (eventBlock ??= new ProxyEventBlock(this, collectionvalue)).ItemsRemoved += value; } - remove + if (eventBlock != null) { - if (eventBlock != null) - { - eventBlock.ItemsRemoved -= value; - } + eventBlock.ItemsRemoved -= value; } } + } - /// - /// The item removed event. Will be raised for every individual removal from the collection. - /// - public event ItemRemovedAtHandler ItemRemovedAt + /// + /// The item removed event. Will be raised for every individual removal from the collection. + /// + public event ItemRemovedAtHandler ItemRemovedAt + { + add { (eventBlock ??= new ProxyEventBlock(this, collectionvalue)).ItemRemovedAt += value; } + remove { - add { (eventBlock ??= new ProxyEventBlock(this, collectionvalue)).ItemRemovedAt += value; } - remove + if (eventBlock != null) { - if (eventBlock != null) - { - eventBlock.ItemRemovedAt -= value; - } + eventBlock.ItemRemovedAt -= value; } } - #endregion - - #region Fields - - private readonly ICollectionValue collectionvalue; - - #endregion - - #region Constructor - - /// - /// Wrap a ICollectionValue<T> in a read-only wrapper - /// - /// the collection to wrap - public GuardedCollectionValue(ICollectionValue collectionvalue) - : base(collectionvalue) - { this.collectionvalue = collectionvalue; } - - #endregion - - #region ICollection Members - - /// - /// Get the size of the wrapped collection - /// - /// The size - public virtual bool IsEmpty => collectionvalue.IsEmpty; - - /// - /// Get the size of the wrapped collection - /// - /// The size - public virtual int Count => collectionvalue.Count; - - /// - /// The value is symbolic indicating the type of asymptotic complexity - /// in terms of the size of this collection (worst-case or amortized as - /// relevant). - /// - /// A characterization of the speed of the - /// Count property in this collection. - public virtual Speed CountSpeed => collectionvalue.CountSpeed; - - /// - /// Copy the items of the wrapped collection to an array - /// - /// The array - /// Starting offset - public virtual void CopyTo(T[] a, int i) { collectionvalue.CopyTo(a, i); } - - /// - /// Create an array from the items of the wrapped collection - /// - /// The array - public virtual T[] ToArray() { return collectionvalue.ToArray(); } - - /// - /// Apply a delegate to all items of the wrapped enumerable. - /// - /// The delegate to apply - //TODO: change this to throw an exception? - public virtual void Apply(Action a) { collectionvalue.Apply(a); } - - - /// - /// Check if there exists an item that satisfies a - /// specific predicate in the wrapped enumerable. - /// - /// A filter delegate - /// () defining the predicate - /// True is such an item exists - public virtual bool Exists(Func filter) { return collectionvalue.Exists(filter); } - - /// - /// - /// - /// - /// - /// - public virtual bool Find(Func filter, out T item) { return collectionvalue.Find(filter, out item); } - - /// - /// Check if all items in the wrapped enumerable satisfies a specific predicate. - /// - /// A filter delegate - /// () defining the predicate - /// True if all items satisfies the predicate - public virtual bool All(Func filter) { return collectionvalue.All(filter); } - - /// - /// Create an enumerable, enumerating the items of this collection that satisfies - /// a certain condition. - /// - /// The T->bool filter delegate defining the condition - /// The filtered enumerable - public virtual System.Collections.Generic.IEnumerable Filter(Func filter) { return collectionvalue.Filter(filter); } - - /// - /// Choose some item of this collection. - /// - /// if collection is empty. - /// - public virtual T Choose() { return collectionvalue.Choose(); } - - #endregion - - #region IShowable Members - - /// - /// - /// - /// - /// - /// - /// - public bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider? formatProvider) - { - return collectionvalue.Show(stringbuilder, ref rest, formatProvider); - } - #endregion + } + #endregion - #region IFormattable Members + #region Fields - /// - /// - /// - /// - /// - /// - public string ToString(string format, IFormatProvider formatProvider) - { - return collectionvalue.ToString(format, formatProvider); - } + private readonly ICollectionValue collectionvalue; + + #endregion + + #region Constructor + + /// + /// Wrap a ICollectionValue<T> in a read-only wrapper + /// + /// the collection to wrap + public GuardedCollectionValue(ICollectionValue collectionvalue) + : base(collectionvalue) + { this.collectionvalue = collectionvalue; } + + #endregion + + #region ICollection Members + + /// + /// Get the size of the wrapped collection + /// + /// The size + public virtual bool IsEmpty => collectionvalue.IsEmpty; + + /// + /// Get the size of the wrapped collection + /// + /// The size + public virtual int Count => collectionvalue.Count; + + /// + /// The value is symbolic indicating the type of asymptotic complexity + /// in terms of the size of this collection (worst-case or amortized as + /// relevant). + /// + /// A characterization of the speed of the + /// Count property in this collection. + public virtual Speed CountSpeed => collectionvalue.CountSpeed; + + /// + /// Copy the items of the wrapped collection to an array + /// + /// The array + /// Starting offset + public virtual void CopyTo(T[] a, int i) { collectionvalue.CopyTo(a, i); } + + /// + /// Create an array from the items of the wrapped collection + /// + /// The array + public virtual T[] ToArray() { return collectionvalue.ToArray(); } - #endregion + /// + /// Apply a delegate to all items of the wrapped enumerable. + /// + /// The delegate to apply + //TODO: change this to throw an exception? + public virtual void Apply(Action a) { collectionvalue.Apply(a); } + + + /// + /// Check if there exists an item that satisfies a + /// specific predicate in the wrapped enumerable. + /// + /// A filter delegate + /// () defining the predicate + /// True is such an item exists + public virtual bool Exists(Func filter) { return collectionvalue.Exists(filter); } + + /// + /// + /// + /// + /// + /// + public virtual bool Find(Func filter, out T item) { return collectionvalue.Find(filter, out item); } + + /// + /// Check if all items in the wrapped enumerable satisfies a specific predicate. + /// + /// A filter delegate + /// () defining the predicate + /// True if all items satisfies the predicate + public virtual bool All(Func filter) { return collectionvalue.All(filter); } + + /// + /// Create an enumerable, enumerating the items of this collection that satisfies + /// a certain condition. + /// + /// The T->bool filter delegate defining the condition + /// The filtered enumerable + public virtual System.Collections.Generic.IEnumerable Filter(Func filter) { return collectionvalue.Filter(filter); } + + /// + /// Choose some item of this collection. + /// + /// if collection is empty. + /// + public virtual T Choose() { return collectionvalue.Choose(); } + + #endregion + + #region IShowable Members + + /// + /// + /// + /// + /// + /// + /// + public bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider? formatProvider) + { + return collectionvalue.Show(stringbuilder, ref rest, formatProvider); } + #endregion + + #region IFormattable Members + + /// + /// + /// + /// + /// + /// + public string ToString(string? format, IFormatProvider? formatProvider) + { + return collectionvalue.ToString(format, formatProvider); + } + + #endregion } \ No newline at end of file diff --git a/C5/Wrappers/GuardedDictionary.cs b/C5/Wrappers/GuardedDictionary.cs index 469fa931..5b661775 100644 --- a/C5/Wrappers/GuardedDictionary.cs +++ b/C5/Wrappers/GuardedDictionary.cs @@ -1,183 +1,185 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; using SCG = System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// A read-only wrapper for a dictionary. +/// +/// Suitable for wrapping a HashDictionary. +/// +public class GuardedDictionary : GuardedCollectionValue>, IDictionary { + #region Fields + + private readonly IDictionary dict; + + #endregion + + #region Constructor + + /// + /// Wrap a dictionary in a read-only wrapper + /// + /// the dictionary + public GuardedDictionary(IDictionary dict) : base(dict) { this.dict = dict; } + + #endregion + + #region IDictionary Members + /// - /// A read-only wrapper for a dictionary. /// - /// Suitable for wrapping a HashDictionary. /// - public class GuardedDictionary : GuardedCollectionValue>, IDictionary + /// + public SCG.IEqualityComparer EqualityComparer => dict.EqualityComparer; + + /// + /// + /// since this is a + /// read-only wrapper if used as a setter + /// Get the value corresponding to a key in the wrapped dictionary + public V this[K key] { - #region Fields - - private readonly IDictionary dict; - - #endregion - - #region Constructor - - /// - /// Wrap a dictionary in a read-only wrapper - /// - /// the dictionary - public GuardedDictionary(IDictionary dict) : base(dict) { this.dict = dict; } - - #endregion - - #region IDictionary Members - - /// - /// - /// - /// - public SCG.IEqualityComparer EqualityComparer => dict.EqualityComparer; - - /// - /// - /// since this is a - /// read-only wrapper if used as a setter - /// Get the value corresponding to a key in the wrapped dictionary - public V this[K key] - { - get => dict[key]; - set => throw new ReadOnlyCollectionException(); - } - - /// - /// (This is a read-only wrapper) - /// - /// True - public bool IsReadOnly => true; - - /// - /// The collection of keys of the wrapped dictionary - public ICollectionValue Keys => new GuardedCollectionValue(dict.Keys); - - - /// - /// The collection of values of the wrapped dictionary - public ICollectionValue Values => new GuardedCollectionValue(dict.Values); - - /// - /// - /// - public virtual Func Func => k => this[k]; - - /// - /// - /// since this is a read-only wrapper - /// - /// - public void Add(K key, V val) => throw new ReadOnlyCollectionException(); - - /// - /// - /// - /// since this is a read-only wrapper - /// - public void AddAll(SCG.IEnumerable> items) - where L : K - where W : V => throw new ReadOnlyCollectionException(); - - /// - /// - /// since this is a read-only wrapper - /// - /// - public bool Remove(K key) => throw new ReadOnlyCollectionException(); - - /// - /// - /// since this is a read-only wrapper - /// - /// - /// - public bool Remove(K key, out V val) => throw new ReadOnlyCollectionException(); - - /// - /// - /// since this is a read-only wrapper - public void Clear() => throw new ReadOnlyCollectionException(); - - /// - /// - /// - /// - public Speed ContainsSpeed => dict.ContainsSpeed; - - /// - /// Check if the wrapped dictionary contains a specific key - /// - /// The key - /// True if it does - public bool Contains(K key) => dict.Contains(key); - - /// - /// - /// - /// - /// - public bool ContainsAll(SCG.IEnumerable keys) where H : K => dict.ContainsAll(keys); - - /// - /// Search for a key in the wrapped dictionary, reporting the value if found - /// - /// The key - /// On exit: the value if found - /// True if found - public bool Find(ref K key, out V val) => dict.Find(ref key, out val); - - /// - /// - /// since this is a read-only wrapper - /// - /// - /// - public bool Update(K key, V val) => throw new ReadOnlyCollectionException(); - - /// - /// - /// since this is a read-only wrapper - /// - /// - /// - /// - public bool Update(K key, V val, out V oldval) => throw new ReadOnlyCollectionException(); - - /// - /// - /// since this is a read-only wrapper - /// - /// - /// - public bool FindOrAdd(K key, ref V val) => throw new ReadOnlyCollectionException(); - - /// - /// - /// since this is a read-only wrapper - /// - /// - /// - public bool UpdateOrAdd(K key, V val) => throw new ReadOnlyCollectionException(); - - /// - /// - /// since this is a read-only wrapper - /// - /// - /// - /// - public bool UpdateOrAdd(K key, V val, out V oldval) => throw new ReadOnlyCollectionException(); - - - /// - /// Check the internal consistency of the wrapped dictionary - /// - /// True if check passed - public bool Check() { return dict.Check(); } - - #endregion + get => dict[key]; + set => throw new ReadOnlyCollectionException(); } + + /// + /// (This is a read-only wrapper) + /// + /// True + public bool IsReadOnly => true; + + /// + /// The collection of keys of the wrapped dictionary + public ICollectionValue Keys => new GuardedCollectionValue(dict.Keys); + + + /// + /// The collection of values of the wrapped dictionary + public ICollectionValue Values => new GuardedCollectionValue(dict.Values); + + /// + /// + /// + public virtual Func Func => k => this[k]; + + /// + /// + /// since this is a read-only wrapper + /// + /// + public void Add(K key, V val) => throw new ReadOnlyCollectionException(); + + /// + /// + /// + /// since this is a read-only wrapper + /// + public void AddAll(SCG.IEnumerable> items) + where L : K + where W : V => throw new ReadOnlyCollectionException(); + + /// + /// + /// since this is a read-only wrapper + /// + /// + public bool Remove(K key) => throw new ReadOnlyCollectionException(); + + /// + /// + /// since this is a read-only wrapper + /// + /// + /// + public bool Remove(K key, out V val) => throw new ReadOnlyCollectionException(); + + /// + /// + /// since this is a read-only wrapper + public void Clear() => throw new ReadOnlyCollectionException(); + + /// + /// + /// + /// + public Speed ContainsSpeed => dict.ContainsSpeed; + + /// + /// Check if the wrapped dictionary contains a specific key + /// + /// The key + /// True if it does + public bool Contains(K key) => dict.Contains(key); + + /// + /// + /// + /// + /// + public bool ContainsAll(SCG.IEnumerable keys) where H : K => dict.ContainsAll(keys); + + /// + /// Search for a key in the wrapped dictionary, reporting the value if found + /// + /// The key + /// On exit: the value if found + /// True if found + public bool Find(ref K key, out V val) => dict.Find(ref key, out val); + + /// + /// + /// since this is a read-only wrapper + /// + /// + /// + public bool Update(K key, V val) => throw new ReadOnlyCollectionException(); + + /// + /// + /// since this is a read-only wrapper + /// + /// + /// + /// + public bool Update(K key, V val, out V oldval) => throw new ReadOnlyCollectionException(); + + /// + /// + /// since this is a read-only wrapper + /// + /// + /// + public bool FindOrAdd(K key, ref V val) => throw new ReadOnlyCollectionException(); + + /// + /// + /// since this is a read-only wrapper + /// + /// + /// + public bool UpdateOrAdd(K key, V val) => throw new ReadOnlyCollectionException(); + + /// + /// + /// since this is a read-only wrapper + /// + /// + /// + /// + public bool UpdateOrAdd(K key, V val, out V oldval) => throw new ReadOnlyCollectionException(); + + + /// + /// Check the internal consistency of the wrapped dictionary + /// + /// True if check passed + public bool Check() { return dict.Check(); } + + #endregion } \ No newline at end of file diff --git a/C5/Wrappers/GuardedDirectedCollectionValue.cs b/C5/Wrappers/GuardedDirectedCollectionValue.cs index fdf15287..2e87e722 100644 --- a/C5/Wrappers/GuardedDirectedCollectionValue.cs +++ b/C5/Wrappers/GuardedDirectedCollectionValue.cs @@ -1,64 +1,66 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// A read-only wrapper for a directed collection +/// +/// This is mainly interesting as a base of other guard classes +/// +public class GuardedDirectedCollectionValue : GuardedCollectionValue, IDirectedCollectionValue { - /// - /// A read-only wrapper for a directed collection - /// - /// This is mainly interesting as a base of other guard classes - /// - public class GuardedDirectedCollectionValue : GuardedCollectionValue, IDirectedCollectionValue - { - #region Fields + #region Fields - private readonly IDirectedCollectionValue directedcollection; + private readonly IDirectedCollectionValue directedcollection; - #endregion + #endregion - #region Constructor + #region Constructor - /// - /// Wrap a directed collection in a read-only wrapper - /// - /// the collection to wrap - public GuardedDirectedCollectionValue(IDirectedCollectionValue directedcollection) - : - base(directedcollection) - { this.directedcollection = directedcollection; } + /// + /// Wrap a directed collection in a read-only wrapper + /// + /// the collection to wrap + public GuardedDirectedCollectionValue(IDirectedCollectionValue directedcollection) + : + base(directedcollection) + { this.directedcollection = directedcollection; } - #endregion + #endregion - #region IDirectedCollection Members + #region IDirectedCollection Members - /// - /// Get a collection that enumerates the wrapped collection in the opposite direction - /// - /// The mirrored collection - public virtual IDirectedCollectionValue Backwards() - { return new GuardedDirectedCollectionValue(directedcollection.Backwards()); } + /// + /// Get a collection that enumerates the wrapped collection in the opposite direction + /// + /// The mirrored collection + public virtual IDirectedCollectionValue Backwards() + { return new GuardedDirectedCollectionValue(directedcollection.Backwards()); } - /// - /// - /// - /// - /// - /// - public virtual bool FindLast(Func predicate, out T item) { return directedcollection.FindLast(predicate, out item); } + /// + /// + /// + /// + /// + /// + public virtual bool FindLast(Func predicate, out T item) { return directedcollection.FindLast(predicate, out item); } - #endregion + #endregion - #region IDirectedEnumerable Members + #region IDirectedEnumerable Members - IDirectedEnumerable IDirectedEnumerable.Backwards() - { return Backwards(); } + IDirectedEnumerable IDirectedEnumerable.Backwards() + { return Backwards(); } - /// - /// Forwards if same, else Backwards - /// - /// The enumeration direction relative to the original collection. - public Direction Direction => directedcollection.Direction; + /// + /// Forwards if same, else Backwards + /// + /// The enumeration direction relative to the original collection. + public Direction Direction => directedcollection.Direction; - #endregion - } + #endregion } \ No newline at end of file diff --git a/C5/Wrappers/GuardedDirectedEnumerable.cs b/C5/Wrappers/GuardedDirectedEnumerable.cs index 19f84f96..d7893b94 100644 --- a/C5/Wrappers/GuardedDirectedEnumerable.cs +++ b/C5/Wrappers/GuardedDirectedEnumerable.cs @@ -1,48 +1,48 @@ -using System; +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. -namespace C5 +namespace C5; + +/// +/// A read-only wrapper for a generic directed enumerable +/// +/// This is mainly interesting as a base of other guard classes +/// +public class GuardedDirectedEnumerable : GuardedEnumerable, IDirectedEnumerable { - /// - /// A read-only wrapper for a generic directed enumerable - /// - /// This is mainly interesting as a base of other guard classes - /// - public class GuardedDirectedEnumerable : GuardedEnumerable, IDirectedEnumerable - { - #region Fields + #region Fields - private readonly IDirectedEnumerable directedenumerable; + private readonly IDirectedEnumerable directedenumerable; - #endregion + #endregion - #region Constructor + #region Constructor - /// - /// Wrap a directed enumerable in a read-only wrapper - /// - /// the collection to wrap - public GuardedDirectedEnumerable(IDirectedEnumerable directedenumerable) - : base(directedenumerable) - { this.directedenumerable = directedenumerable; } + /// + /// Wrap a directed enumerable in a read-only wrapper + /// + /// the collection to wrap + public GuardedDirectedEnumerable(IDirectedEnumerable directedenumerable) + : base(directedenumerable) + { this.directedenumerable = directedenumerable; } - #endregion + #endregion - #region IDirectedEnumerable Members + #region IDirectedEnumerable Members - /// - /// Get a enumerable that enumerates the wrapped collection in the opposite direction - /// - /// The mirrored enumerable - public IDirectedEnumerable Backwards() - { return new GuardedDirectedEnumerable(directedenumerable.Backwards()); } + /// + /// Get a enumerable that enumerates the wrapped collection in the opposite direction + /// + /// The mirrored enumerable + public IDirectedEnumerable Backwards() + { return new GuardedDirectedEnumerable(directedenumerable.Backwards()); } - /// - /// Forwards if same, else Backwards - /// - /// The enumeration direction relative to the original collection. - public Direction Direction => directedenumerable.Direction; + /// + /// Forwards if same, else Backwards + /// + /// The enumeration direction relative to the original collection. + public Direction Direction => directedenumerable.Direction; - #endregion - } + #endregion } \ No newline at end of file diff --git a/C5/Wrappers/GuardedEnumerable.cs b/C5/Wrappers/GuardedEnumerable.cs index 6f3e7f28..fbc0e0ff 100644 --- a/C5/Wrappers/GuardedEnumerable.cs +++ b/C5/Wrappers/GuardedEnumerable.cs @@ -1,51 +1,52 @@ -using System; +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// A read-only wrapper class for a generic enumerable +/// +/// This is mainly interesting as a base of other guard classes +/// +public class GuardedEnumerable : System.Collections.Generic.IEnumerable { - /// - /// A read-only wrapper class for a generic enumerable - /// - /// This is mainly interesting as a base of other guard classes - /// - public class GuardedEnumerable : System.Collections.Generic.IEnumerable - { - #region Fields + #region Fields - private readonly System.Collections.Generic.IEnumerable enumerable; + private readonly System.Collections.Generic.IEnumerable enumerable; - #endregion + #endregion - #region Constructor + #region Constructor - /// - /// Wrap an enumerable in a read-only wrapper - /// - /// The enumerable to wrap - public GuardedEnumerable(System.Collections.Generic.IEnumerable enumerable) - { this.enumerable = enumerable; } + /// + /// Wrap an enumerable in a read-only wrapper + /// + /// The enumerable to wrap + public GuardedEnumerable(System.Collections.Generic.IEnumerable enumerable) + { this.enumerable = enumerable; } - #endregion + #endregion - #region System.Collections.Generic.IEnumerable Members + #region System.Collections.Generic.IEnumerable Members - /// - /// Get an enumerator from the wrapped enumerable - /// - /// The enumerator (itself wrapped) - public IEnumerator GetEnumerator() - { return new GuardedEnumerator(enumerable.GetEnumerator()); } + /// + /// Get an enumerator from the wrapped enumerable + /// + /// The enumerator (itself wrapped) + public IEnumerator GetEnumerator() + { return new GuardedEnumerator(enumerable.GetEnumerator()); } - #endregion + #endregion - #region IEnumerable Members + #region IEnumerable Members - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } - #endregion + #endregion - } } \ No newline at end of file diff --git a/C5/Wrappers/GuardedEnumerator.cs b/C5/Wrappers/GuardedEnumerator.cs index 4b9dc3b4..e5579eaa 100644 --- a/C5/Wrappers/GuardedEnumerator.cs +++ b/C5/Wrappers/GuardedEnumerator.cs @@ -1,71 +1,69 @@ // This file is part of the C5 Generic Collection Library for C# and CLI // See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. -using System; using System.Collections.Generic; -namespace C5 -{ - /// - /// A read-only wrapper class for a generic enumerator - /// - public class GuardedEnumerator : IEnumerator - { - #region Fields +namespace C5; - private readonly IEnumerator enumerator; +/// +/// A read-only wrapper class for a generic enumerator +/// +public class GuardedEnumerator : IEnumerator +{ + #region Fields - #endregion + private readonly IEnumerator enumerator; - #region Constructor + #endregion - /// - /// Create a wrapper around a generic enumerator - /// - /// The enumerator to wrap - public GuardedEnumerator(IEnumerator enumerator) - { this.enumerator = enumerator; } + #region Constructor - #endregion + /// + /// Create a wrapper around a generic enumerator + /// + /// The enumerator to wrap + public GuardedEnumerator(IEnumerator enumerator) + { this.enumerator = enumerator; } - #region IEnumerator Members + #endregion - /// - /// Move wrapped enumerator to next item, or the first item if - /// this is the first call to MoveNext. - /// - /// True if enumerator is valid now - public bool MoveNext() { return enumerator.MoveNext(); } + #region IEnumerator Members + /// + /// Move wrapped enumerator to next item, or the first item if + /// this is the first call to MoveNext. + /// + /// True if enumerator is valid now + public bool MoveNext() { return enumerator.MoveNext(); } - /// - /// Undefined if enumerator is not valid (MoveNext hash been called returning true) - /// - /// The current item of the wrapped enumerator. - public T Current => enumerator.Current; - #endregion + /// + /// Undefined if enumerator is not valid (MoveNext hash been called returning true) + /// + /// The current item of the wrapped enumerator. + public T Current => enumerator.Current; - #region IDisposable Members + #endregion - //TODO: consider possible danger of calling through to Dispose. - /// - /// Dispose wrapped enumerator. - /// - public void Dispose() { enumerator.Dispose(); } + #region IDisposable Members - #endregion + //TODO: consider possible danger of calling through to Dispose. + /// + /// Dispose wrapped enumerator. + /// + public void Dispose() { enumerator.Dispose(); } + #endregion - #region IEnumerator Members - object System.Collections.IEnumerator.Current => enumerator.Current!; + #region IEnumerator Members - void System.Collections.IEnumerator.Reset() - { - enumerator.Reset(); - } + object System.Collections.IEnumerator.Current => enumerator.Current!; - #endregion + void System.Collections.IEnumerator.Reset() + { + enumerator.Reset(); } + + #endregion } \ No newline at end of file diff --git a/C5/Wrappers/GuardedIndexedSorted.cs b/C5/Wrappers/GuardedIndexedSorted.cs index 8617761a..f89a273a 100644 --- a/C5/Wrappers/GuardedIndexedSorted.cs +++ b/C5/Wrappers/GuardedIndexedSorted.cs @@ -1,171 +1,173 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// Read-only wrapper for indexed sorted collections +/// +/// Suitable for wrapping TreeSet, TreeBag and SortedArray +/// +public class GuardedIndexedSorted : GuardedSorted, IIndexedSorted { + #region Fields + + private readonly IIndexedSorted indexedsorted; + + #endregion + + #region Constructor + + /// + /// Wrap an indexed sorted collection in a read-only wrapper + /// + /// the indexed sorted collection + public GuardedIndexedSorted(IIndexedSorted list) + : base(list) + { indexedsorted = list; } + + #endregion + + #region IIndexedSorted Members + + /// + /// Get the specified range from the wrapped collection. + /// (The current implementation erroneously does not wrap the result.) + /// + /// + /// + public new IDirectedCollectionValue RangeFrom(T bot) + { return indexedsorted.RangeFrom(bot); } + + + /// + /// Get the specified range from the wrapped collection. + /// (The current implementation erroneously does not wrap the result.) + /// + /// + /// + /// + public new IDirectedCollectionValue RangeFromTo(T bot, T top) + { return indexedsorted.RangeFromTo(bot, top); } + + + /// + /// Get the specified range from the wrapped collection. + /// (The current implementation erroneously does not wrap the result.) + /// + /// + /// + public new IDirectedCollectionValue RangeTo(T top) + { return indexedsorted.RangeTo(top); } + + + /// + /// Report the number of items in the specified range of the wrapped collection + /// + /// + /// + public int CountFrom(T bot) { return indexedsorted.CountFrom(bot); } + + + /// + /// Report the number of items in the specified range of the wrapped collection + /// + /// + /// + /// + public int CountFromTo(T bot, T top) { return indexedsorted.CountFromTo(bot, top); } + + + /// + /// Report the number of items in the specified range of the wrapped collection + /// + /// + /// + public int CountTo(T top) { return indexedsorted.CountTo(top); } + + + /// + /// Run FindAll on the wrapped collection with the indicated filter. + /// The result will not be read-only. + /// + /// + /// + public IIndexedSorted FindAll(Func f) + { return indexedsorted.FindAll(f); } + + + /// + /// Run Map on the wrapped collection with the indicated mapper. + /// The result will not be read-only. + /// + /// + /// The comparer to use in the result + /// + public IIndexedSorted Map(Func m, System.Collections.Generic.IComparer c) + { return indexedsorted.Map(m, c); } + + #endregion + + #region IIndexed Members + + /// + /// + /// + /// The i'th item of the wrapped sorted collection + public T this[int i] => indexedsorted[i]; + /// - /// Read-only wrapper for indexed sorted collections /// - /// Suitable for wrapping TreeSet, TreeBag and SortedArray /// - public class GuardedIndexedSorted : GuardedSorted, IIndexedSorted - { - #region Fields - - private readonly IIndexedSorted indexedsorted; - - #endregion - - #region Constructor - - /// - /// Wrap an indexed sorted collection in a read-only wrapper - /// - /// the indexed sorted collection - public GuardedIndexedSorted(IIndexedSorted list) - : base(list) - { indexedsorted = list; } - - #endregion - - #region IIndexedSorted Members - - /// - /// Get the specified range from the wrapped collection. - /// (The current implementation erroneously does not wrap the result.) - /// - /// - /// - public new IDirectedCollectionValue RangeFrom(T bot) - { return indexedsorted.RangeFrom(bot); } - - - /// - /// Get the specified range from the wrapped collection. - /// (The current implementation erroneously does not wrap the result.) - /// - /// - /// - /// - public new IDirectedCollectionValue RangeFromTo(T bot, T top) - { return indexedsorted.RangeFromTo(bot, top); } - - - /// - /// Get the specified range from the wrapped collection. - /// (The current implementation erroneously does not wrap the result.) - /// - /// - /// - public new IDirectedCollectionValue RangeTo(T top) - { return indexedsorted.RangeTo(top); } - - - /// - /// Report the number of items in the specified range of the wrapped collection - /// - /// - /// - public int CountFrom(T bot) { return indexedsorted.CountFrom(bot); } - - - /// - /// Report the number of items in the specified range of the wrapped collection - /// - /// - /// - /// - public int CountFromTo(T bot, T top) { return indexedsorted.CountFromTo(bot, top); } - - - /// - /// Report the number of items in the specified range of the wrapped collection - /// - /// - /// - public int CountTo(T top) { return indexedsorted.CountTo(top); } - - - /// - /// Run FindAll on the wrapped collection with the indicated filter. - /// The result will not be read-only. - /// - /// - /// - public IIndexedSorted FindAll(Func f) - { return indexedsorted.FindAll(f); } - - - /// - /// Run Map on the wrapped collection with the indicated mapper. - /// The result will not be read-only. - /// - /// - /// The comparer to use in the result - /// - public IIndexedSorted Map(Func m, System.Collections.Generic.IComparer c) - { return indexedsorted.Map(m, c); } - - #endregion - - #region IIndexed Members - - /// - /// - /// - /// The i'th item of the wrapped sorted collection - public T this[int i] => indexedsorted[i]; - - /// - /// - /// - /// - public virtual Speed IndexingSpeed => indexedsorted.IndexingSpeed; - - /// - /// A directed collection of the items in the indicated interval of the wrapped collection - public IDirectedCollectionValue this[int start, int end] => new GuardedDirectedCollectionValue(indexedsorted[start, end]); - - - /// - /// Find the (first) index of an item in the wrapped collection - /// - /// - /// - public int IndexOf(T item) { return indexedsorted.IndexOf(item); } - - - /// - /// Find the last index of an item in the wrapped collection - /// - /// - /// - public int LastIndexOf(T item) { return indexedsorted.LastIndexOf(item); } - - - /// - /// - /// since this is a read-only wrapper - /// - /// - public T RemoveAt(int i) - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - - - /// - /// - /// since this is a read-only wrapper - /// - /// - public void RemoveInterval(int start, int count) - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + /// + public virtual Speed IndexingSpeed => indexedsorted.IndexingSpeed; + + /// + /// A directed collection of the items in the indicated interval of the wrapped collection + public IDirectedCollectionValue this[int start, int end] => new GuardedDirectedCollectionValue(indexedsorted[start, end]); + + + /// + /// Find the (first) index of an item in the wrapped collection + /// + /// + /// + public int IndexOf(T item) { return indexedsorted.IndexOf(item); } + + + /// + /// Find the last index of an item in the wrapped collection + /// + /// + /// + public int LastIndexOf(T item) { return indexedsorted.LastIndexOf(item); } + + + /// + /// + /// since this is a read-only wrapper + /// + /// + public T RemoveAt(int i) + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + + + /// + /// + /// since this is a read-only wrapper + /// + /// + public void RemoveInterval(int start, int count) + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + + #endregion + + #region IDirectedEnumerable Members - #endregion - - #region IDirectedEnumerable Members - - IDirectedEnumerable IDirectedEnumerable.Backwards() - { return Backwards(); } + IDirectedEnumerable IDirectedEnumerable.Backwards() + { return Backwards(); } - #endregion - } + #endregion } \ No newline at end of file diff --git a/C5/Wrappers/GuardedList.cs b/C5/Wrappers/GuardedList.cs index f62d4270..55444e06 100644 --- a/C5/Wrappers/GuardedList.cs +++ b/C5/Wrappers/GuardedList.cs @@ -1,597 +1,605 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// A read-only wrapper for a generic list collection +/// Suitable as a wrapper for LinkedList, HashedLinkedList, ArrayList and HashedArray. +/// , +/// , +/// or +/// . +/// +/// +public class GuardedList : GuardedSequenced, IList, System.Collections.Generic.IList { + #region Fields + + private readonly IList innerlist; + private readonly GuardedList? underlying; + private readonly bool slidableView = false; + + #endregion + + #region Constructor + /// - /// A read-only wrapper for a generic list collection - /// Suitable as a wrapper for LinkedList, HashedLinkedList, ArrayList and HashedArray. - /// , - /// , - /// or - /// . - /// + /// Wrap a list in a read-only wrapper. A list gets wrapped as read-only, + /// a list view gets wrapped as read-only and non-slidable. /// - public class GuardedList : GuardedSequenced, IList, System.Collections.Generic.IList + /// The list + public GuardedList(IList list) + : base(list) { - #region Fields + innerlist = list; + // If wrapping a list view, make innerlist = the view, and make + // underlying = a guarded version of the view's underlying list + if (list.Underlying != null) + { + underlying = new GuardedList(list.Underlying, null, false); + } + } - private readonly IList innerlist; - private readonly GuardedList? underlying; - private readonly bool slidableView = false; + private GuardedList(IList list, GuardedList? underlying, bool slidableView) + : base(list) + { + innerlist = list; this.underlying = underlying; this.slidableView = slidableView; + } + #endregion - #endregion + #region IList Members - #region Constructor + /// + /// + /// + /// The first item of the wrapped list + public T First => innerlist.First; - /// - /// Wrap a list in a read-only wrapper. A list gets wrapped as read-only, - /// a list view gets wrapped as read-only and non-slidable. - /// - /// The list - public GuardedList(IList list) - : base(list) - { - innerlist = list; - // If wrapping a list view, make innerlist = the view, and make - // underlying = a guarded version of the view's underlying list - if (list.Underlying != null) - { - underlying = new GuardedList(list.Underlying, null, false); - } - } - private GuardedList(IList list, GuardedList? underlying, bool slidableView) - : base(list) - { - innerlist = list; this.underlying = underlying; this.slidableView = slidableView; - } - #endregion + /// + /// + /// + /// The last item of the wrapped list + public T Last => innerlist.Last; - #region IList Members - /// - /// - /// - /// The first item of the wrapped list - public T First => innerlist.First; + /// + /// + /// if used as setter + /// True if wrapped list has FIFO semantics for the Add(T item) and Remove() methods + public bool FIFO + { + get => innerlist.FIFO; + set => throw new ReadOnlyCollectionException("List is read only"); + } + /// + /// + /// + public virtual bool IsFixedSize => true; - /// - /// - /// - /// The last item of the wrapped list - public T Last => innerlist.Last; + /// + /// + /// if used as setter + /// The i'th item of the wrapped list + public T this[int i] + { + get => innerlist[i]; + set => throw new ReadOnlyCollectionException("List is read only"); + } - /// - /// - /// if used as setter - /// True if wrapped list has FIFO semantics for the Add(T item) and Remove() methods - public bool FIFO - { - get => innerlist.FIFO; - set => throw new ReadOnlyCollectionException("List is read only"); - } + /// + /// + /// + /// + public virtual Speed IndexingSpeed => innerlist.IndexingSpeed; - /// - /// - /// - public virtual bool IsFixedSize => true; + /// + /// + /// since this is a read-only wrapper + /// + /// + public void Insert(int index, T item) + { + throw new ReadOnlyCollectionException(); + } + /// + /// + /// since this is a read-only wrapper + /// + /// + public void Insert(IList pointer, T item) + { + throw new ReadOnlyCollectionException(); + } - /// - /// - /// if used as setter - /// The i'th item of the wrapped list - public T this[int i] - { - get => innerlist[i]; - set => throw new ReadOnlyCollectionException("List is read only"); - } + /// + /// + /// since this is a read-only wrapper + /// + public void InsertFirst(T item) + { + throw new ReadOnlyCollectionException("List is read only"); + } - /// - /// - /// - /// - public virtual Speed IndexingSpeed => innerlist.IndexingSpeed; - - /// - /// - /// since this is a read-only wrapper - /// - /// - public void Insert(int index, T item) - { - throw new ReadOnlyCollectionException(); - } + /// + /// + /// since this is a read-only wrapper + /// + public void InsertLast(T item) + { + throw new ReadOnlyCollectionException("List is read only"); + } - /// - /// - /// since this is a read-only wrapper - /// - /// - public void Insert(IList pointer, T item) - { - throw new ReadOnlyCollectionException(); - } + /// + /// + /// since this is a read-only wrapper + /// + /// + public void InsertBefore(T item, T target) + { + throw new ReadOnlyCollectionException("List is read only"); + } - /// - /// - /// since this is a read-only wrapper - /// - public void InsertFirst(T item) - { - throw new ReadOnlyCollectionException("List is read only"); - } - /// - /// - /// since this is a read-only wrapper - /// - public void InsertLast(T item) - { - throw new ReadOnlyCollectionException("List is read only"); - } + /// + /// + /// since this is a read-only wrapper + /// + /// + public void InsertAfter(T item, T target) + { + throw new ReadOnlyCollectionException("List is read only"); + } - /// - /// - /// since this is a read-only wrapper - /// - /// - public void InsertBefore(T item, T target) - { - throw new ReadOnlyCollectionException("List is read only"); - } + /// + /// + /// since this is a read-only wrapper + /// + /// + public void InsertAll(int i, System.Collections.Generic.IEnumerable items) + { throw new ReadOnlyCollectionException("List is read only"); } - /// - /// - /// since this is a read-only wrapper - /// - /// - public void InsertAfter(T item, T target) - { - throw new ReadOnlyCollectionException("List is read only"); - } + /// + /// Perform FindAll on the wrapped list. The result is not necessarily read-only. + /// + /// The filter to use + /// + public IList FindAll(Func filter) { return innerlist.FindAll(filter); } - /// - /// - /// since this is a read-only wrapper - /// - /// - public void InsertAll(int i, System.Collections.Generic.IEnumerable items) - { throw new ReadOnlyCollectionException("List is read only"); } - - - /// - /// Perform FindAll on the wrapped list. The result is not necessarily read-only. - /// - /// The filter to use - /// - public IList FindAll(Func filter) { return innerlist.FindAll(filter); } - - - /// - /// Perform Map on the wrapped list. The result is not necessarily read-only. - /// - /// The type of items of the new list - /// The mapper to use. - /// The mapped list - public IList Map(Func mapper) { return innerlist.Map(mapper); } - - /// - /// Perform Map on the wrapped list. The result is not necessarily read-only. - /// - /// The type of items of the new list - /// The delegate defining the map. - /// The itemequalityComparer to use for the new list - /// The new list. - public IList Map(Func mapper, System.Collections.Generic.IEqualityComparer itemequalityComparer) { return innerlist.Map(mapper, itemequalityComparer); } - - /// - /// - /// since this is a read-only wrapper - /// - public T Remove() { throw new ReadOnlyCollectionException("List is read only"); } - - - /// - /// - /// since this is a read-only wrapper - /// - public T RemoveFirst() { throw new ReadOnlyCollectionException("List is read only"); } - - - /// - /// - /// since this is a read-only wrapper - /// - public T RemoveLast() { throw new ReadOnlyCollectionException("List is read only"); } - - - /// - /// Create the indicated view on the wrapped list and wrap it read-only. - /// - /// - /// - /// - public IList? View(int start, int count) - { - IList? view = innerlist.View(start, count); - return view == null ? null : new GuardedList(view, underlying ?? this, true); - } - /// - /// Create the indicated view on the wrapped list and wrap it read-only. - /// - /// - /// - public IList? ViewOf(T item) - { - IList? view = innerlist.ViewOf(item); - return view == null ? null : new GuardedList(view, underlying ?? this, true); - } + /// + /// Perform Map on the wrapped list. The result is not necessarily read-only. + /// + /// The type of items of the new list + /// The mapper to use. + /// The mapped list + public IList Map(Func mapper) { return innerlist.Map(mapper); } - /// - /// Create the indicated view on the wrapped list and wrap it read-only. - /// - /// - /// - public IList? LastViewOf(T item) - { - IList? view = innerlist.LastViewOf(item); - return view == null ? null : new GuardedList(view, underlying ?? this, true); - } + /// + /// Perform Map on the wrapped list. The result is not necessarily read-only. + /// + /// The type of items of the new list + /// The delegate defining the map. + /// The itemequalityComparer to use for the new list + /// The new list. + public IList Map(Func mapper, System.Collections.Generic.IEqualityComparer itemequalityComparer) { return innerlist.Map(mapper, itemequalityComparer); } + + /// + /// + /// since this is a read-only wrapper + /// + public T Remove() { throw new ReadOnlyCollectionException("List is read only"); } - /// - /// - /// The wrapped underlying list of the wrapped view - public IList? Underlying => underlying; + /// + /// + /// since this is a read-only wrapper + /// + public T RemoveFirst() { throw new ReadOnlyCollectionException("List is read only"); } - /// - /// - /// - /// The offset of the wrapped list as a view. - public int Offset => innerlist.Offset; + /// + /// + /// since this is a read-only wrapper + /// + public T RemoveLast() { throw new ReadOnlyCollectionException("List is read only"); } - /// - /// - /// - /// - public virtual bool IsValid => innerlist.IsValid; - /// - /// - /// if this is a wrapped view and not a view that was made on a wrapper - /// - public IList Slide(int offset) + /// + /// Create the indicated view on the wrapped list and wrap it read-only. + /// + /// + /// + /// + public IList? View(int start, int count) + { + IList? view = innerlist.View(start, count); + return view == null ? null : new GuardedList(view, underlying ?? this, true); + } + + /// + /// Create the indicated view on the wrapped list and wrap it read-only. + /// + /// + /// + public IList? ViewOf(T item) + { + IList? view = innerlist.ViewOf(item); + return view == null ? null : new GuardedList(view, underlying ?? this, true); + } + + /// + /// Create the indicated view on the wrapped list and wrap it read-only. + /// + /// + /// + public IList? LastViewOf(T item) + { + IList? view = innerlist.LastViewOf(item); + return view == null ? null : new GuardedList(view, underlying ?? this, true); + } + + + /// + /// + /// The wrapped underlying list of the wrapped view + public IList? Underlying => underlying; + + + /// + /// + /// + /// The offset of the wrapped list as a view. + public int Offset => innerlist.Offset; + + /// + /// + /// + /// + public virtual bool IsValid => innerlist.IsValid; + + /// + /// + /// if this is a wrapped view and not a view that was made on a wrapper + /// + public IList Slide(int offset) + { + if (slidableView) { - if (slidableView) - { - innerlist.Slide(offset); - return this; - } - else - { - throw new ReadOnlyCollectionException("List is read only"); - } + innerlist.Slide(offset); + return this; } + else + { + throw new ReadOnlyCollectionException("List is read only"); + } + } - /// - /// - /// since this is a read-only wrapper - /// - /// - public IList Slide(int offset, int size) + /// + /// + /// since this is a read-only wrapper + /// + /// + public IList Slide(int offset, int size) + { + if (slidableView) { - if (slidableView) - { - innerlist.Slide(offset, size); - return this; - } - else - { - throw new ReadOnlyCollectionException("List is read only"); - } + innerlist.Slide(offset, size); + return this; } + else + { + throw new ReadOnlyCollectionException("List is read only"); + } + } - /// - /// - /// - /// since this is a read-only wrapper - /// - /// - public bool TrySlide(int offset) + /// + /// + /// + /// since this is a read-only wrapper + /// + /// + public bool TrySlide(int offset) + { + if (slidableView) { - if (slidableView) - { - return innerlist.TrySlide(offset); - } - else - { - throw new ReadOnlyCollectionException("List is read only"); - } + return innerlist.TrySlide(offset); } - - /// - /// - /// - /// since this is a read-only wrapper - /// - /// - /// - public bool TrySlide(int offset, int size) + else { - if (slidableView) - { - return innerlist.TrySlide(offset, size); - } - else - { - throw new ReadOnlyCollectionException("List is read only"); - } + throw new ReadOnlyCollectionException("List is read only"); } + } - /// - /// - /// - /// - /// - public IList? Span(IList otherView) + /// + /// + /// + /// since this is a read-only wrapper + /// + /// + /// + public bool TrySlide(int offset, int size) + { + if (slidableView) + { + return innerlist.TrySlide(offset, size); + } + else { - if (!(otherView is GuardedList otherGuardedList)) - { - throw new IncompatibleViewException(); - } - - IList? span = innerlist.Span(otherGuardedList.innerlist); - if (span == null) - { - return null; - } - - return new GuardedList(span, underlying ?? otherGuardedList.underlying ?? this, true); + throw new ReadOnlyCollectionException("List is read only"); } + } - /// - /// since this is a read-only wrapper - /// - public void Reverse() { throw new ReadOnlyCollectionException("List is read only"); } + /// + /// + /// + /// + /// + public IList? Span(IList otherView) + { + if (!(otherView is GuardedList otherGuardedList)) + { + throw new IncompatibleViewException(); + } + IList? span = innerlist.Span(otherGuardedList.innerlist); + if (span == null) + { + return null; + } - /// - /// - /// since this is a read-only wrapper - /// - /// - public void Reverse(int start, int count) - { throw new ReadOnlyCollectionException("List is read only"); } + return new GuardedList(span, underlying ?? otherGuardedList.underlying ?? this, true); + } + /// + /// since this is a read-only wrapper + /// + public void Reverse() { throw new ReadOnlyCollectionException("List is read only"); } - /// - /// Check if wrapped list is sorted according to the default sorting order - /// for the item type T, as defined by the class - /// - /// if T is not comparable - /// True if the list is sorted, else false. - public bool IsSorted() { return innerlist.IsSorted(System.Collections.Generic.Comparer.Default); } - /// - /// Check if wrapped list is sorted - /// - /// The sorting order to use - /// True if sorted - public bool IsSorted(System.Collections.Generic.IComparer c) { return innerlist.IsSorted(c); } + /// + /// + /// since this is a read-only wrapper + /// + /// + public void Reverse(int start, int count) + { throw new ReadOnlyCollectionException("List is read only"); } - /// - /// - /// since this is a read-only wrapper - public void Sort() - { throw new ReadOnlyCollectionException("List is read only"); } + /// + /// Check if wrapped list is sorted according to the default sorting order + /// for the item type T, as defined by the class + /// + /// if T is not comparable + /// True if the list is sorted, else false. + public bool IsSorted() { return innerlist.IsSorted(System.Collections.Generic.Comparer.Default); } + /// + /// Check if wrapped list is sorted + /// + /// The sorting order to use + /// True if sorted + public bool IsSorted(System.Collections.Generic.IComparer c) { return innerlist.IsSorted(c); } - /// - /// - /// since this is a read-only wrapper - /// - public void Sort(System.Collections.Generic.IComparer c) - { throw new ReadOnlyCollectionException("List is read only"); } - /// - /// - /// since this is a read-only wrapper - public void Shuffle() - { throw new ReadOnlyCollectionException("List is read only"); } + /// + /// + /// since this is a read-only wrapper + public void Sort() + { throw new ReadOnlyCollectionException("List is read only"); } - /// - /// - /// since this is a read-only wrapper - /// - public void Shuffle(Random rnd) - { throw new ReadOnlyCollectionException("List is read only"); } + /// + /// + /// since this is a read-only wrapper + /// + public void Sort(System.Collections.Generic.IComparer c) + { throw new ReadOnlyCollectionException("List is read only"); } - #endregion + /// + /// + /// since this is a read-only wrapper + public void Shuffle() + { throw new ReadOnlyCollectionException("List is read only"); } - #region IIndexed Members - /// - /// A directed collection of the items in the indicated interval of the wrapped collection - public IDirectedCollectionValue this[int start, int end] => new GuardedDirectedCollectionValue(innerlist[start, end]); + /// + /// + /// since this is a read-only wrapper + /// + public void Shuffle(Random rnd) + { throw new ReadOnlyCollectionException("List is read only"); } + #endregion - /// - /// Find the (first) index of an item in the wrapped collection - /// - /// - /// - public int IndexOf(T item) { return innerlist.IndexOf(item); } + #region IIndexed Members + /// + /// A directed collection of the items in the indicated interval of the wrapped collection + public IDirectedCollectionValue this[int start, int end] => new GuardedDirectedCollectionValue(innerlist[start, end]); - /// - /// Find the last index of an item in the wrapped collection - /// - /// - /// - public int LastIndexOf(T item) { return innerlist.LastIndexOf(item); } + /// + /// Find the (first) index of an item in the wrapped collection + /// + /// + /// + public int IndexOf(T item) { return innerlist.IndexOf(item); } - /// - /// - /// since this is a read-only wrapper - /// - /// - public T RemoveAt(int i) - { throw new ReadOnlyCollectionException("List is read only"); } + /// + /// Find the last index of an item in the wrapped collection + /// + /// + /// + public int LastIndexOf(T item) { return innerlist.LastIndexOf(item); } - /// - /// - /// since this is a read-only wrapper - /// - /// - public void RemoveInterval(int start, int count) - { throw new ReadOnlyCollectionException("List is read only"); } - #endregion + /// + /// + /// since this is a read-only wrapper + /// + /// + public T RemoveAt(int i) + { throw new ReadOnlyCollectionException("List is read only"); } - #region IDirectedEnumerable Members - IDirectedEnumerable IDirectedEnumerable.Backwards() - { return Backwards(); } + /// + /// + /// since this is a read-only wrapper + /// + /// + public void RemoveInterval(int start, int count) + { throw new ReadOnlyCollectionException("List is read only"); } - #endregion + #endregion - #region IStack Members + #region IDirectedEnumerable Members + IDirectedEnumerable IDirectedEnumerable.Backwards() + { return Backwards(); } - /// - /// - /// - /// since this is a read-only wrapper - /// - - public void Push(T item) - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + #endregion - /// - /// - /// - /// since this is a read-only wrapper - /// - - public T Pop() - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + #region IStack Members - #endregion - #region IQueue Members + /// + /// + /// + /// since this is a read-only wrapper + /// - + public void Push(T item) + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - /// - /// - /// - /// since this is a read-only wrapper - /// - - public void Enqueue(T item) - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + /// + /// + /// + /// since this is a read-only wrapper + /// - + public T Pop() + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - /// - /// - /// - /// since this is a read-only wrapper - /// - - public T Dequeue() - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + #endregion - #endregion + #region IQueue Members - #region IDisposable Members + /// + /// + /// + /// since this is a read-only wrapper + /// - + public void Enqueue(T item) + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - /// - /// Ignore: this may be called by a foreach or using statement. - /// - public void Dispose() { } + /// + /// + /// + /// since this is a read-only wrapper + /// - + public T Dequeue() + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - #endregion + #endregion - #region System.Collections.Generic.IList Members + #region IDisposable Members - void System.Collections.Generic.IList.RemoveAt(int index) - { - throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); - } + /// + /// Ignore: this may be called by a foreach or using statement. + /// + public void Dispose() { } - void System.Collections.Generic.ICollection.Add(T item) - { - throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); - } + #endregion - #endregion + #region System.Collections.Generic.IList Members - #region System.Collections.ICollection Members + void System.Collections.Generic.IList.RemoveAt(int index) + { + throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); + } - bool System.Collections.ICollection.IsSynchronized => false; + void System.Collections.Generic.ICollection.Add(T item) + { + throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); + } - [Obsolete] - Object System.Collections.ICollection.SyncRoot => innerlist.SyncRoot; + #endregion - void System.Collections.ICollection.CopyTo(Array arr, int index) - { - if (index < 0 || index + Count > arr.Length) - { - throw new ArgumentOutOfRangeException(); - } - - foreach (T item in this) - { - arr.SetValue(item, index++); - } - } + #region System.Collections.ICollection Members - #endregion + bool System.Collections.ICollection.IsSynchronized => false; - #region System.Collections.IList Members + [Obsolete] + object System.Collections.ICollection.SyncRoot => innerlist.SyncRoot; - Object System.Collections.IList.this[int index] + void System.Collections.ICollection.CopyTo(Array arr, int index) + { + if (index < 0 || index + Count > arr.Length) { - get => this[index]!; - set => throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); + throw new ArgumentOutOfRangeException(); } - int System.Collections.IList.Add(Object o) + foreach (T item in this) { - throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); + arr.SetValue(item, index++); } + } - bool System.Collections.IList.Contains(Object o) - { - return Contains((T)o); - } + #endregion - int System.Collections.IList.IndexOf(Object o) - { - return Math.Max(-1, IndexOf((T)o)); - } + #region System.Collections.IList Members - void System.Collections.IList.Insert(int index, Object o) - { - throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); - } + object? System.Collections.IList.this[int index] + { + get => this[index]!; + set => throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); + } - void System.Collections.IList.Remove(Object o) - { - throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); - } + int System.Collections.IList.Add(object? value) + { + throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); + } - void System.Collections.IList.RemoveAt(int index) - { - throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); - } + bool System.Collections.IList.Contains(object? value) + { + if (value is null && default(T) is not null) return false; + if (value is not T) return false; - #endregion + return Contains((T)value); } + + int System.Collections.IList.IndexOf(object? value) + { + if (value is null && default(T) is not null) return -1; + if (value is not T) return -1; + + return Math.Max(-1, IndexOf((T)value)); + } + + void System.Collections.IList.Insert(int index, object? value) + { + throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); + } + + void System.Collections.IList.Remove(object? value) + { + throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); + } + + void System.Collections.IList.RemoveAt(int index) + { + throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); + } + + #endregion } \ No newline at end of file diff --git a/C5/Wrappers/GuardedQueue.cs b/C5/Wrappers/GuardedQueue.cs index 5680d814..8bdcfd6d 100644 --- a/C5/Wrappers/GuardedQueue.cs +++ b/C5/Wrappers/GuardedQueue.cs @@ -1,61 +1,61 @@ -using System; - -namespace C5 +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + +namespace C5; + +/// +/// A read-only wrapper for a generic indexable queue (allows indexing). +/// +/// Suitable for wrapping a +/// +/// The item type. +public class GuardedQueue : GuardedDirectedCollectionValue, IQueue { + #region Fields + + private readonly IQueue queue; + + #endregion + + #region Constructor + /// - /// A read-only wrapper for a generic indexable queue (allows indexing). - /// - /// Suitable for wrapping a + /// Wrap a queue in a read-only wrapper /// - /// The item type. - public class GuardedQueue : GuardedDirectedCollectionValue, IQueue - { - #region Fields - - private readonly IQueue queue; - - #endregion - - #region Constructor - - /// - /// Wrap a queue in a read-only wrapper - /// - /// The queue - public GuardedQueue(IQueue queue) : base(queue) { this.queue = queue; } - - #endregion - - #region IQueue Members - /// - /// - /// - /// - public bool AllowsDuplicates => queue.AllowsDuplicates; - - /// - /// Index into the wrapped queue - /// - /// - /// - public T this[int i] => queue[i]; - - /// - /// - /// - /// since this is a read-only wrapper - /// - - public void Enqueue(T item) - { throw new ReadOnlyCollectionException("Queue cannot be modified through this guard object"); } - - /// - /// - /// - /// since this is a read-only wrapper - /// - - public T Dequeue() - { throw new ReadOnlyCollectionException("Queue cannot be modified through this guard object"); } - - #endregion - } + /// The queue + public GuardedQueue(IQueue queue) : base(queue) { this.queue = queue; } + + #endregion + + #region IQueue Members + /// + /// + /// + /// + public bool AllowsDuplicates => queue.AllowsDuplicates; + + /// + /// Index into the wrapped queue + /// + /// + /// + public T this[int i] => queue[i]; + + /// + /// + /// + /// since this is a read-only wrapper + /// - + public void Enqueue(T item) + { throw new ReadOnlyCollectionException("Queue cannot be modified through this guard object"); } + + /// + /// + /// + /// since this is a read-only wrapper + /// - + public T Dequeue() + { throw new ReadOnlyCollectionException("Queue cannot be modified through this guard object"); } + + #endregion } \ No newline at end of file diff --git a/C5/Wrappers/GuardedSequenced.cs b/C5/Wrappers/GuardedSequenced.cs index 9b3623df..e52aa824 100644 --- a/C5/Wrappers/GuardedSequenced.cs +++ b/C5/Wrappers/GuardedSequenced.cs @@ -1,137 +1,139 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// A read-only wrapper for a sequenced collection +/// +/// This is mainly interesting as a base of other guard classes +/// +public class GuardedSequenced : GuardedCollection, ISequenced { - /// - /// A read-only wrapper for a sequenced collection - /// - /// This is mainly interesting as a base of other guard classes - /// - public class GuardedSequenced : GuardedCollection, ISequenced - { - #region Fields + #region Fields - private readonly ISequenced sequenced; + private readonly ISequenced sequenced; - #endregion + #endregion - #region Constructor + #region Constructor - /// - /// Wrap a sequenced collection in a read-only wrapper - /// - /// - public GuardedSequenced(ISequenced sorted) : base(sorted) { sequenced = sorted; } + /// + /// Wrap a sequenced collection in a read-only wrapper + /// + /// + public GuardedSequenced(ISequenced sorted) : base(sorted) { sequenced = sorted; } - #endregion + #endregion + + /// + /// Check if there exists an item that satisfies a + /// specific predicate in this collection and return the index of the first one. + /// + /// A delegate + /// ( with R == bool) defining the predicate + /// the index, if found, a negative value else + public int FindIndex(Func predicate) + { + if (sequenced is IIndexed indexed) + { + return indexed.FindIndex(predicate); + } - /// - /// Check if there exists an item that satisfies a - /// specific predicate in this collection and return the index of the first one. - /// - /// A delegate - /// ( with R == bool) defining the predicate - /// the index, if found, a negative value else - public int FindIndex(Func predicate) + int index = 0; + foreach (T item in this) { - if (sequenced is IIndexed indexed) + if (predicate(item)) { - return indexed.FindIndex(predicate); + return index; } - int index = 0; - foreach (T item in this) - { - if (predicate(item)) - { - return index; - } + index++; + } + return -1; + } - index++; - } - return -1; + /// + /// Check if there exists an item that satisfies a + /// specific predicate in this collection and return the index of the last one. + /// + /// A delegate + /// ( with R == bool) defining the predicate + /// the index, if found, a negative value else + public int FindLastIndex(Func predicate) + { + if (sequenced is IIndexed indexed) + { + return indexed.FindLastIndex(predicate); } - /// - /// Check if there exists an item that satisfies a - /// specific predicate in this collection and return the index of the last one. - /// - /// A delegate - /// ( with R == bool) defining the predicate - /// the index, if found, a negative value else - public int FindLastIndex(Func predicate) + int index = Count - 1; + foreach (T item in Backwards()) { - if (sequenced is IIndexed indexed) + if (predicate(item)) { - return indexed.FindLastIndex(predicate); + return index; } - int index = Count - 1; - foreach (T item in Backwards()) - { - if (predicate(item)) - { - return index; - } - - index--; - } - return -1; + index--; } + return -1; + } - #region ISequenced Members + #region ISequenced Members - /// - /// - /// - /// - public int GetSequencedHashCode() - { return sequenced.GetSequencedHashCode(); } + /// + /// + /// + /// + public int GetSequencedHashCode() + { return sequenced.GetSequencedHashCode(); } - /// - /// - /// - /// - /// - public bool SequencedEquals(ISequenced that) - { return sequenced.SequencedEquals(that); } + /// + /// + /// + /// + /// + public bool SequencedEquals(ISequenced that) + { return sequenced.SequencedEquals(that); } - #endregion + #endregion - #region IDirectedCollection Members + #region IDirectedCollection Members - /// - /// Get a collection that enumerates the wrapped collection in the opposite direction - /// - /// The mirrored collection - public virtual IDirectedCollectionValue Backwards() - { return new GuardedDirectedCollectionValue(sequenced.Backwards()); } + /// + /// Get a collection that enumerates the wrapped collection in the opposite direction + /// + /// The mirrored collection + public virtual IDirectedCollectionValue Backwards() + { return new GuardedDirectedCollectionValue(sequenced.Backwards()); } - /// - /// - /// - /// - /// - /// - public virtual bool FindLast(Func predicate, out T item) { return sequenced.FindLast(predicate, out item); } + /// + /// + /// + /// + /// + /// + public virtual bool FindLast(Func predicate, out T item) { return sequenced.FindLast(predicate, out item); } - #endregion + #endregion - #region IDirectedEnumerable Members + #region IDirectedEnumerable Members - IDirectedEnumerable IDirectedEnumerable.Backwards() - { return Backwards(); } + IDirectedEnumerable IDirectedEnumerable.Backwards() + { return Backwards(); } - /// - /// Forwards if same, else Backwards - /// - /// The enumeration direction relative to the original collection. - public Direction Direction => Direction.Forwards; + /// + /// Forwards if same, else Backwards + /// + /// The enumeration direction relative to the original collection. + public Direction Direction => Direction.Forwards; - #endregion - } + #endregion } \ No newline at end of file diff --git a/C5/Wrappers/GuardedSorted.cs b/C5/Wrappers/GuardedSorted.cs index 3a0a003d..1d290212 100644 --- a/C5/Wrappers/GuardedSorted.cs +++ b/C5/Wrappers/GuardedSorted.cs @@ -1,234 +1,236 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; -namespace C5 +namespace C5; + +/// +/// A read-only wrapper for a sorted collection +/// +/// This is mainly interesting as a base of other guard classes +/// +public class GuardedSorted : GuardedSequenced, ISorted { + #region Fields + + private readonly ISorted sorted; + + #endregion + + #region Constructor + /// - /// A read-only wrapper for a sorted collection - /// - /// This is mainly interesting as a base of other guard classes - /// - public class GuardedSorted : GuardedSequenced, ISorted - { - #region Fields - - private readonly ISorted sorted; - - #endregion - - #region Constructor - - /// - /// Wrap a sorted collection in a read-only wrapper - /// - /// - public GuardedSorted(ISorted sorted) : base(sorted) { this.sorted = sorted; } - - #endregion - - #region ISorted Members - - /// - /// Find the strict predecessor of item in the guarded sorted collection, - /// that is, the greatest item in the collection smaller than the item. - /// - /// The item to find the predecessor for. - /// The predecessor, if any; otherwise the default value for T. - /// True if item has a predecessor; otherwise false. - public bool TryPredecessor(T item, out T res) { return sorted.TryPredecessor(item, out res); } - - - /// - /// Find the strict successor of item in the guarded sorted collection, - /// that is, the least item in the collection greater than the supplied value. - /// - /// The item to find the successor for. - /// The successor, if any; otherwise the default value for T. - /// True if item has a successor; otherwise false. - public bool TrySuccessor(T item, out T res) { return sorted.TrySuccessor(item, out res); } - - - /// - /// Find the weak predecessor of item in the guarded sorted collection, - /// that is, the greatest item in the collection smaller than or equal to the item. - /// - /// The item to find the weak predecessor for. - /// The weak predecessor, if any; otherwise the default value for T. - /// True if item has a weak predecessor; otherwise false. - public bool TryWeakPredecessor(T item, out T res) { return sorted.TryWeakPredecessor(item, out res); } - - - /// - /// Find the weak successor of item in the sorted collection, - /// that is, the least item in the collection greater than or equal to the supplied value. - /// - /// The item to find the weak successor for. - /// The weak successor, if any; otherwise the default value for T. - /// True if item has a weak successor; otherwise false. - public bool TryWeakSuccessor(T item, out T res) { return sorted.TryWeakSuccessor(item, out res); } - - - /// - /// Find the predecessor of the item in the wrapped sorted collection - /// - /// if no such element exists - /// The item - /// The predecessor - public T Predecessor(T item) { return sorted.Predecessor(item); } - - - /// - /// Find the Successor of the item in the wrapped sorted collection - /// - /// if no such element exists - /// The item - /// The Successor - public T Successor(T item) { return sorted.Successor(item); } - - - /// - /// Find the weak predecessor of the item in the wrapped sorted collection - /// - /// if no such element exists - /// The item - /// The weak predecessor - public T WeakPredecessor(T item) { return sorted.WeakPredecessor(item); } - - - /// - /// Find the weak Successor of the item in the wrapped sorted collection - /// - /// if no such element exists - /// The item - /// The weak Successor - public T WeakSuccessor(T item) { return sorted.WeakSuccessor(item); } - - - /// - /// Run Cut on the wrapped sorted collection - /// - /// - /// - /// - /// - /// - /// - public bool Cut(IComparable c, out T low, out bool lval, out T high, out bool hval) - { return sorted.Cut(c, out low, out lval, out high, out hval); } - - - /// - /// Get the specified range from the wrapped collection. - /// (The current implementation erroneously does not wrap the result.) - /// - /// - /// - public IDirectedEnumerable RangeFrom(T bot) { return sorted.RangeFrom(bot); } - - - /// - /// Get the specified range from the wrapped collection. - /// (The current implementation erroneously does not wrap the result.) - /// - /// - /// - /// - public IDirectedEnumerable RangeFromTo(T bot, T top) - { return sorted.RangeFromTo(bot, top); } - - - /// - /// Get the specified range from the wrapped collection. - /// (The current implementation erroneously does not wrap the result.) - /// - /// - /// - public IDirectedEnumerable RangeTo(T top) { return sorted.RangeTo(top); } - - - /// - /// Get the specified range from the wrapped collection. - /// (The current implementation erroneously does not wrap the result.) - /// - /// - public IDirectedCollectionValue RangeAll() { return sorted.RangeAll(); } - - /// - /// - /// since this is a read-only wrapper - /// - public void AddSorted(System.Collections.Generic.IEnumerable items) - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - - /// - /// - /// since this is a read-only wrapper - /// - public void RemoveRangeFrom(T low) - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - - - /// - /// - /// since this is a read-only wrapper - /// - /// - public void RemoveRangeFromTo(T low, T hi) - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - - - /// - /// - /// since this is a read-only wrapper - /// - public void RemoveRangeTo(T hi) - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - - #endregion - - #region IPriorityQueue Members - - /// - /// Find the minimum of the wrapped collection - /// - /// The minimum - public T FindMin() { return sorted.FindMin(); } - - - /// - /// - /// since this is a read-only wrapper - /// - public T DeleteMin() - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - - - /// - /// Find the maximum of the wrapped collection - /// - /// The maximum - public T FindMax() { return sorted.FindMax(); } - - - /// - /// - /// since this is a read-only wrapper - /// - public T DeleteMax() - { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } - - //TODO: we should guard the comparer! - /// - /// The comparer object supplied at creation time for the underlying collection - /// - /// The comparer - public System.Collections.Generic.IComparer Comparer => sorted.Comparer; - #endregion - - #region IDirectedEnumerable Members - - IDirectedEnumerable IDirectedEnumerable.Backwards() - { return Backwards(); } - - #endregion - } + /// Wrap a sorted collection in a read-only wrapper + /// + /// + public GuardedSorted(ISorted sorted) : base(sorted) { this.sorted = sorted; } + + #endregion + + #region ISorted Members + + /// + /// Find the strict predecessor of item in the guarded sorted collection, + /// that is, the greatest item in the collection smaller than the item. + /// + /// The item to find the predecessor for. + /// The predecessor, if any; otherwise the default value for T. + /// True if item has a predecessor; otherwise false. + public bool TryPredecessor(T item, out T res) { return sorted.TryPredecessor(item, out res); } + + + /// + /// Find the strict successor of item in the guarded sorted collection, + /// that is, the least item in the collection greater than the supplied value. + /// + /// The item to find the successor for. + /// The successor, if any; otherwise the default value for T. + /// True if item has a successor; otherwise false. + public bool TrySuccessor(T item, out T res) { return sorted.TrySuccessor(item, out res); } + + + /// + /// Find the weak predecessor of item in the guarded sorted collection, + /// that is, the greatest item in the collection smaller than or equal to the item. + /// + /// The item to find the weak predecessor for. + /// The weak predecessor, if any; otherwise the default value for T. + /// True if item has a weak predecessor; otherwise false. + public bool TryWeakPredecessor(T item, out T res) { return sorted.TryWeakPredecessor(item, out res); } + + + /// + /// Find the weak successor of item in the sorted collection, + /// that is, the least item in the collection greater than or equal to the supplied value. + /// + /// The item to find the weak successor for. + /// The weak successor, if any; otherwise the default value for T. + /// True if item has a weak successor; otherwise false. + public bool TryWeakSuccessor(T item, out T res) { return sorted.TryWeakSuccessor(item, out res); } + + + /// + /// Find the predecessor of the item in the wrapped sorted collection + /// + /// if no such element exists + /// The item + /// The predecessor + public T Predecessor(T item) { return sorted.Predecessor(item); } + + + /// + /// Find the Successor of the item in the wrapped sorted collection + /// + /// if no such element exists + /// The item + /// The Successor + public T Successor(T item) { return sorted.Successor(item); } + + + /// + /// Find the weak predecessor of the item in the wrapped sorted collection + /// + /// if no such element exists + /// The item + /// The weak predecessor + public T WeakPredecessor(T item) { return sorted.WeakPredecessor(item); } + + + /// + /// Find the weak Successor of the item in the wrapped sorted collection + /// + /// if no such element exists + /// The item + /// The weak Successor + public T WeakSuccessor(T item) { return sorted.WeakSuccessor(item); } + + + /// + /// Run Cut on the wrapped sorted collection + /// + /// + /// + /// + /// + /// + /// + public bool Cut(IComparable c, out T low, out bool lval, out T high, out bool hval) + { return sorted.Cut(c, out low, out lval, out high, out hval); } + + + /// + /// Get the specified range from the wrapped collection. + /// (The current implementation erroneously does not wrap the result.) + /// + /// + /// + public IDirectedEnumerable RangeFrom(T bot) { return sorted.RangeFrom(bot); } + + + /// + /// Get the specified range from the wrapped collection. + /// (The current implementation erroneously does not wrap the result.) + /// + /// + /// + /// + public IDirectedEnumerable RangeFromTo(T bot, T top) + { return sorted.RangeFromTo(bot, top); } + + + /// + /// Get the specified range from the wrapped collection. + /// (The current implementation erroneously does not wrap the result.) + /// + /// + /// + public IDirectedEnumerable RangeTo(T top) { return sorted.RangeTo(top); } + + + /// + /// Get the specified range from the wrapped collection. + /// (The current implementation erroneously does not wrap the result.) + /// + /// + public IDirectedCollectionValue RangeAll() { return sorted.RangeAll(); } + + /// + /// + /// since this is a read-only wrapper + /// + public void AddSorted(System.Collections.Generic.IEnumerable items) + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + + /// + /// + /// since this is a read-only wrapper + /// + public void RemoveRangeFrom(T low) + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + + + /// + /// + /// since this is a read-only wrapper + /// + /// + public void RemoveRangeFromTo(T low, T hi) + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + + + /// + /// + /// since this is a read-only wrapper + /// + public void RemoveRangeTo(T hi) + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + + #endregion + + #region IPriorityQueue Members + + /// + /// Find the minimum of the wrapped collection + /// + /// The minimum + public T FindMin() { return sorted.FindMin(); } + + + /// + /// + /// since this is a read-only wrapper + /// + public T DeleteMin() + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + + + /// + /// Find the maximum of the wrapped collection + /// + /// The maximum + public T FindMax() { return sorted.FindMax(); } + + + /// + /// + /// since this is a read-only wrapper + /// + public T DeleteMax() + { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } + + //TODO: we should guard the comparer! + /// + /// The comparer object supplied at creation time for the underlying collection + /// + /// The comparer + public System.Collections.Generic.IComparer Comparer => sorted.Comparer; + #endregion + + #region IDirectedEnumerable Members + + IDirectedEnumerable IDirectedEnumerable.Backwards() + { return Backwards(); } + + #endregion } \ No newline at end of file diff --git a/C5/Wrappers/GuardedSortedDictionary.cs b/C5/Wrappers/GuardedSortedDictionary.cs index 5269d3b5..422e1be6 100644 --- a/C5/Wrappers/GuardedSortedDictionary.cs +++ b/C5/Wrappers/GuardedSortedDictionary.cs @@ -1,228 +1,230 @@ +// This file is part of the C5 Generic Collection Library for C# and CLI +// See https://github.com/sestoft/C5/blob/master/LICENSE for licensing details. + using System; using SCG = System.Collections.Generic; -namespace C5 +namespace C5; + +/// +/// A read-only wrapper for a sorted dictionary. +/// +/// Suitable for wrapping a Dictionary. +/// +public class GuardedSortedDictionary : GuardedDictionary, ISortedDictionary { + #region Fields + + private readonly ISortedDictionary sorteddict; + + #endregion + + #region Constructor + + /// + /// Wrap a sorted dictionary in a read-only wrapper + /// + /// the dictionary + public GuardedSortedDictionary(ISortedDictionary sorteddict) + : base(sorteddict) + { + this.sorteddict = sorteddict; + } + + #endregion + + #region ISortedDictionary Members + + /// + /// The key comparer used by this dictionary. + /// + /// + public SCG.IComparer Comparer => sorteddict.Comparer; + + /// + /// The collection of keys of the wrapped dictionary + public new ISorted Keys => new GuardedSorted(sorteddict.Keys); + + /// + /// Find the entry in the dictionary whose key is the + /// predecessor of the specified key. + /// + /// The key + /// The predecessor, if any + /// True if key has a predecessor + public bool TryPredecessor(K key, out SCG.KeyValuePair res) => sorteddict.TryPredecessor(key, out res); + + /// + /// Find the entry in the dictionary whose key is the + /// successor of the specified key. + /// + /// The key + /// The successor, if any + /// True if the key has a successor + public bool TrySuccessor(K key, out SCG.KeyValuePair res) => sorteddict.TrySuccessor(key, out res); + + /// + /// Find the entry in the dictionary whose key is the + /// weak predecessor of the specified key. + /// + /// The key + /// The predecessor, if any + /// True if key has a weak predecessor + public bool TryWeakPredecessor(K key, out SCG.KeyValuePair res) => sorteddict.TryWeakPredecessor(key, out res); + + /// + /// Find the entry in the dictionary whose key is the + /// weak successor of the specified key. + /// + /// The key + /// The weak successor, if any + /// True if the key has a weak successor + public bool TryWeakSuccessor(K key, out SCG.KeyValuePair res) => sorteddict.TryWeakSuccessor(key, out res); + + /// + /// Get the entry in the wrapped dictionary whose key is the + /// predecessor of a specified key. + /// + /// if no such entry exists + /// The key + /// The entry + public SCG.KeyValuePair Predecessor(K key) => sorteddict.Predecessor(key); + + /// + /// Get the entry in the wrapped dictionary whose key is the + /// successor of a specified key. + /// + /// if no such entry exists + /// The key + /// The entry + public SCG.KeyValuePair Successor(K key) => sorteddict.Successor(key); + + /// + /// Get the entry in the wrapped dictionary whose key is the + /// weak predecessor of a specified key. + /// + /// if no such entry exists + /// The key + /// The entry + public SCG.KeyValuePair WeakPredecessor(K key) => sorteddict.WeakPredecessor(key); + + /// + /// Get the entry in the wrapped dictionary whose key is the + /// weak successor of a specified key. + /// + /// if no such entry exists + /// The key + /// The entry + public SCG.KeyValuePair WeakSuccessor(K key) => sorteddict.WeakSuccessor(key); + + /// + /// + /// + /// + public SCG.KeyValuePair FindMin() => sorteddict.FindMin(); + + /// + /// + /// + /// since this is a read-only wrapper + /// + public SCG.KeyValuePair DeleteMin() => throw new ReadOnlyCollectionException(); + /// - /// A read-only wrapper for a sorted dictionary. /// - /// Suitable for wrapping a Dictionary. /// - public class GuardedSortedDictionary : GuardedDictionary, ISortedDictionary + /// + public SCG.KeyValuePair FindMax() => sorteddict.FindMax(); + + /// + /// + /// + /// since this is a read-only wrapper + /// + public SCG.KeyValuePair DeleteMax() => throw new ReadOnlyCollectionException(); + + /// + /// + /// + /// + /// + /// + /// + /// + /// + public bool Cut(IComparable c, out SCG.KeyValuePair lowEntry, out bool lowIsValid, out SCG.KeyValuePair highEntry, out bool highIsValid) { - #region Fields - - private readonly ISortedDictionary sorteddict; - - #endregion - - #region Constructor - - /// - /// Wrap a sorted dictionary in a read-only wrapper - /// - /// the dictionary - public GuardedSortedDictionary(ISortedDictionary sorteddict) - : base(sorteddict) - { - this.sorteddict = sorteddict; - } - - #endregion - - #region ISortedDictionary Members - - /// - /// The key comparer used by this dictionary. - /// - /// - public SCG.IComparer Comparer => sorteddict.Comparer; - - /// - /// The collection of keys of the wrapped dictionary - public new ISorted Keys => new GuardedSorted(sorteddict.Keys); - - /// - /// Find the entry in the dictionary whose key is the - /// predecessor of the specified key. - /// - /// The key - /// The predecessor, if any - /// True if key has a predecessor - public bool TryPredecessor(K key, out SCG.KeyValuePair res) => sorteddict.TryPredecessor(key, out res); - - /// - /// Find the entry in the dictionary whose key is the - /// successor of the specified key. - /// - /// The key - /// The successor, if any - /// True if the key has a successor - public bool TrySuccessor(K key, out SCG.KeyValuePair res) => sorteddict.TrySuccessor(key, out res); - - /// - /// Find the entry in the dictionary whose key is the - /// weak predecessor of the specified key. - /// - /// The key - /// The predecessor, if any - /// True if key has a weak predecessor - public bool TryWeakPredecessor(K key, out SCG.KeyValuePair res) => sorteddict.TryWeakPredecessor(key, out res); - - /// - /// Find the entry in the dictionary whose key is the - /// weak successor of the specified key. - /// - /// The key - /// The weak successor, if any - /// True if the key has a weak successor - public bool TryWeakSuccessor(K key, out SCG.KeyValuePair res) => sorteddict.TryWeakSuccessor(key, out res); - - /// - /// Get the entry in the wrapped dictionary whose key is the - /// predecessor of a specified key. - /// - /// if no such entry exists - /// The key - /// The entry - public SCG.KeyValuePair Predecessor(K key) => sorteddict.Predecessor(key); - - /// - /// Get the entry in the wrapped dictionary whose key is the - /// successor of a specified key. - /// - /// if no such entry exists - /// The key - /// The entry - public SCG.KeyValuePair Successor(K key) => sorteddict.Successor(key); - - /// - /// Get the entry in the wrapped dictionary whose key is the - /// weak predecessor of a specified key. - /// - /// if no such entry exists - /// The key - /// The entry - public SCG.KeyValuePair WeakPredecessor(K key) => sorteddict.WeakPredecessor(key); - - /// - /// Get the entry in the wrapped dictionary whose key is the - /// weak successor of a specified key. - /// - /// if no such entry exists - /// The key - /// The entry - public SCG.KeyValuePair WeakSuccessor(K key) => sorteddict.WeakSuccessor(key); - - /// - /// - /// - /// - public SCG.KeyValuePair FindMin() => sorteddict.FindMin(); - - /// - /// - /// - /// since this is a read-only wrapper - /// - public SCG.KeyValuePair DeleteMin() => throw new ReadOnlyCollectionException(); - - /// - /// - /// - /// - public SCG.KeyValuePair FindMax() => sorteddict.FindMax(); - - /// - /// - /// - /// since this is a read-only wrapper - /// - public SCG.KeyValuePair DeleteMax() => throw new ReadOnlyCollectionException(); - - /// - /// - /// - /// - /// - /// - /// - /// - /// - public bool Cut(IComparable c, out SCG.KeyValuePair lowEntry, out bool lowIsValid, out SCG.KeyValuePair highEntry, out bool highIsValid) - { - return sorteddict.Cut(c, out lowEntry, out lowIsValid, out highEntry, out highIsValid); - } - - /// - /// - /// - /// - /// - public IDirectedEnumerable> RangeFrom(K bot) - { - return new GuardedDirectedEnumerable>(sorteddict.RangeFrom(bot)); - } - - /// - /// - /// - /// - /// - /// - public IDirectedEnumerable> RangeFromTo(K bot, K top) - { - return new GuardedDirectedEnumerable>(sorteddict.RangeFromTo(bot, top)); - } - - /// - /// - /// - /// - /// - public IDirectedEnumerable> RangeTo(K top) - { - return new GuardedDirectedEnumerable>(sorteddict.RangeTo(top)); - } - - /// - /// - /// - /// - public IDirectedCollectionValue> RangeAll() - { - return new GuardedDirectedCollectionValue>(sorteddict.RangeAll()); - } - - /// - /// - /// - /// since this is a read-only wrapper - /// - public void AddSorted(SCG.IEnumerable> items) => throw new ReadOnlyCollectionException(); - - /// - /// - /// - /// since this is a read-only wrapper - /// - public void RemoveRangeFrom(K low) => throw new ReadOnlyCollectionException(); - - /// - /// - /// - /// since this is a read-only wrapper - /// - /// - public void RemoveRangeFromTo(K low, K hi) => throw new ReadOnlyCollectionException(); - - /// - /// - /// - /// since this is a read-only wrapper - /// - public void RemoveRangeTo(K hi) => throw new ReadOnlyCollectionException(); - - #endregion + return sorteddict.Cut(c, out lowEntry, out lowIsValid, out highEntry, out highIsValid); } + + /// + /// + /// + /// + /// + public IDirectedEnumerable> RangeFrom(K bot) + { + return new GuardedDirectedEnumerable>(sorteddict.RangeFrom(bot)); + } + + /// + /// + /// + /// + /// + /// + public IDirectedEnumerable> RangeFromTo(K bot, K top) + { + return new GuardedDirectedEnumerable>(sorteddict.RangeFromTo(bot, top)); + } + + /// + /// + /// + /// + /// + public IDirectedEnumerable> RangeTo(K top) + { + return new GuardedDirectedEnumerable>(sorteddict.RangeTo(top)); + } + + /// + /// + /// + /// + public IDirectedCollectionValue> RangeAll() + { + return new GuardedDirectedCollectionValue>(sorteddict.RangeAll()); + } + + /// + /// + /// + /// since this is a read-only wrapper + /// + public void AddSorted(SCG.IEnumerable> items) => throw new ReadOnlyCollectionException(); + + /// + /// + /// + /// since this is a read-only wrapper + /// + public void RemoveRangeFrom(K low) => throw new ReadOnlyCollectionException(); + + /// + /// + /// + /// since this is a read-only wrapper + /// + /// + public void RemoveRangeFromTo(K low, K hi) => throw new ReadOnlyCollectionException(); + + /// + /// + /// + /// since this is a read-only wrapper + /// + public void RemoveRangeTo(K hi) => throw new ReadOnlyCollectionException(); + + #endregion } \ No newline at end of file diff --git a/README.md b/README.md index 552eef5d..1a7be4a7 100644 --- a/README.md +++ b/README.md @@ -63,4 +63,4 @@ C5 targets .NET Standard 2.0, NET 6.0, and .NET 8.0. 1. Building the unit test project requires NUnit. If you have NuGet installed it should automatically add the reference. - There are more than 1400 NUnit test cases which should execute in less than 5 seconds. All should pass. + There are more than 1500 NUnit test cases which should execute in less than 5 seconds. All should pass. diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 9105012f..a04392f4 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,5 +1,9 @@ # Release Notes for C5 Generic Collection Library for C#/CLI +## Release 3.1 of + +- C5 now targets .NET Standard 2.0 and .NET 8.0. + ## Release 3.0.0 of 2024-06-05 - C5 now targets .NET Standard 2.0, .NET 6.0 and .NET 8.0. diff --git a/azure-pipelines.yml b/azure-pipelines.yml index ab9fe75f..3fd0a9b0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,4 +1,9 @@ --- +trigger: + branches: + include: + - master + pool: vmImage: ubuntu-latest diff --git a/C5/images/icon.png b/images/icon.png similarity index 100% rename from C5/images/icon.png rename to images/icon.png
+/// An implementation of Red-Black trees as an indexed, sorted collection with bag semantics, +/// cf. CLRS. ( for an +/// implementation with set semantics). +///
+/// The comparer (sorting order) may be either natural, because the item type is comparable +/// (generic: or non-generic: System.IComparable) or it can +/// be external and supplied by the user in the constructor. +///
+/// Each distinct item is only kept in one place in the tree - together with the number +/// of times it is a member of the bag. Thus, if two items that are equal according +///