From 352739c9408835d16c11eed9e40a811958c1459d Mon Sep 17 00:00:00 2001 From: Vladimir Pecanac Date: Sun, 8 Nov 2026 18:24:54 +0100 Subject: [PATCH] Selection sort: move to .NET 10 and copy the benchmark input per call Both projects target net10.0 with BenchmarkDotNet 0.15.8, MSTest 4.5.2, Microsoft.NET.Test.Sdk 18.11.0 and coverlet.collector 10.1.0. The benchmark moves into SelectionBenchmarks, which copies its generated array into a work array on every call so the random case no longer sorts already sorted data after the first call. Program.cs passes args to BenchmarkRunner. Tests use (expected, actual) order and gain an Array.Sort oracle test and edge-case rows. --- .../SelectionSort/SelectionSort/Program.cs | 2 +- .../SelectionSort/SelectionSort/Selection.cs | 78 +++++++--------- .../SelectionSort/SelectionBenchmarks.cs | 34 +++++++ .../SelectionSort/SelectionSort.csproj | 4 +- .../SelectionSortTest.csproj | 15 ++-- .../SelectionSortUnitTest.cs | 90 ++++++++++++------- 6 files changed, 138 insertions(+), 85 deletions(-) create mode 100644 csharp-algorithms/SelectionSort/SelectionSort/SelectionBenchmarks.cs diff --git a/csharp-algorithms/SelectionSort/SelectionSort/Program.cs b/csharp-algorithms/SelectionSort/SelectionSort/Program.cs index 1ccb25baf0..b2862f009c 100644 --- a/csharp-algorithms/SelectionSort/SelectionSort/Program.cs +++ b/csharp-algorithms/SelectionSort/SelectionSort/Program.cs @@ -1,4 +1,4 @@ using BenchmarkDotNet.Running; using SelectionSort; -var summary = BenchmarkRunner.Run(); \ No newline at end of file +BenchmarkRunner.Run(args: args); diff --git a/csharp-algorithms/SelectionSort/SelectionSort/Selection.cs b/csharp-algorithms/SelectionSort/SelectionSort/Selection.cs index d8d3c55fe5..2837417c22 100644 --- a/csharp-algorithms/SelectionSort/SelectionSort/Selection.cs +++ b/csharp-algorithms/SelectionSort/SelectionSort/Selection.cs @@ -1,63 +1,51 @@ -using BenchmarkDotNet.Attributes; +namespace SelectionSort; -namespace SelectionSort +public class Selection { - public class Selection + public int[] NumArray { get; set; } = []; + + public int[] SortArray() { - [ParamsSource(nameof(ArraySizes))] - public int[]? NumArray { get; set; } - int[] smallArray = AddRandomElements(200); - int[] mediumArray = AddRandomElements(2000); - int[] largeArray = AddRandomElements(200000); - int[] sortedSmallArray = AddSortedElements(200); - int[] sortedMediumArray = AddSortedElements(2000); - int[] sortedLargeArray = AddSortedElements(200000); - public IEnumerable ArraySizes => new[] { sortedSmallArray, sortedMediumArray, sortedLargeArray }; - - [Benchmark] - public int[] SortArray() + var arrayLength = NumArray.Length; + + for (int i = 0; i < arrayLength - 1; i++) { - var arrayLength = NumArray.Length; + var smallestVal = i; - for (int i = 0; i < arrayLength - 1; i++) + for (int j = i + 1; j < arrayLength; j++) { - var smallestVal = i; - - for (int j = i + 1; j < arrayLength; j++) + if (NumArray[j] < NumArray[smallestVal]) { - if (NumArray[j] < NumArray[smallestVal]) - { - smallestVal = j; - } + smallestVal = j; } - - var tempVar = NumArray[smallestVal]; - NumArray[smallestVal] = NumArray[i]; - NumArray[i] = tempVar; } - return NumArray; + + var tempVar = NumArray[smallestVal]; + NumArray[smallestVal] = NumArray[i]; + NumArray[i] = tempVar; } + return NumArray; + } - public static int[] AddRandomElements(int size) - { - var array = new int[size]; - var rand = new Random(); - var maxNum = 10000; + public static int[] AddRandomElements(int size) + { + var array = new int[size]; + var rand = new Random(); + var maxNum = 10000; - for (int i = 0; i < size; i++) - array[i] = rand.Next(maxNum + 1); + for (int i = 0; i < size; i++) + array[i] = rand.Next(maxNum + 1); - return array; - } + return array; + } - public static int[] AddSortedElements(int size) - { - var array = new int[size]; + public static int[] AddSortedElements(int size) + { + var array = new int[size]; - for (int i = 0; i < size; i++) - array[i] = i; + for (int i = 0; i < size; i++) + array[i] = i; - return array; - } + return array; } } diff --git a/csharp-algorithms/SelectionSort/SelectionSort/SelectionBenchmarks.cs b/csharp-algorithms/SelectionSort/SelectionSort/SelectionBenchmarks.cs new file mode 100644 index 0000000000..8dc53ceee3 --- /dev/null +++ b/csharp-algorithms/SelectionSort/SelectionSort/SelectionBenchmarks.cs @@ -0,0 +1,34 @@ +using BenchmarkDotNet.Attributes; + +namespace SelectionSort; + +public class SelectionBenchmarks +{ + private readonly Selection _selection = new(); + private int[] _source = []; + private int[] _work = []; + + [Params(200, 2_000, 20_000)] + public int Size { get; set; } + + [Params("Random", "Sorted")] + public string Input { get; set; } = "Random"; + + [GlobalSetup] + public void Setup() + { + _source = Input == "Random" + ? Selection.AddRandomElements(Size) + : Selection.AddSortedElements(Size); + _work = new int[Size]; + } + + [Benchmark] + public int[] SortArray() + { + _source.CopyTo(_work, 0); + _selection.NumArray = _work; + + return _selection.SortArray(); + } +} diff --git a/csharp-algorithms/SelectionSort/SelectionSort/SelectionSort.csproj b/csharp-algorithms/SelectionSort/SelectionSort/SelectionSort.csproj index 79e7148fd0..62be4f867f 100644 --- a/csharp-algorithms/SelectionSort/SelectionSort/SelectionSort.csproj +++ b/csharp-algorithms/SelectionSort/SelectionSort/SelectionSort.csproj @@ -2,13 +2,13 @@ Exe - net6.0 + net10.0 enable enable - + diff --git a/csharp-algorithms/SelectionSort/SelectionSortTest/SelectionSortTest.csproj b/csharp-algorithms/SelectionSort/SelectionSortTest/SelectionSortTest.csproj index 62f130f051..35eb28aa28 100644 --- a/csharp-algorithms/SelectionSort/SelectionSortTest/SelectionSortTest.csproj +++ b/csharp-algorithms/SelectionSort/SelectionSortTest/SelectionSortTest.csproj @@ -1,17 +1,22 @@ - net6.0 + net10.0 + enable enable false - - - - + + + + + + + + diff --git a/csharp-algorithms/SelectionSort/SelectionSortTest/SelectionSortUnitTest.cs b/csharp-algorithms/SelectionSort/SelectionSortTest/SelectionSortUnitTest.cs index 65a7613568..de36d6ec87 100644 --- a/csharp-algorithms/SelectionSort/SelectionSortTest/SelectionSortUnitTest.cs +++ b/csharp-algorithms/SelectionSort/SelectionSortTest/SelectionSortUnitTest.cs @@ -1,45 +1,71 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; using SelectionSort; -namespace SelectionSortTest +namespace SelectionSortTest; + +[TestClass] +public class SelectionSortUnitTest { - [TestClass] - public class SelectionSortUnitTest + [TestMethod] + public void GivenUnsortedArray_ThenReturnSortedArray() { - [TestMethod] - public void GivenUnsortedArray_ThenReturnSortedArray() - { - var array = new int[] { 73, 57, 49, 99, 133, 20, 1 }; - var expected = new int[] { 1, 20, 49, 57, 73, 99, 133 }; - var sortFunction = new Selection(); - sortFunction.NumArray = array; + var array = new int[] { 73, 57, 49, 99, 133, 20, 1 }; + var expected = new int[] { 1, 20, 49, 57, 73, 99, 133 }; + var sortFunction = new Selection(); + sortFunction.NumArray = array; + + var sortedArray = sortFunction.SortArray(); + + Assert.IsNotNull(sortedArray); + CollectionAssert.AreEqual(expected, sortedArray); + } - var sortedArray = sortFunction.SortArray(); + [TestMethod] + public void GivenUnsortedArray_CheckInstanceType() + { + var sortFunction = new Selection(); + sortFunction.NumArray = Selection.AddRandomElements(200); - Assert.IsNotNull(sortedArray); - CollectionAssert.AreEqual(sortedArray, expected); - } + var sortedArray = sortFunction.SortArray(); - [TestMethod] - public void GivenUnsortedArray_CheckInstanceType() - { - var sortFunction = new Selection(); - sortFunction.NumArray = Selection.AddRandomElements(200); + Assert.IsInstanceOfType(sortedArray, typeof(int[])); + } - var sortedArray = sortFunction.SortArray(); + [TestMethod] + public void GivenUnsortedArray_CheckSortedNotNull() + { + var sortFunction = new Selection(); + sortFunction.NumArray = Selection.AddRandomElements(200); - Assert.IsInstanceOfType(sortedArray, typeof(int[])); - } + var sortedArray = sortFunction.SortArray(); - [TestMethod] - public void GivenUnsortedArray_CheckSortedNotNull() - { - var sortFunction = new Selection(); - sortFunction.NumArray = Selection.AddRandomElements(200); + Assert.IsNotNull(sortedArray); + } + + [TestMethod] + public void GivenRandomArray_WhenSorted_ThenMatchesArraySort() + { + var source = Selection.AddRandomElements(500); + var expected = source.ToArray(); + Array.Sort(expected); + + var sortedArray = new Selection { NumArray = source.ToArray() }.SortArray(); + + CollectionAssert.AreEqual(expected, sortedArray); + } + + [TestMethod] + [DataRow(new int[] { })] + [DataRow(new int[] { 42 })] + [DataRow(new int[] { 5, 3, 5, 1, 3, 5 })] + [DataRow(new int[] { 1, 2, 3, 4, 5 })] + [DataRow(new int[] { 5, 4, 3, 2, 1 })] + public void GivenEdgeCaseArray_WhenSorted_ThenMatchesArraySort(int[] array) + { + var expected = array.ToArray(); + Array.Sort(expected); - var sortedArray = sortFunction.SortArray(); + var sortedArray = new Selection { NumArray = array }.SortArray(); - Assert.IsNotNull(sortedArray); - } + CollectionAssert.AreEqual(expected, sortedArray); } -} \ No newline at end of file +}