From 100c3227cc1b080da50ede95c4ac00ea6cc6a045 Mon Sep 17 00:00:00 2001 From: Antyss77 Date: Mon, 10 Aug 2026 11:28:12 +0200 Subject: [PATCH] fix: correctly annotate nullable string/array parameters Methods that already tolerate a null input (via an explicit guard or via AsSpan()) now honestly declare it in their signature, instead of promising non-null while checking for null anyway. Flagged by community review (Wycott). --- Benchmarks/Benchmark.cs | 6 +++--- StringExtension/Casing/Casing.cs | 17 +++++++++++------ StringExtension/Linguistics/Linguistics.cs | 6 ++++-- StringExtension/StringExtension.cs | 9 +++++---- StringExtension/Validation/Validation.cs | 6 ++++-- UnitTests/StringExtensionTests.cs | 11 +++++------ 6 files changed, 32 insertions(+), 23 deletions(-) diff --git a/Benchmarks/Benchmark.cs b/Benchmarks/Benchmark.cs index c0ac8b1..7f42590 100644 --- a/Benchmarks/Benchmark.cs +++ b/Benchmarks/Benchmark.cs @@ -28,7 +28,7 @@ public class StringExtensionBenchmark /// Benchmark for the RemoveCharacters method. /// [Benchmark] - public string RemoveCharacters() + public string? RemoveCharacters() { return input.RemoveCharacters(charactersToRemove); } @@ -64,7 +64,7 @@ public int CountSubstring() /// Benchmark for the ReverseWords method. /// [Benchmark] - public string ReverseWords() + public string? ReverseWords() { return input.ReverseWords(); } @@ -91,7 +91,7 @@ public int CountLetters() /// Benchmark for the RemoveDuplicateCharacters method. /// [Benchmark] - public string RemoveDuplicateCharacters() + public string? RemoveDuplicateCharacters() { return input.RemoveDuplicateCharacters(); } diff --git a/StringExtension/Casing/Casing.cs b/StringExtension/Casing/Casing.cs index c0b12ee..542e23f 100644 --- a/StringExtension/Casing/Casing.cs +++ b/StringExtension/Casing/Casing.cs @@ -25,7 +25,8 @@ public static class Casing /// /// The input string. /// The input string converted to camel case. - public static string ToCamelCase(this string input) + /// Returns if is . + public static string ToCamelCase(this string? input) { return ToCamelCase(input.AsSpan()); } @@ -96,7 +97,8 @@ public static string ToCamelCase(this ReadOnlySpan input) /// /// The input string. /// The input string converted to Pascal case. - public static string ToPascalCase(this string input) + /// Returns if is . + public static string ToPascalCase(this string? input) { return ToPascalCase(input.AsSpan()); } @@ -156,7 +158,8 @@ public static string ToPascalCase(this ReadOnlySpan input) /// /// The input string. /// The input string converted to snake case. - public static string ToSnakeCase(this string input) + /// Returns if is . + public static string ToSnakeCase(this string? input) { return ToSnakeCase(input.AsSpan()); } @@ -183,7 +186,8 @@ public static string ToSnakeCase(this ReadOnlySpan input) /// /// The input string. /// The input string converted to kebab case. - public static string ToKebabCase(this string input) + /// Returns if is . + public static string ToKebabCase(this string? input) { return ToKebabCase(input.AsSpan()); } @@ -215,7 +219,8 @@ public static string ToKebabCase(this ReadOnlySpan input) /// If (the default), every word is capitalized. /// /// The input string converted to title case. - public static string ToTitleCase(this string input, bool useEnglishMinorWordRules = false) + /// Returns if is . + public static string ToTitleCase(this string? input, bool useEnglishMinorWordRules = false) { return ToTitleCase(input.AsSpan(), useEnglishMinorWordRules); } @@ -405,7 +410,7 @@ private static bool IsEnglishMinorWord(ReadOnlySpan word) /// stripped or transliterated. Returns if /// is or empty. /// - public static string Slugify(this string input, char separator = '-') + public static string Slugify(this string? input, char separator = '-') { if (string.IsNullOrEmpty(input)) { diff --git a/StringExtension/Linguistics/Linguistics.cs b/StringExtension/Linguistics/Linguistics.cs index c1ec2c1..a747ab9 100644 --- a/StringExtension/Linguistics/Linguistics.cs +++ b/StringExtension/Linguistics/Linguistics.cs @@ -14,7 +14,8 @@ public static class Linguistics /// /// The input string. /// true if the string is a palindrome; otherwise, false. - public static bool IsPalindrome(this string input) + /// Returns if is . + public static bool IsPalindrome(this string? input) { return IsPalindrome(input.AsSpan()); } @@ -83,7 +84,8 @@ public static bool IsPalindrome(this ReadOnlySpan input) /// /// The input string. /// The number of letters in the input string. - public static int CountLetters(this string input) + /// Returns 0 if is . + public static int CountLetters(this string? input) { return CountLetters(input.AsSpan()); } diff --git a/StringExtension/StringExtension.cs b/StringExtension/StringExtension.cs index 4421662..880ceee 100644 --- a/StringExtension/StringExtension.cs +++ b/StringExtension/StringExtension.cs @@ -15,7 +15,7 @@ public static class StringExtension /// An array of characters to remove. /// A new string with specified characters removed. /// Returns if is . - public static string RemoveCharacters(this string input, char[] charactersToRemove) + public static string? RemoveCharacters(this string? input, char[]? charactersToRemove) { if (string.IsNullOrEmpty(input) || charactersToRemove is null || charactersToRemove.Length == 0) { @@ -71,7 +71,8 @@ public static string RemoveCharacters(this ReadOnlySpan input, ReadOnlySpa /// The input string. /// The substring to count. /// The number of occurrences of the substring in the input string. - public static int CountSubstring(this string input, string substring) + /// Returns 0 if or is . + public static int CountSubstring(this string? input, string? substring) { return CountSubstring(input.AsSpan(), substring.AsSpan()); } @@ -99,7 +100,7 @@ public static int CountSubstring(this ReadOnlySpan input, ReadOnlySpanThe input to reverse words. /// The input string with the order of words reversed. /// Returns if is . - public static string ReverseWords(this string input) + public static string? ReverseWords(this string? input) { if (string.IsNullOrEmpty(input)) { @@ -133,7 +134,7 @@ public static string ReverseWords(this string input) /// The input string. /// A new string with duplicate characters removed. /// Returns if is . - public static string RemoveDuplicateCharacters(this string input) + public static string? RemoveDuplicateCharacters(this string? input) { if (string.IsNullOrEmpty(input)) { diff --git a/StringExtension/Validation/Validation.cs b/StringExtension/Validation/Validation.cs index 814f603..acbb74d 100644 --- a/StringExtension/Validation/Validation.cs +++ b/StringExtension/Validation/Validation.cs @@ -26,7 +26,8 @@ public static partial class Validation /// /// The email address to validate. /// true if the given email address is valid; otherwise, false. - public static bool IsValidEmail(this string email) + /// Returns if is . + public static bool IsValidEmail(this string? email) { return !string.IsNullOrEmpty(email) && MailAddressRegex().IsMatch(email); } @@ -46,7 +47,8 @@ public static bool IsValidEmail(this ReadOnlySpan email) /// /// The phone number to validate. /// true if the given phone number is valid; otherwise, false. - public static bool IsValidPhoneNumber(this string phoneNumber) + /// Returns if is . + public static bool IsValidPhoneNumber(this string? phoneNumber) { return !string.IsNullOrEmpty(phoneNumber) && PhoneNumberRegex().IsMatch(phoneNumber); } diff --git a/UnitTests/StringExtensionTests.cs b/UnitTests/StringExtensionTests.cs index dc53768..a9271a3 100644 --- a/UnitTests/StringExtensionTests.cs +++ b/UnitTests/StringExtensionTests.cs @@ -19,7 +19,7 @@ public void TestRemoveCharacters() string input = "hello world!"; char[] charactersToRemove = { 'l', 'o' }; string expected = "he wrd!"; - string result = input.RemoveCharacters(charactersToRemove); + string? result = input.RemoveCharacters(charactersToRemove); Assert.That(result, Is.EqualTo(expected)); } @@ -31,7 +31,7 @@ public void TestRemoveCharacters_NullInput() { string input = null!; char[] charactersToRemove = { 'l', 'o' }; - string result = input.RemoveCharacters(charactersToRemove); + string? result = input.RemoveCharacters(charactersToRemove); Assert.That(result, Is.Null); } @@ -91,7 +91,7 @@ public void TestReverseWords() { string input = "hello world!"; string expected = "world! hello"; - string result = input.ReverseWords(); + string? result = input.ReverseWords(); Assert.That(result, Is.EqualTo(expected)); } @@ -102,7 +102,7 @@ public void TestReverseWords() public void TestReverseWords_NullInput() { string input = null!; - string result = input.ReverseWords(); + string? result = input.ReverseWords(); Assert.That(result, Is.Null); } @@ -190,7 +190,7 @@ public void TestRemoveDuplicateCharacters() { string input = "hello world!"; string expected = "helo wrd!"; - string result = input.RemoveDuplicateCharacters(); + string? result = input.RemoveDuplicateCharacters(); Assert.That(result, Is.EqualTo(expected)); } @@ -330,7 +330,6 @@ public void TestToTitleCase_LastWordAlwaysCapitalized() Assert.That(result, Is.EqualTo(expected)); } - /// /// Tests the Slugify method with accented characters and punctuation. ///