From ce350c1cc251fabe16be5cce33b289d52ba0a2da Mon Sep 17 00:00:00 2001 From: Vladimir Pecanac Date: Sun, 25 Oct 2026 13:24:43 +0100 Subject: [PATCH] Merging dictionaries: port to .NET 10 and pin duplicate-key behaviour with tests Retarget all three projects to net10.0, update NUnit, the test SDK, coverlet and BenchmarkDotNet, add the notnull key constraint to the six merge methods, initialise the benchmark dictionaries where they are declared, pass args to BenchmarkRunner, move the tests to the constraint model, fix the Duplicate spelling in test names and add four tests for duplicate keys. --- ...rgingDictionariesInCSharp.Benchmark.csproj | 4 +- .../MergingMethodsBenchmark.cs | 13 ++-- .../Program.cs | 2 +- .../MergingDictionariesInCSharp.Tests.csproj | 12 +-- .../UnitTests.cs | 73 ++++++++++++++----- .../MergingDictionariesInCSharp.csproj | 2 +- .../Methods/ConcatMethod.cs | 1 + .../Methods/ForEachMethod.cs | 1 + .../Methods/GroupByMethod.cs | 1 + .../Methods/LookupMethod.cs | 1 + .../Methods/UnionMethod.cs | 1 + .../Methods/UsingListsMethod.cs | 1 + 12 files changed, 74 insertions(+), 38 deletions(-) diff --git a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Benchmark/MergingDictionariesInCSharp.Benchmark.csproj b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Benchmark/MergingDictionariesInCSharp.Benchmark.csproj index 218beee44b..dc6f04d43e 100644 --- a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Benchmark/MergingDictionariesInCSharp.Benchmark.csproj +++ b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Benchmark/MergingDictionariesInCSharp.Benchmark.csproj @@ -2,13 +2,13 @@ Exe - net7.0 + net10.0 enable enable - + diff --git a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Benchmark/MergingMethodsBenchmark.cs b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Benchmark/MergingMethodsBenchmark.cs index a8fe46264d..b4136b13d7 100644 --- a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Benchmark/MergingMethodsBenchmark.cs +++ b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Benchmark/MergingMethodsBenchmark.cs @@ -8,27 +8,24 @@ [RankColumn] public class MergingMethodsBenchmark { - private Dictionary _dictionaryA; - private Dictionary _dictionaryB; + private readonly Dictionary _dictionaryA = []; + private readonly Dictionary _dictionaryB = []; [GlobalSetup] public void Setup() { - _dictionaryA = new Dictionary(); - _dictionaryB = new Dictionary(); - // Generate random values for dictionaryA for (var i = 0; i < 100; i++) { var randomValue = GenerateRandomValue(); - _dictionaryA.Add(i, randomValue); + _dictionaryA.Add(i, randomValue); } // Generate random values for dictionaryB - for (int i = 100; i < 200; i++) + for (var i = 100; i < 200; i++) { var randomValue = GenerateRandomValue(); - _dictionaryB.Add(i, randomValue); + _dictionaryB.Add(i, randomValue); } } diff --git a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Benchmark/Program.cs b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Benchmark/Program.cs index 9dca772280..9dbefa1337 100644 --- a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Benchmark/Program.cs +++ b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Benchmark/Program.cs @@ -1 +1 @@ -BenchmarkDotNet.Running.BenchmarkRunner.Run(); \ No newline at end of file +BenchmarkDotNet.Running.BenchmarkRunner.Run(args: args); \ No newline at end of file diff --git a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Tests/MergingDictionariesInCSharp.Tests.csproj b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Tests/MergingDictionariesInCSharp.Tests.csproj index 89e365a787..09759a3601 100644 --- a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Tests/MergingDictionariesInCSharp.Tests.csproj +++ b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Tests/MergingDictionariesInCSharp.Tests.csproj @@ -1,7 +1,7 @@ - net7.0 + net10.0 enable enable @@ -9,11 +9,11 @@ - - - - - + + + + + diff --git a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Tests/UnitTests.cs b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Tests/UnitTests.cs index e31e43d755..cf03a12c72 100644 --- a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Tests/UnitTests.cs +++ b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.Tests/UnitTests.cs @@ -3,9 +3,10 @@ [TestFixture] public class MergingMethodsTests { - private Dictionary _dictionaryA; - private Dictionary _dictionaryB; - private Dictionary _expectedMergedDictionary; + private Dictionary _dictionaryA = []; + private Dictionary _dictionaryB = []; + private Dictionary _expectedMergedDictionary = []; + private Dictionary _clashingDictionary = []; [SetUp] public void SetUp() @@ -33,6 +34,12 @@ public void SetUp() { 5, "Watermelon" }, { 6, "Pineapple" } }; + + // key 1 already exists in _dictionaryA, with a different value + _clashingDictionary = new Dictionary() + { + { 1, "Watermelon" } + }; } [Test] @@ -40,7 +47,7 @@ public void GivenConcatMethod_WhenDictionaryAB_ThenExpectedDictionary() { var mergedDictionary = ConcatMethod(_dictionaryA, _dictionaryB); - CollectionAssert.AreEqual(_expectedMergedDictionary, mergedDictionary); + Assert.That(mergedDictionary, Is.EqualTo(_expectedMergedDictionary)); } [Test] @@ -48,7 +55,7 @@ public void GivenForEachMethod_WhenDictionaryAB_ThenExpectedDictionary() { var mergedDictionary = ForEachMethod(_dictionaryA, _dictionaryB); - CollectionAssert.AreEqual(_expectedMergedDictionary, mergedDictionary); + Assert.That(mergedDictionary, Is.EqualTo(_expectedMergedDictionary)); } [Test] @@ -56,7 +63,7 @@ public void GivenGroupByMethod_WhenDictionaryAB_ThenExpectedDictionary() { var mergedDictionary = GroupByMethod(_dictionaryA, _dictionaryB); - CollectionAssert.AreEqual(_expectedMergedDictionary, mergedDictionary); + Assert.That(mergedDictionary, Is.EqualTo(_expectedMergedDictionary)); } [Test] @@ -64,7 +71,7 @@ public void GivenToLookupMethod_WhenDictionaryAB_ThenExpectedDictionary() { var mergedDictionary = LookupMethod(_dictionaryA, _dictionaryB); - CollectionAssert.AreEqual(_expectedMergedDictionary, mergedDictionary); + Assert.That(mergedDictionary, Is.EqualTo(_expectedMergedDictionary)); } [Test] @@ -72,7 +79,7 @@ public void GivenUnionMethod_WhenDictionaryAB_ThenExpectedDictionary() { var mergedDictionary = UnionMethod(_dictionaryA, _dictionaryB); - CollectionAssert.AreEqual(_expectedMergedDictionary, mergedDictionary); + Assert.That(mergedDictionary, Is.EqualTo(_expectedMergedDictionary)); } [Test] @@ -80,30 +87,56 @@ public void GivenListsMethod_WhenDictionaryAB_ThenExpectedDictionary() { var mergedDictionary = UsingListsMethod(_dictionaryA, _dictionaryB); - CollectionAssert.AreEqual(_expectedMergedDictionary, mergedDictionary); + Assert.That(mergedDictionary, Is.EqualTo(_expectedMergedDictionary)); } [Test] - public void GivenConcatMethod_WhenDictionariesWithDublicateKeys_ThenException() + public void GivenConcatMethod_WhenDictionariesWithDuplicateKeys_ThenException() { Assert.Throws(() => ConcatMethod(_dictionaryA, _dictionaryA)); } [Test] - public void GivenUnionMethod_WhenDictionariesWithDublicateKeys_ThenException() + public void GivenUnionMethod_WhenDictionariesWithDuplicateKeys_ThenException() + { + Assert.Throws(() => UnionMethod(_dictionaryA, _clashingDictionary)); + } + + [Test] + public void GivenUnionMethod_WhenSameKeyWithSameValue_ThenNoException() { - Assert.Throws(() => UnionMethod(_dictionaryA, new Dictionary() - { - {1, "Watermelon" } - //key:1 already exists in _dictionaryA, - //but UnionMethod needs different key value pair to throw exception. - }) - ); + var mergedDictionary = UnionMethod(_dictionaryA, _dictionaryA); + + Assert.That(mergedDictionary, Is.EqualTo(_dictionaryA)); } [Test] - public void GivenListsMethod_WhenDictionariesWithDublicateKeys_ThenException() + public void GivenListsMethod_WhenDictionariesWithDuplicateKeys_ThenException() { Assert.Throws(() => UsingListsMethod(_dictionaryA, _dictionaryA)); } -} \ No newline at end of file + + [Test] + public void GivenForEachMethod_WhenDictionariesWithDuplicateKeys_ThenFirstValueKept() + { + var mergedDictionary = ForEachMethod(_dictionaryA, _clashingDictionary); + + Assert.That(mergedDictionary[1], Is.EqualTo("Apple")); + } + + [Test] + public void GivenGroupByMethod_WhenDictionariesWithDuplicateKeys_ThenFirstValueKept() + { + var mergedDictionary = GroupByMethod(_dictionaryA, _clashingDictionary); + + Assert.That(mergedDictionary[1], Is.EqualTo("Apple")); + } + + [Test] + public void GivenToLookupMethod_WhenDictionariesWithDuplicateKeys_ThenFirstValueKept() + { + var mergedDictionary = LookupMethod(_dictionaryA, _clashingDictionary); + + Assert.That(mergedDictionary[1], Is.EqualTo("Apple")); + } +} diff --git a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.csproj b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.csproj index f02677bf64..dfb40caafc 100644 --- a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.csproj +++ b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp.csproj @@ -2,7 +2,7 @@ Exe - net7.0 + net10.0 enable enable diff --git a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/ConcatMethod.cs b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/ConcatMethod.cs index ef14f20038..e43f9b35ac 100644 --- a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/ConcatMethod.cs +++ b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/ConcatMethod.cs @@ -3,6 +3,7 @@ public partial class Methods { public static Dictionary ConcatMethod(params Dictionary[] dictionaries) + where TKey : notnull { var mergedDictionary = dictionaries.Aggregate((dict1, dict2) => dict1.Concat(dict2).ToDictionary(kvp => kvp.Key, kvp => kvp.Value) diff --git a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/ForEachMethod.cs b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/ForEachMethod.cs index 39a8275319..b0982146ff 100644 --- a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/ForEachMethod.cs +++ b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/ForEachMethod.cs @@ -3,6 +3,7 @@ public partial class Methods { public static Dictionary ForEachMethod(params Dictionary[] dictionaries) + where TKey : notnull { var mergedDictionary = new Dictionary(); diff --git a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/GroupByMethod.cs b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/GroupByMethod.cs index 818adb08a7..3793684c97 100644 --- a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/GroupByMethod.cs +++ b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/GroupByMethod.cs @@ -3,6 +3,7 @@ public partial class Methods { public static Dictionary GroupByMethod(params Dictionary[] dictionaries) + where TKey : notnull { var mergedDictionary = dictionaries.SelectMany(dict => dict) .GroupBy(kvp => kvp.Key) diff --git a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/LookupMethod.cs b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/LookupMethod.cs index 11478a7285..e29489f35a 100644 --- a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/LookupMethod.cs +++ b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/LookupMethod.cs @@ -3,6 +3,7 @@ public partial class Methods { public static Dictionary LookupMethod(params Dictionary[] dictionaries) + where TKey : notnull { var mergedDictionary = dictionaries.SelectMany(dict => dict) .ToLookup(pair => pair.Key, pair => pair.Value) diff --git a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/UnionMethod.cs b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/UnionMethod.cs index 7807ec1051..9ece130e02 100644 --- a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/UnionMethod.cs +++ b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/UnionMethod.cs @@ -3,6 +3,7 @@ public partial class Methods { public static Dictionary UnionMethod(params Dictionary[] dictionaries) + where TKey : notnull { var mergedDictionary = dictionaries.Aggregate((result, dict) => { diff --git a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/UsingListsMethod.cs b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/UsingListsMethod.cs index 54ff653dbd..72d07521b4 100644 --- a/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/UsingListsMethod.cs +++ b/collections-csharp/MergingDictionariesInCSharp/MergingDictionariesInCSharp/Methods/UsingListsMethod.cs @@ -3,6 +3,7 @@ public partial class Methods { public static Dictionary UsingListsMethod(params Dictionary[] dictionaries) + where TKey : notnull { var keys = new List(); var values = new List();