From 61c76efcf620db585f6b62bbc99dc07f305d7d33 Mon Sep 17 00:00:00 2001 From: Vladimir Pecanac Date: Mon, 14 Sep 2026 16:23:37 +0200 Subject: [PATCH] Update AddValuesToArray sample: net10.0, append methods, grow benchmark Retarget all three projects from net8.0 to net10.0 and refresh the packages: BenchmarkDotNet 0.15.8, xunit 2.9.3 with runner 4.0.0, Microsoft.NET.Test.Sdk 18.10.0, coverlet.collector 10.0.1. Fix the benchmark's size parameter. The class held three fixed 10,000-element fields while taking arraySize as an argument, so only the two Manual methods honoured it and a 1,000-element run made ArrayCopyTo throw. Replace ArgumentsSource with [Params(1_000, 10_000)] and build the source array and list in a [GlobalSetup]. Drop the dead arraySize parameter from UsingList and update its two call sites. Trim trailing whitespace in ArrayCopyTo. Add AppendWithResize, AppendWithCollectionExpression, CollectionExpression, GrowWithResize and GrowWithList, with five tests covering them, a CollectionExpression benchmark and a new GrowBenchmark class comparing Array.Resize in a loop against List.Add followed by ToArray. Run the benchmark project through BenchmarkSwitcher so either class can be selected. --- .../AddValuesToArray.Benchmark.csproj | 4 +- .../AddValuesToArrayBenchmark.cs | 48 ++++++--------- .../GrowBenchmark.cs | 17 ++++++ .../AddValuesToArray.Benchmark/Program.cs | 2 +- .../AddValuesToArray/AddValuesToArray.csproj | 2 +- .../AddValuesToArrayMethods.cs | 41 ++++++++++++- .../AddValuesToArray/Program.cs | 2 +- .../Tests/AddValuesToArrayUnitTest.cs | 59 ++++++++++++++++++- .../AddValuesToArray/Tests/Tests.csproj | 10 ++-- 9 files changed, 141 insertions(+), 44 deletions(-) create mode 100644 collections-arrays/AddValuesToArray/AddValuesToArray.Benchmark/GrowBenchmark.cs diff --git a/collections-arrays/AddValuesToArray/AddValuesToArray.Benchmark/AddValuesToArray.Benchmark.csproj b/collections-arrays/AddValuesToArray/AddValuesToArray.Benchmark/AddValuesToArray.Benchmark.csproj index a1e7746c15..f9296b3b80 100644 --- a/collections-arrays/AddValuesToArray/AddValuesToArray.Benchmark/AddValuesToArray.Benchmark.csproj +++ b/collections-arrays/AddValuesToArray/AddValuesToArray.Benchmark/AddValuesToArray.Benchmark.csproj @@ -2,13 +2,13 @@ Exe - net8.0 + net10.0 enable enable - + diff --git a/collections-arrays/AddValuesToArray/AddValuesToArray.Benchmark/AddValuesToArrayBenchmark.cs b/collections-arrays/AddValuesToArray/AddValuesToArray.Benchmark/AddValuesToArrayBenchmark.cs index 34d97caf52..4a63c925c9 100644 --- a/collections-arrays/AddValuesToArray/AddValuesToArray.Benchmark/AddValuesToArrayBenchmark.cs +++ b/collections-arrays/AddValuesToArray/AddValuesToArray.Benchmark/AddValuesToArrayBenchmark.cs @@ -6,49 +6,37 @@ namespace AddValuesToArray.Benchmark; [MemoryDiagnoser, Orderer(SummaryOrderPolicy.FastestToSlowest)] [GroupBenchmarksBy(BenchmarkDotNet.Configs.BenchmarkLogicalGroupRule.ByCategory)] [CategoriesColumn] +[HideColumns("StdDev", "Median", "Gen0", "Gen1")] public class AddValuesToArrayBenchmark { - int[] concatArray = Enumerable.Range(0, 10000).ToArray(); - int[] copyToArray = Enumerable.Range(0, 10000).ToArray(); - List list = Enumerable.Range(0, 10000).ToList(); + private int[] _source = []; + private List _list = []; - public IEnumerable ArraySize() + [Params(1_000, 10_000)] + public int ArraySize { get; set; } + + [GlobalSetup] + public void GlobalSetup() { - yield return 10_000; + _source = Enumerable.Range(0, ArraySize).ToArray(); + _list = Enumerable.Range(0, ArraySize).ToList(); } [Benchmark, BenchmarkCategory("Manual")] - [ArgumentsSource(nameof(ArraySize))] - public void ArrayIndexInitializer(int arraySize) - { - AddValuesToArrayMethods.ArrayIndexInitializer(arraySize); - } + public int[] ArrayIndexInitializer() => AddValuesToArrayMethods.ArrayIndexInitializer(ArraySize); [Benchmark, BenchmarkCategory("Manual")] - [ArgumentsSource(nameof(ArraySize))] - public void SetValueMethod(int arraySize) - { - AddValuesToArrayMethods.SetValueMethod(arraySize); - } + public int[] SetValueMethod() => AddValuesToArrayMethods.SetValueMethod(ArraySize); [Benchmark, BenchmarkCategory("Populated Collection")] - [ArgumentsSource(nameof(ArraySize))] - public void ListCollection(int arraySize) - { - AddValuesToArrayMethods.UsingList(arraySize, list); - } + public int[] ListCollection() => AddValuesToArrayMethods.UsingList(_list); [Benchmark, BenchmarkCategory("Populated Collection")] - [ArgumentsSource(nameof(ArraySize))] - public void LinqConcat(int arraySize) - { - AddValuesToArrayMethods.LinqConcat(concatArray); - } + public int[] LinqConcat() => AddValuesToArrayMethods.LinqConcat(_source); [Benchmark, BenchmarkCategory("Populated Collection")] - [ArgumentsSource(nameof(ArraySize))] - public void ArrayCopyTo(int arraySize) - { - AddValuesToArrayMethods.ArrayCopyTo(arraySize, copyToArray); - } + public int[] ArrayCopyTo() => AddValuesToArrayMethods.ArrayCopyTo(ArraySize, _source); + + [Benchmark, BenchmarkCategory("Populated Collection")] + public int[] CollectionExpression() => AddValuesToArrayMethods.CollectionExpression(_source); } diff --git a/collections-arrays/AddValuesToArray/AddValuesToArray.Benchmark/GrowBenchmark.cs b/collections-arrays/AddValuesToArray/AddValuesToArray.Benchmark/GrowBenchmark.cs new file mode 100644 index 0000000000..5d0f77db21 --- /dev/null +++ b/collections-arrays/AddValuesToArray/AddValuesToArray.Benchmark/GrowBenchmark.cs @@ -0,0 +1,17 @@ +using BenchmarkDotNet.Attributes; + +namespace AddValuesToArray.Benchmark; + +[MemoryDiagnoser] +[HideColumns("StdDev", "Median", "Gen0", "Gen1", "Gen2")] +public class GrowBenchmark +{ + [Params(1_000, 10_000)] + public int Count { get; set; } + + [Benchmark] + public int[] ResizeInALoop() => AddValuesToArrayMethods.GrowWithResize(Count); + + [Benchmark] + public int[] ListAddThenToArray() => AddValuesToArrayMethods.GrowWithList(Count); +} diff --git a/collections-arrays/AddValuesToArray/AddValuesToArray.Benchmark/Program.cs b/collections-arrays/AddValuesToArray/AddValuesToArray.Benchmark/Program.cs index 7debbe290e..d3fe4f97c7 100644 --- a/collections-arrays/AddValuesToArray/AddValuesToArray.Benchmark/Program.cs +++ b/collections-arrays/AddValuesToArray/AddValuesToArray.Benchmark/Program.cs @@ -6,6 +6,6 @@ internal class Program { static void Main(string[] args) { - BenchmarkRunner.Run(); + BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args); } } diff --git a/collections-arrays/AddValuesToArray/AddValuesToArray/AddValuesToArray.csproj b/collections-arrays/AddValuesToArray/AddValuesToArray/AddValuesToArray.csproj index 91b464afea..dfb40caafc 100644 --- a/collections-arrays/AddValuesToArray/AddValuesToArray/AddValuesToArray.csproj +++ b/collections-arrays/AddValuesToArray/AddValuesToArray/AddValuesToArray.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net10.0 enable enable diff --git a/collections-arrays/AddValuesToArray/AddValuesToArray/AddValuesToArrayMethods.cs b/collections-arrays/AddValuesToArray/AddValuesToArray/AddValuesToArrayMethods.cs index 85c587ec76..b94b12bcfb 100644 --- a/collections-arrays/AddValuesToArray/AddValuesToArray/AddValuesToArrayMethods.cs +++ b/collections-arrays/AddValuesToArray/AddValuesToArray/AddValuesToArrayMethods.cs @@ -25,7 +25,7 @@ public static int[] SetValueMethod(int arraySize) return array; } - public static int[] UsingList(int arraySize, List list) + public static int[] UsingList(List list) { return list.ToArray(); } @@ -41,10 +41,47 @@ public static int[] LinqConcat(int[] array) public static int[] ArrayCopyTo(int arraySize, int[] array) { - var array1 = new int[arraySize]; + var array1 = new int[arraySize]; array.CopyTo(array1, 0); return array1; } + + public static int[] AppendWithResize(int[] array, int value) + { + Array.Resize(ref array, array.Length + 1); + array[^1] = value; + + return array; + } + + public static int[] AppendWithCollectionExpression(int[] array, int value) => [.. array, value]; + + public static int[] CollectionExpression(int[] array) => [.. array]; + + public static int[] GrowWithResize(int count) + { + var array = Array.Empty(); + + for (var index = 0; index < count; index++) + { + Array.Resize(ref array, array.Length + 1); + array[index] = index; + } + + return array; + } + + public static int[] GrowWithList(int count) + { + var list = new List(); + + for (var index = 0; index < count; index++) + { + list.Add(index); + } + + return list.ToArray(); + } } diff --git a/collections-arrays/AddValuesToArray/AddValuesToArray/Program.cs b/collections-arrays/AddValuesToArray/AddValuesToArray/Program.cs index fc0ceb9641..7db734e000 100644 --- a/collections-arrays/AddValuesToArray/AddValuesToArray/Program.cs +++ b/collections-arrays/AddValuesToArray/AddValuesToArray/Program.cs @@ -14,7 +14,7 @@ static void Main(string[] args) Console.WriteLine(nameof(AddValuesToArrayMethods.UsingList)); var list = Enumerable.Range(0, 5).ToList(); - var array3 = AddValuesToArrayMethods.UsingList(5, list); + var array3 = AddValuesToArrayMethods.UsingList(list); Console.WriteLine(string.Join(", ", array3)); Console.WriteLine(nameof(AddValuesToArrayMethods.LinqConcat)); diff --git a/collections-arrays/AddValuesToArray/Tests/AddValuesToArrayUnitTest.cs b/collections-arrays/AddValuesToArray/Tests/AddValuesToArrayUnitTest.cs index 59475ed513..b98edd0e22 100644 --- a/collections-arrays/AddValuesToArray/Tests/AddValuesToArrayUnitTest.cs +++ b/collections-arrays/AddValuesToArray/Tests/AddValuesToArrayUnitTest.cs @@ -27,7 +27,7 @@ public void GivenAnArraySize_WhenUsingSetValueMethod_ThenValuesShouldBeAdded() public void GivenAnArraySize_WhenUsingLinqList_ThenValuesShouldBeAdded() { var list = Enumerable.Range(0, 3).ToList(); - var array = AddValuesToArrayMethods.UsingList(3, list); + var array = AddValuesToArrayMethods.UsingList(list); Assert.Equal(0, array[0]); Assert.Equal(1, array[1]); @@ -55,4 +55,59 @@ public void GivenAnArraySize_WhenUsingArrayCopyTo_ThenValuesShouldBeAdded() Assert.Equal(1, array[1]); Assert.Equal(2, array[2]); } -} \ No newline at end of file + + [Fact] + public void GivenAnArray_WhenAppendingWithResize_ThenTheOriginalArrayIsUnchanged() + { + var original = new[] { 100, 101, 102 }; + var alias = original; + + var appended = AddValuesToArrayMethods.AppendWithResize(original, 103); + + Assert.Equal(4, appended.Length); + Assert.Equal(3, alias.Length); + Assert.False(ReferenceEquals(appended, alias)); + } + + [Fact] + public void GivenAnArray_WhenAppendingWithResize_ThenTheValueIsAddedAtTheEnd() + { + var array = new[] { 100, 101, 102 }; + + var appended = AddValuesToArrayMethods.AppendWithResize(array, 103); + + Assert.Equal(new[] { 100, 101, 102, 103 }, appended); + } + + [Fact] + public void GivenAnArray_WhenAppendingWithCollectionExpression_ThenANewArrayIsReturned() + { + var array = new[] { 100, 101, 102 }; + + var appended = AddValuesToArrayMethods.AppendWithCollectionExpression(array, 103); + + Assert.Equal(new[] { 100, 101, 102, 103 }, appended); + Assert.False(ReferenceEquals(array, appended)); + } + + [Fact] + public void GivenAnArray_WhenUsingCollectionExpression_ThenACopyIsReturned() + { + var array = Enumerable.Range(0, 3).ToArray(); + + var copy = AddValuesToArrayMethods.CollectionExpression(array); + + Assert.Equal(array, copy); + Assert.False(ReferenceEquals(array, copy)); + } + + [Fact] + public void GivenACount_WhenGrowingWithResizeAndWithList_ThenBothProduceTheSameArray() + { + var resized = AddValuesToArrayMethods.GrowWithResize(5); + var listed = AddValuesToArrayMethods.GrowWithList(5); + + Assert.Equal(new[] { 0, 1, 2, 3, 4 }, resized); + Assert.Equal(resized, listed); + } +} diff --git a/collections-arrays/AddValuesToArray/Tests/Tests.csproj b/collections-arrays/AddValuesToArray/Tests/Tests.csproj index 7e9065130e..48e3daa63a 100644 --- a/collections-arrays/AddValuesToArray/Tests/Tests.csproj +++ b/collections-arrays/AddValuesToArray/Tests/Tests.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable @@ -9,13 +9,13 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all