From 0277c57727d6c9b963fbad21ac40b8ece6e8c909 Mon Sep 17 00:00:00 2001 From: Vladimir Pecanac Date: Sun, 18 Oct 2026 14:19:39 +0200 Subject: [PATCH] SortedListInCSharp: move to net10.0, fix RemoveAt example, add memory comparison Retarget both projects to net10.0 and update the test packages (MSTest 4.5.1, Test SDK 18.11.0, coverlet 10.1.0). Fix the RemoveAt index so the example removes key 2, correct the non-generic exception comment, add a read-by-key-and-index method with tests, and add a program that compares the memory a SortedList, SortedDictionary and Dictionary keep for 100,000 int pairs, including a SortedList after TrimExcess(). --- .../SortedListInCSharp/GenericLists.cs | 15 +++++++-- .../SortedListInCSharp/MemoryComparison.cs | 24 ++++++++++++++ .../SortedListInCSharp/NonGenericLists.cs | 2 +- .../SortedListInCSharp/Program.cs | 32 ++++++++++++------- .../SortedListInCSharp.csproj | 3 +- .../SortedListInCSharp/Tests/Tests.csproj | 10 +++--- .../SortedListInCSharp/Tests/UnitTests.cs | 30 ++++++++++++++--- 7 files changed, 91 insertions(+), 25 deletions(-) create mode 100644 collections-csharp/SortedListInCSharp/SortedListInCSharp/MemoryComparison.cs diff --git a/collections-csharp/SortedListInCSharp/SortedListInCSharp/GenericLists.cs b/collections-csharp/SortedListInCSharp/SortedListInCSharp/GenericLists.cs index 57e94ea35a..ea586c9462 100644 --- a/collections-csharp/SortedListInCSharp/SortedListInCSharp/GenericLists.cs +++ b/collections-csharp/SortedListInCSharp/SortedListInCSharp/GenericLists.cs @@ -51,14 +51,23 @@ public static SortedList AddElementsToSortedList(SortedList RemoveElementsFromSortedList(SortedList myGenericList) { - myGenericList.RemoveAt(3); // removes (2, "") which is the item at position 3 - myGenericList.Remove(4); // removes (4, "") + myGenericList.RemoveAt(1); // removes the element with key 2, which sits at index 1 + myGenericList.Remove(4); // removes the element with key 4 - myGenericList.Clear(); // removes all the elements and returns an empty collection + myGenericList.Clear(); // removes all the elements, Count is now 0 return myGenericList; } + public static (string Third, string Fifth, int FirstKey) ReadElementsFromSortedList(SortedList myGenericList) + { + var third = myGenericList[3]; // "This is my third value" + myGenericList.TryGetValue(5, out var fifth); // false, fifth is null + var firstKey = myGenericList.GetKeyAtIndex(0); // 1 + + return (third, fifth, firstKey); + } + public static bool CheckContentsOfGenericList(SortedList myGenericList, int myKey) { return myGenericList.ContainsKey(myKey); diff --git a/collections-csharp/SortedListInCSharp/SortedListInCSharp/MemoryComparison.cs b/collections-csharp/SortedListInCSharp/SortedListInCSharp/MemoryComparison.cs new file mode 100644 index 0000000000..61f4ba6223 --- /dev/null +++ b/collections-csharp/SortedListInCSharp/SortedListInCSharp/MemoryComparison.cs @@ -0,0 +1,24 @@ +namespace SortedListInCSharp; + +public static class MemoryComparison +{ + public static long RetainedBytes(Func fill) + { + var before = GC.GetTotalMemory(forceFullCollection: true); + var collection = fill(); + var after = GC.GetTotalMemory(forceFullCollection: true); + GC.KeepAlive(collection); + + return after - before; + } + + public static IDictionary Fill(IDictionary collection, int[] keys) + { + foreach (var key in keys) + { + collection.Add(key, key); + } + + return collection; + } +} diff --git a/collections-csharp/SortedListInCSharp/SortedListInCSharp/NonGenericLists.cs b/collections-csharp/SortedListInCSharp/SortedListInCSharp/NonGenericLists.cs index 1af2ca17db..c626f4aebc 100644 --- a/collections-csharp/SortedListInCSharp/SortedListInCSharp/NonGenericLists.cs +++ b/collections-csharp/SortedListInCSharp/SortedListInCSharp/NonGenericLists.cs @@ -12,7 +12,7 @@ public static SortedList NonGenericSortedList() myNonGenericList.Add(2, "This is my second string element"); // These next lines will give us runtime exceptions... /* - myNonGenericList.Add("three", "This is my third string element"); // System.ArgumentException: 'Item has already been added. Key in dictionary: '1' Key being added: 'three'' + myNonGenericList.Add("three", "This is my third string element"); // System.InvalidOperationException: Failed to compare two elements in the array. myNonGenericList.Add(null, "There is nothing to see here"); // System.ArgumentNullException: 'Key cannot be null. (Parameter 'key')' */ diff --git a/collections-csharp/SortedListInCSharp/SortedListInCSharp/Program.cs b/collections-csharp/SortedListInCSharp/SortedListInCSharp/Program.cs index af982385b8..7f8008a952 100644 --- a/collections-csharp/SortedListInCSharp/SortedListInCSharp/Program.cs +++ b/collections-csharp/SortedListInCSharp/SortedListInCSharp/Program.cs @@ -1,13 +1,23 @@ -using System; +using SortedListInCSharp; -namespace SortedListInCSharp +var keys = Enumerable.Range(0, 100_000).ToArray(); + +var sortedList = MemoryComparison.RetainedBytes( + () => MemoryComparison.Fill(new SortedList(), keys)); +var sortedDictionary = MemoryComparison.RetainedBytes( + () => MemoryComparison.Fill(new SortedDictionary(), keys)); +var dictionary = MemoryComparison.RetainedBytes( + () => MemoryComparison.Fill(new Dictionary(), keys)); +var trimmedSortedList = MemoryComparison.RetainedBytes(() => { - class Program - { - static void Main(string[] args) - { - Console.WriteLine("Hello World!"); - } - } - -} + var list = new SortedList(); + MemoryComparison.Fill(list, keys); + list.TrimExcess(); + + return list; +}); + +Console.WriteLine($"SortedList: {sortedList:N0} bytes"); +Console.WriteLine($"SortedDictionary: {sortedDictionary:N0} bytes"); +Console.WriteLine($"Dictionary: {dictionary:N0} bytes"); +Console.WriteLine($"SortedList after TrimExcess(): {trimmedSortedList:N0} bytes"); diff --git a/collections-csharp/SortedListInCSharp/SortedListInCSharp/SortedListInCSharp.csproj b/collections-csharp/SortedListInCSharp/SortedListInCSharp/SortedListInCSharp.csproj index 41f1d5ad4b..38042621af 100644 --- a/collections-csharp/SortedListInCSharp/SortedListInCSharp/SortedListInCSharp.csproj +++ b/collections-csharp/SortedListInCSharp/SortedListInCSharp/SortedListInCSharp.csproj @@ -2,7 +2,8 @@ Exe - net6.0 + net10.0 + enable diff --git a/collections-csharp/SortedListInCSharp/Tests/Tests.csproj b/collections-csharp/SortedListInCSharp/Tests/Tests.csproj index 17469b5f7d..52a27ceb9b 100644 --- a/collections-csharp/SortedListInCSharp/Tests/Tests.csproj +++ b/collections-csharp/SortedListInCSharp/Tests/Tests.csproj @@ -1,16 +1,16 @@ - net6.0 + net10.0 false - - - - + + + + diff --git a/collections-csharp/SortedListInCSharp/Tests/UnitTests.cs b/collections-csharp/SortedListInCSharp/Tests/UnitTests.cs index a50d0febf3..6e6d094d48 100644 --- a/collections-csharp/SortedListInCSharp/Tests/UnitTests.cs +++ b/collections-csharp/SortedListInCSharp/Tests/UnitTests.cs @@ -17,7 +17,7 @@ public void whenGenericSortedListIsCalled_MethodProducesCorrectListType() var genericSortedList = GenericLists.GenericSortedList(); var expected = typeof(SortedList); var output = genericSortedList.GetType(); - Assert.AreEqual(output, expected); + Assert.AreEqual(expected, output); } [TestMethod] @@ -26,7 +26,7 @@ public void whenNonGenericSortedListIsCalled_MethodProducesCorrectListType() var genericSortedList = NonGenericLists.NonGenericSortedList(); var expected = typeof(SortedList); var output = genericSortedList.GetType(); - Assert.AreEqual(output, expected); + Assert.AreEqual(expected, output); } [TestMethod] @@ -35,7 +35,7 @@ public void whenGenericSortedListFromDictionaryIsCalled_MethodProducesCorrectLis var genericSortedList = GenericLists.GenericSortedListFromDictionary(); var expected = typeof(SortedList); var output = genericSortedList.GetType(); - Assert.AreEqual(output, expected); + Assert.AreEqual(expected, output); } [TestMethod] @@ -66,7 +66,7 @@ public void whenRemoveElementsFromSortedListIsCalled_MethodProducesCorrectListCo GenericLists.RemoveElementsFromSortedList(testGenericSortedList); - Assert.AreEqual(testGenericSortedList.Count, 0); + Assert.AreEqual(0, testGenericSortedList.Count); } [TestMethod] @@ -100,5 +100,27 @@ public void whenCheckContentsOfNonGenericListIsCalledWithValue_MethodMustReturnA testNonGenericSortedList.Add(4, "This is my fourth string element"); Assert.IsFalse(NonGenericLists.CheckContentsOfNonGenericList(testNonGenericSortedList, "This is my first string element")); } + + [TestMethod] + public void whenReadElementsFromSortedListIsCalled_MethodReturnsValuesByKeyAndIndex() + { + testGenericSortedList = new SortedList(); + GenericLists.AddElementsToSortedList(testGenericSortedList); + + var (third, fifth, firstKey) = GenericLists.ReadElementsFromSortedList(testGenericSortedList); + + Assert.AreEqual("This is my third value", third); + Assert.IsNull(fifth); + Assert.AreEqual(1, firstKey); + } + + [TestMethod] + public void whenNonGenericSortedListGetsKeyOfAnotherType_AddThrowsInvalidOperationException() + { + var nonGenericSortedList = NonGenericLists.NonGenericSortedList(); + + Assert.ThrowsExactly( + () => nonGenericSortedList.Add("three", "This is my third string element")); + } } }