diff --git a/PowerKit.Tests/FunctionalExtensionsTests.cs b/PowerKit.Tests/FunctionalExtensionsTests.cs index ee9c76c..aea8a25 100644 --- a/PowerKit.Tests/FunctionalExtensionsTests.cs +++ b/PowerKit.Tests/FunctionalExtensionsTests.cs @@ -15,6 +15,14 @@ public void Pipe_Test() "hello".Pipe(s => s.ToUpper()).Pipe(s => s + "!").Should().Be("HELLO!"); } + [Fact] + public void NullIf_ReferenceType_Test() + { + // Act & assert + "hello".NullIf(v => v == "hello").Should().BeNull(); + "world".NullIf(v => v == "hello").Should().Be("world"); + } + [Fact] public void NullIf_Test() { diff --git a/PowerKit/Extensions/FunctionalExtensions.cs b/PowerKit/Extensions/FunctionalExtensions.cs index 894c3d1..da3ca49 100644 --- a/PowerKit/Extensions/FunctionalExtensions.cs +++ b/PowerKit/Extensions/FunctionalExtensions.cs @@ -42,3 +42,18 @@ internal static class FunctionalExtensions public string? NullIfWhiteSpace() => !string.IsNullOrWhiteSpace(value) ? value : null; } } + +// Separate class because C# (CS0111) does not allow two generic methods with identical +// parameter types that differ only by constraint (class vs struct) in the same class. +internal static class ReferenceTypeFunctionalExtensions +{ + extension(T value) + where T : class + { + /// + /// Returns if the value is or matches the specified predicate; + /// otherwise, returns the value. + /// + public T? NullIf(Func predicate) => value?.Pipe(v => !predicate(v) ? v : null); + } +}