From 9ee38acad5eef2b640ad47f7c20baea43dc0990f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Apr 2026 10:30:09 +0000 Subject: [PATCH 1/6] feat: add GetValueOrNull on IReadOnlyDictionary and IDictionary for struct TValue Agent-Logs-Url: https://github.com/Tyrrrz/PowerKit/sessions/9c4b8ea4-27f3-4a79-a85f-a3feb7c644c6 Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com> --- .../Extensions/DictionaryExtensionsTests.cs | 52 +++++++++++++++++++ PowerKit/Extensions/DictionaryExtensions.cs | 24 +++++++++ 2 files changed, 76 insertions(+) diff --git a/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs b/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs index 7fa81ac..8567270 100644 --- a/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs +++ b/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs @@ -9,6 +9,58 @@ namespace PowerKit.Tests.Extensions; public class DictionaryExtensionsTests { + [Fact] + public void GetValueOrNull_ReadOnly_Found_Test() + { + // Arrange + IReadOnlyDictionary source = new Dictionary { ["one"] = 1 }; + + // Act + var result = source.GetValueOrNull("one"); + + // Assert + result.Should().Be(1); + } + + [Fact] + public void GetValueOrNull_ReadOnly_NotFound_Test() + { + // Arrange + IReadOnlyDictionary source = new Dictionary { ["one"] = 1 }; + + // Act + var result = source.GetValueOrNull("two"); + + // Assert + result.Should().BeNull(); + } + + [Fact] + public void GetValueOrNull_Found_Test() + { + // Arrange + IDictionary source = new Dictionary { ["one"] = 1 }; + + // Act + var result = source.GetValueOrNull("one"); + + // Assert + result.Should().Be(1); + } + + [Fact] + public void GetValueOrNull_NotFound_Test() + { + // Arrange + IDictionary source = new Dictionary { ["one"] = 1 }; + + // Act + var result = source.GetValueOrNull("two"); + + // Assert + result.Should().BeNull(); + } + [Fact] public void ToDictionary_Test() { diff --git a/PowerKit/Extensions/DictionaryExtensions.cs b/PowerKit/Extensions/DictionaryExtensions.cs index 9cd9a13..d8212da 100644 --- a/PowerKit/Extensions/DictionaryExtensions.cs +++ b/PowerKit/Extensions/DictionaryExtensions.cs @@ -11,6 +11,30 @@ namespace PowerKit.Extensions; #endif internal static class DictionaryExtensions { +#if NET40_OR_GREATER || NETSTANDARD || NET + extension(IReadOnlyDictionary dictionary) + where TKey : notnull + where TValue : struct + { + /// + /// Returns the value associated with the specified key, or if the key is not found. + /// + public TValue? GetValueOrNull(TKey key) => + dictionary.TryGetValue(key, out var value) ? value : null; + } +#endif + + extension(IDictionary dictionary) + where TKey : notnull + where TValue : struct + { + /// + /// Returns the value associated with the specified key, or if the key is not found. + /// + public TValue? GetValueOrNull(TKey key) => + dictionary.TryGetValue(key, out var value) ? value : null; + } + extension(IDictionary dictionary) { /// From 3f1bb406074fe749e6c1c9b39760a00d0c9032f1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Apr 2026 10:35:09 +0000 Subject: [PATCH 2/6] fix: correct extension block and test method ordering Agent-Logs-Url: https://github.com/Tyrrrz/PowerKit/sessions/9c4b8ea4-27f3-4a79-a85f-a3feb7c644c6 Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com> --- .../Extensions/DictionaryExtensionsTests.cs | 16 ++++++++-------- PowerKit/Extensions/DictionaryExtensions.cs | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs b/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs index 8567270..7b29fe7 100644 --- a/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs +++ b/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs @@ -10,10 +10,10 @@ namespace PowerKit.Tests.Extensions; public class DictionaryExtensionsTests { [Fact] - public void GetValueOrNull_ReadOnly_Found_Test() + public void GetValueOrNull_Found_Test() { // Arrange - IReadOnlyDictionary source = new Dictionary { ["one"] = 1 }; + IDictionary source = new Dictionary { ["one"] = 1 }; // Act var result = source.GetValueOrNull("one"); @@ -23,10 +23,10 @@ public void GetValueOrNull_ReadOnly_Found_Test() } [Fact] - public void GetValueOrNull_ReadOnly_NotFound_Test() + public void GetValueOrNull_NotFound_Test() { // Arrange - IReadOnlyDictionary source = new Dictionary { ["one"] = 1 }; + IDictionary source = new Dictionary { ["one"] = 1 }; // Act var result = source.GetValueOrNull("two"); @@ -36,10 +36,10 @@ public void GetValueOrNull_ReadOnly_NotFound_Test() } [Fact] - public void GetValueOrNull_Found_Test() + public void GetValueOrNull_ReadOnly_Found_Test() { // Arrange - IDictionary source = new Dictionary { ["one"] = 1 }; + IReadOnlyDictionary source = new Dictionary { ["one"] = 1 }; // Act var result = source.GetValueOrNull("one"); @@ -49,10 +49,10 @@ public void GetValueOrNull_Found_Test() } [Fact] - public void GetValueOrNull_NotFound_Test() + public void GetValueOrNull_ReadOnly_NotFound_Test() { // Arrange - IDictionary source = new Dictionary { ["one"] = 1 }; + IReadOnlyDictionary source = new Dictionary { ["one"] = 1 }; // Act var result = source.GetValueOrNull("two"); diff --git a/PowerKit/Extensions/DictionaryExtensions.cs b/PowerKit/Extensions/DictionaryExtensions.cs index d8212da..461c3ec 100644 --- a/PowerKit/Extensions/DictionaryExtensions.cs +++ b/PowerKit/Extensions/DictionaryExtensions.cs @@ -11,8 +11,7 @@ namespace PowerKit.Extensions; #endif internal static class DictionaryExtensions { -#if NET40_OR_GREATER || NETSTANDARD || NET - extension(IReadOnlyDictionary dictionary) + extension(IDictionary dictionary) where TKey : notnull where TValue : struct { @@ -22,9 +21,9 @@ internal static class DictionaryExtensions public TValue? GetValueOrNull(TKey key) => dictionary.TryGetValue(key, out var value) ? value : null; } -#endif - extension(IDictionary dictionary) +#if NET40_OR_GREATER || NETSTANDARD || NET + extension(IReadOnlyDictionary dictionary) where TKey : notnull where TValue : struct { @@ -34,6 +33,7 @@ internal static class DictionaryExtensions public TValue? GetValueOrNull(TKey key) => dictionary.TryGetValue(key, out var value) ? value : null; } +#endif extension(IDictionary dictionary) { From bb26a0f34d01c92c130f68f8ad2426b019e16cf8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Apr 2026 10:39:54 +0000 Subject: [PATCH 3/6] refactor: move IReadOnlyDictionary extensions to its own file Agent-Logs-Url: https://github.com/Tyrrrz/PowerKit/sessions/c363d2fa-4d03-4fc9-a5db-42fb307b288e Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com> --- .../Extensions/DictionaryExtensionsTests.cs | 26 -------------- .../ReadOnlyDictionaryExtensionsTests.cs | 35 +++++++++++++++++++ PowerKit/Extensions/DictionaryExtensions.cs | 13 ------- .../ReadOnlyDictionaryExtensions.cs | 24 +++++++++++++ 4 files changed, 59 insertions(+), 39 deletions(-) create mode 100644 PowerKit.Tests/Extensions/ReadOnlyDictionaryExtensionsTests.cs create mode 100644 PowerKit/Extensions/ReadOnlyDictionaryExtensions.cs diff --git a/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs b/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs index 7b29fe7..fa471a2 100644 --- a/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs +++ b/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs @@ -35,32 +35,6 @@ public void GetValueOrNull_NotFound_Test() result.Should().BeNull(); } - [Fact] - public void GetValueOrNull_ReadOnly_Found_Test() - { - // Arrange - IReadOnlyDictionary source = new Dictionary { ["one"] = 1 }; - - // Act - var result = source.GetValueOrNull("one"); - - // Assert - result.Should().Be(1); - } - - [Fact] - public void GetValueOrNull_ReadOnly_NotFound_Test() - { - // Arrange - IReadOnlyDictionary source = new Dictionary { ["one"] = 1 }; - - // Act - var result = source.GetValueOrNull("two"); - - // Assert - result.Should().BeNull(); - } - [Fact] public void ToDictionary_Test() { diff --git a/PowerKit.Tests/Extensions/ReadOnlyDictionaryExtensionsTests.cs b/PowerKit.Tests/Extensions/ReadOnlyDictionaryExtensionsTests.cs new file mode 100644 index 0000000..0a799ed --- /dev/null +++ b/PowerKit.Tests/Extensions/ReadOnlyDictionaryExtensionsTests.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using FluentAssertions; +using PowerKit.Extensions; +using Xunit; + +namespace PowerKit.Tests.Extensions; + +public class ReadOnlyDictionaryExtensionsTests +{ + [Fact] + public void GetValueOrNull_Found_Test() + { + // Arrange + IReadOnlyDictionary source = new Dictionary { ["one"] = 1 }; + + // Act + var result = source.GetValueOrNull("one"); + + // Assert + result.Should().Be(1); + } + + [Fact] + public void GetValueOrNull_NotFound_Test() + { + // Arrange + IReadOnlyDictionary source = new Dictionary { ["one"] = 1 }; + + // Act + var result = source.GetValueOrNull("two"); + + // Assert + result.Should().BeNull(); + } +} diff --git a/PowerKit/Extensions/DictionaryExtensions.cs b/PowerKit/Extensions/DictionaryExtensions.cs index 461c3ec..8555069 100644 --- a/PowerKit/Extensions/DictionaryExtensions.cs +++ b/PowerKit/Extensions/DictionaryExtensions.cs @@ -22,19 +22,6 @@ internal static class DictionaryExtensions dictionary.TryGetValue(key, out var value) ? value : null; } -#if NET40_OR_GREATER || NETSTANDARD || NET - extension(IReadOnlyDictionary dictionary) - where TKey : notnull - where TValue : struct - { - /// - /// Returns the value associated with the specified key, or if the key is not found. - /// - public TValue? GetValueOrNull(TKey key) => - dictionary.TryGetValue(key, out var value) ? value : null; - } -#endif - extension(IDictionary dictionary) { /// diff --git a/PowerKit/Extensions/ReadOnlyDictionaryExtensions.cs b/PowerKit/Extensions/ReadOnlyDictionaryExtensions.cs new file mode 100644 index 0000000..c2effe1 --- /dev/null +++ b/PowerKit/Extensions/ReadOnlyDictionaryExtensions.cs @@ -0,0 +1,24 @@ +#nullable enable +#if NET40_OR_GREATER || NETSTANDARD || NET +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace PowerKit.Extensions; + +#if !POWERKIT_INCLUDE_COVERAGE +[ExcludeFromCodeCoverage] +#endif +internal static class ReadOnlyDictionaryExtensions +{ + extension(IReadOnlyDictionary dictionary) + where TKey : notnull + where TValue : struct + { + /// + /// Returns the value associated with the specified key, or if the key is not found. + /// + public TValue? GetValueOrNull(TKey key) => + dictionary.TryGetValue(key, out var value) ? value : null; + } +} +#endif From 85c0ed55719f05f0fe984e101ea8c33fcf8c2463 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Apr 2026 10:41:54 +0000 Subject: [PATCH 4/6] test: merge GetValueOrNull Found/NotFound into single test Agent-Logs-Url: https://github.com/Tyrrrz/PowerKit/sessions/8e3a40cb-08a5-4517-97f3-5a42ccc66841 Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com> --- .../Extensions/DictionaryExtensionsTests.cs | 23 ++++--------------- .../ReadOnlyDictionaryExtensionsTests.cs | 23 ++++--------------- 2 files changed, 8 insertions(+), 38 deletions(-) diff --git a/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs b/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs index fa471a2..2a0874a 100644 --- a/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs +++ b/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs @@ -10,29 +10,14 @@ namespace PowerKit.Tests.Extensions; public class DictionaryExtensionsTests { [Fact] - public void GetValueOrNull_Found_Test() + public void GetValueOrNull_Test() { // Arrange IDictionary source = new Dictionary { ["one"] = 1 }; - // Act - var result = source.GetValueOrNull("one"); - - // Assert - result.Should().Be(1); - } - - [Fact] - public void GetValueOrNull_NotFound_Test() - { - // Arrange - IDictionary source = new Dictionary { ["one"] = 1 }; - - // Act - var result = source.GetValueOrNull("two"); - - // Assert - result.Should().BeNull(); + // Act & assert + source.GetValueOrNull("one").Should().Be(1); + source.GetValueOrNull("two").Should().BeNull(); } [Fact] diff --git a/PowerKit.Tests/Extensions/ReadOnlyDictionaryExtensionsTests.cs b/PowerKit.Tests/Extensions/ReadOnlyDictionaryExtensionsTests.cs index 0a799ed..9e61246 100644 --- a/PowerKit.Tests/Extensions/ReadOnlyDictionaryExtensionsTests.cs +++ b/PowerKit.Tests/Extensions/ReadOnlyDictionaryExtensionsTests.cs @@ -8,28 +8,13 @@ namespace PowerKit.Tests.Extensions; public class ReadOnlyDictionaryExtensionsTests { [Fact] - public void GetValueOrNull_Found_Test() + public void GetValueOrNull_Test() { // Arrange IReadOnlyDictionary source = new Dictionary { ["one"] = 1 }; - // Act - var result = source.GetValueOrNull("one"); - - // Assert - result.Should().Be(1); - } - - [Fact] - public void GetValueOrNull_NotFound_Test() - { - // Arrange - IReadOnlyDictionary source = new Dictionary { ["one"] = 1 }; - - // Act - var result = source.GetValueOrNull("two"); - - // Assert - result.Should().BeNull(); + // Act & assert + source.GetValueOrNull("one").Should().Be(1); + source.GetValueOrNull("two").Should().BeNull(); } } From be395569e7e1983acfcff6745c1365c33f3f0cd0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Apr 2026 10:49:36 +0000 Subject: [PATCH 5/6] test: use var with explicit cast in GetValueOrNull tests Agent-Logs-Url: https://github.com/Tyrrrz/PowerKit/sessions/eb5b8adc-aa10-434f-bdba-5d7b945b322c Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com> --- PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs | 2 +- PowerKit.Tests/Extensions/ReadOnlyDictionaryExtensionsTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs b/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs index 2a0874a..94d5b5a 100644 --- a/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs +++ b/PowerKit.Tests/Extensions/DictionaryExtensionsTests.cs @@ -13,7 +13,7 @@ public class DictionaryExtensionsTests public void GetValueOrNull_Test() { // Arrange - IDictionary source = new Dictionary { ["one"] = 1 }; + var source = (IDictionary)new Dictionary { ["one"] = 1 }; // Act & assert source.GetValueOrNull("one").Should().Be(1); diff --git a/PowerKit.Tests/Extensions/ReadOnlyDictionaryExtensionsTests.cs b/PowerKit.Tests/Extensions/ReadOnlyDictionaryExtensionsTests.cs index 9e61246..c4b00a4 100644 --- a/PowerKit.Tests/Extensions/ReadOnlyDictionaryExtensionsTests.cs +++ b/PowerKit.Tests/Extensions/ReadOnlyDictionaryExtensionsTests.cs @@ -11,7 +11,7 @@ public class ReadOnlyDictionaryExtensionsTests public void GetValueOrNull_Test() { // Arrange - IReadOnlyDictionary source = new Dictionary { ["one"] = 1 }; + var source = (IReadOnlyDictionary)new Dictionary { ["one"] = 1 }; // Act & assert source.GetValueOrNull("one").Should().Be(1); From 7ef1d835e01931293c1aab3f641b10c0c6c033b6 Mon Sep 17 00:00:00 2001 From: Oleksii Holub <1935960+Tyrrrz@users.noreply.github.com> Date: Wed, 22 Apr 2026 14:11:08 +0300 Subject: [PATCH 6/6] Update PowerKit/Extensions/ReadOnlyDictionaryExtensions.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- PowerKit/Extensions/ReadOnlyDictionaryExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PowerKit/Extensions/ReadOnlyDictionaryExtensions.cs b/PowerKit/Extensions/ReadOnlyDictionaryExtensions.cs index c2effe1..d682c77 100644 --- a/PowerKit/Extensions/ReadOnlyDictionaryExtensions.cs +++ b/PowerKit/Extensions/ReadOnlyDictionaryExtensions.cs @@ -1,5 +1,5 @@ -#nullable enable #if NET40_OR_GREATER || NETSTANDARD || NET +#nullable enable using System.Collections.Generic; using System.Diagnostics.CodeAnalysis;