diff --git a/FrameworkFeatureConstants.props b/FrameworkFeatureConstants.props index 03d5a21f..819d8f1d 100644 --- a/FrameworkFeatureConstants.props +++ b/FrameworkFeatureConstants.props @@ -1,7 +1,7 @@ - $(DefineConstants);INDEX_OF_CHAR_COMPARISONTYPE_SUPPORTED;TIMESPAN_MULTIPLY_SUPPORTED;SPLIT_ACCEPTS_STRING_SEPARATOR;LAZY_RETURN_CONSTRUCTOR;QUEUE_TRY_OVERLOADS;OPTIMIZED_ELEMENT_AT;RANGE_SUPPORTED;READ_ONLY_SPAN_SUPPORTED;INDEX_TYPE;JOIN_TO_STRING_CHAR_SEPARATOR + $(DefineConstants);INDEX_OF_CHAR_COMPARISONTYPE_SUPPORTED;TIMESPAN_MULTIPLY_SUPPORTED;SPLIT_ACCEPTS_STRING_SEPARATOR;LAZY_RETURN_CONSTRUCTOR;QUEUE_TRY_OVERLOADS;OPTIMIZED_ELEMENT_AT;RANGE_SUPPORTED;READ_ONLY_SPAN_SUPPORTED;INDEX_TYPE;JOIN_TO_STRING_CHAR_SEPARATOR;REMOVE_EXTENSION $(DefineConstants);SYSTEM_INDEX_SUPPORTED;IP_END_POINT_TRY_PARSE_SUPPORTED diff --git a/Funcky.Test/Extensions/DictionaryExtensionTest.cs b/Funcky.Test/Extensions/DictionaryExtensionTest.cs index d75907f5..ad029b30 100644 --- a/Funcky.Test/Extensions/DictionaryExtensionTest.cs +++ b/Funcky.Test/Extensions/DictionaryExtensionTest.cs @@ -22,4 +22,28 @@ public void CallingGetValueOrNoneOnADictionaryThatImplementsBothReadonlyAndNonRe var dictionary = new Dictionary { ["some"] = "value" }; _ = dictionary.GetValueOrNone("some"); } + +#if REMOVE_EXTENSION + [Fact] + public void RemoveOrNoneOfAnExistingItemRemovesItemFromDictionaryAndReturnsTheValue() + { + IDictionary dictionary = new Dictionary { ["some"] = "value" }; + + var value = dictionary.RemoveOrNone("some"); + + Assert.Empty(dictionary); + FunctionalAssert.Some("value", value); + } + + [Fact] + public void RemoveOrNoneOfANonExistingItemReturnsNoneAndLeavesTheDictionaryUnchanegd() + { + IDictionary dictionary = new Dictionary { ["some"] = "value" }; + + var value = dictionary.RemoveOrNone("none"); + + Assert.NotEmpty(dictionary); + FunctionalAssert.None(value); + } +#endif } diff --git a/Funcky.sln b/Funcky.sln index 4321d770..f3ad8966 100644 --- a/Funcky.sln +++ b/Funcky.sln @@ -17,6 +17,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build Config", "Build Config", "{DD8F8450-BE23-4D6B-9C5C-7AED0ABB7531}" ProjectSection(SolutionItems) = preProject + Analyzers.props = Analyzers.props + Funcky\CompatibilitySuppressions.xml = Funcky\CompatibilitySuppressions.xml Directory.Build.props = Directory.Build.props Directory.Packages.props = Directory.Packages.props FrameworkFeatureConstants.props = FrameworkFeatureConstants.props @@ -24,9 +26,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build Config", "Build Confi GlobalUsings.props = GlobalUsings.props GlobalUsings.Test.props = GlobalUsings.Test.props NuGet.config = NuGet.config - typos.toml = typos.toml - Analyzers.props = Analyzers.props SemanticVersioning.targets = SemanticVersioning.targets + typos.toml = typos.toml EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Funcky.Xunit", "Funcky.Xunit\Funcky.Xunit.csproj", "{F2E98B0D-CC17-4576-89DE-065FF475BE6E}" diff --git a/Funcky/CompatibilitySuppressions.xml b/Funcky/CompatibilitySuppressions.xml index ee1f1edc..46401cc6 100644 --- a/Funcky/CompatibilitySuppressions.xml +++ b/Funcky/CompatibilitySuppressions.xml @@ -19,4 +19,10 @@ lib/netstandard2.1/Funcky.dll lib/netcoreapp3.1/Funcky.dll + + CP0021 + M:Funcky.Extensions.DictionaryExtensions.RemoveOrNone``2(System.Collections.Generic.IDictionary{``0,``1},``0)``0:notnull + lib/netstandard2.1/Funcky.dll + lib/netcoreapp3.1/Funcky.dll + \ No newline at end of file diff --git a/Funcky/Extensions/DictionaryExtensions.cs b/Funcky/Extensions/DictionaryExtensions.cs index f942fecc..f9358a76 100644 --- a/Funcky/Extensions/DictionaryExtensions.cs +++ b/Funcky/Extensions/DictionaryExtensions.cs @@ -28,4 +28,17 @@ public static Option GetValueOrNone(this IReadOnlyDictiona => dictionary.TryGetValue(readOnlyKey, out var result) ? result : Option.None; + +#if REMOVE_EXTENSION + public static Option RemoveOrNone(this IDictionary dictionary, TKey key) +#if NETCOREAPP3_1 + // TKey was constraint to notnull when nullability annotations were originally added. It was later dropped again. + // See: https://github.com/dotnet/runtime/issues/31401 + where TKey : notnull +#endif + where TValue : notnull + => dictionary.Remove(key, out var result) + ? result + : Option.None; +#endif } diff --git a/Funcky/PublicAPI.Unshipped.txt b/Funcky/PublicAPI.Unshipped.txt index 45bdf2f4..9d0d9458 100644 --- a/Funcky/PublicAPI.Unshipped.txt +++ b/Funcky/PublicAPI.Unshipped.txt @@ -1,6 +1,7 @@ #nullable enable Funcky.Extensions.JsonSerializerOptionsExtensions Funcky.Extensions.OrderedDictionaryExtensions +static Funcky.Extensions.DictionaryExtensions.RemoveOrNone(this System.Collections.Generic.IDictionary! dictionary, TKey key) -> Funcky.Monads.Option static Funcky.Extensions.FuncExtensions.Apply(this System.Func! func, Funcky.Unit p1, Funcky.Unit p2, Funcky.Unit p3, Funcky.Unit p4, T5 p5) -> System.Func! static Funcky.Extensions.FuncExtensions.Apply(this System.Func! func, Funcky.Unit p1, Funcky.Unit p2, Funcky.Unit p3, T4 p4, Funcky.Unit p5) -> System.Func! static Funcky.Extensions.FuncExtensions.Apply(this System.Func! func, Funcky.Unit p1, Funcky.Unit p2, Funcky.Unit p3, T4 p4, T5 p5) -> System.Func!