From 5273db7b01dd19c7ed837a3e3be0b43ab6092487 Mon Sep 17 00:00:00 2001 From: Vladimir Pecanac Date: Sun, 30 Aug 2026 21:30:28 +0200 Subject: [PATCH] SplitString: fix platform-dependent newline split, retarget net10.0 The newline sample split a \n-only literal on Environment.NewLine, so on Windows it found no separator and returned one element while the test asserted five. It passed on Linux CI only. Both sides now split on ["\r\n", "\n"], which is honest on every platform. - SplitStringUsingStringArrayWithoptions takes StringSplitOptions (default None) so the sample can demonstrate RemoveEmptyEntries on an input that has empty entries. - Adds SplitStringWithOptions, covering the four StringSplitOptions results the article tabulates, and CountSplitRanges, the allocation-free ReadOnlySpan.Split into a stack-allocated Span. - net6.0 -> net10.0; MSTest 4.3.3, Microsoft.NET.Test.Sdk 18.9.0, coverlet.collector 10.0.1. --- .../SplitString/SplitString/Program.cs | 42 ++++++++- .../SplitString/SplitString.csproj | 2 +- .../SplitStringTests/SplitStringTests.cs | 92 ++++++++++++++++++- .../SplitStringTests/SplitStringTests.csproj | 10 +- 4 files changed, 133 insertions(+), 13 deletions(-) diff --git a/strings-csharp/SplitString/SplitString/Program.cs b/strings-csharp/SplitString/SplitString/Program.cs index 02c0ad0df5..f98996f2f0 100644 --- a/strings-csharp/SplitString/SplitString/Program.cs +++ b/strings-csharp/SplitString/SplitString/Program.cs @@ -17,13 +17,22 @@ static void Main(string[] args) SplitStringUsingCharacterArrayWithoptionsUsingCount(" apple , banana ; cherry,orange ", new[] { ',', ';' }, 3); Console.WriteLine("\n***************** Split the String Using String Array with String Split Options ***************\n"); - SplitStringUsingStringArrayWithoptions("apple,banana,kiwi;grape,mango,orange", new[] { ",", ";" }); + SplitStringUsingStringArrayWithoptions("apple,,banana;;kiwi", new[] { ",", ";" }, StringSplitOptions.RemoveEmptyEntries); Console.WriteLine("\n***************** Split the String Using String Array with String Split Options Using Count ***************\n"); SplitStringUsingStringArrayWithoptionsUsingCount("apple,banana,cherry,orange,pear", new[] { "," }, 3); Console.WriteLine("\n***************** Split a String Into New Lines ***************\n"); - SplitStringIntoNewLines("Line 1\nLine 2\nLine 3\nLine 4\nLine 5", new[] { Environment.NewLine }); + SplitStringIntoNewLines("Line 1\nLine 2\nLine 3\nLine 4\nLine 5", ["\r\n", "\n"]); + + Console.WriteLine("\n***************** StringSplitOptions on the Same Input ***************\n"); + SplitStringWithOptions("a,,b, c, , d ,e", ',', StringSplitOptions.None); + SplitStringWithOptions("a,,b, c, , d ,e", ',', StringSplitOptions.RemoveEmptyEntries); + SplitStringWithOptions("a,,b, c, , d ,e", ',', StringSplitOptions.TrimEntries); + SplitStringWithOptions("a,,b, c, , d ,e", ',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + + Console.WriteLine("\n***************** Split a String Without Allocating Substrings ***************\n"); + CountSplitRanges("apple,banana,cherry,date", ','); } public static string[] SplitStringUsingCharacterArray(string input, char[] separators) @@ -73,9 +82,10 @@ public static string[] SplitStringUsingCharacterArrayWithoptionsUsingCount(strin return result; } - public static string[] SplitStringUsingStringArrayWithoptions(string input, string[] delimiters) + public static string[] SplitStringUsingStringArrayWithoptions(string input, string[] delimiters, + StringSplitOptions options = StringSplitOptions.None) { - string[] result = input.Split(delimiters, StringSplitOptions.None); + string[] result = input.Split(delimiters, options); foreach (string s in result) { @@ -108,5 +118,29 @@ public static string[] SplitStringIntoNewLines(string multiLineText, string[] se return lines; } + + public static string[] SplitStringWithOptions(string input, char separator, StringSplitOptions options) + { + string[] result = input.Split(separator, options); + + Console.WriteLine($"{options}: [{string.Join("] [", result)}]"); + + return result; + } + + public static int CountSplitRanges(string input, char separator) + { + ReadOnlySpan source = input; + Span ranges = stackalloc Range[8]; + + int count = source.Split(ranges, separator); + + for (int i = 0; i < count; i++) + { + Console.WriteLine(source[ranges[i]].ToString()); + } + + return count; + } } } \ No newline at end of file diff --git a/strings-csharp/SplitString/SplitString/SplitString.csproj b/strings-csharp/SplitString/SplitString/SplitString.csproj index 74abf5c976..dfb40caafc 100644 --- a/strings-csharp/SplitString/SplitString/SplitString.csproj +++ b/strings-csharp/SplitString/SplitString/SplitString.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net10.0 enable enable diff --git a/strings-csharp/SplitString/SplitStringTests/SplitStringTests.cs b/strings-csharp/SplitString/SplitStringTests/SplitStringTests.cs index 5ad9fe4e9b..e2c3498802 100644 --- a/strings-csharp/SplitString/SplitStringTests/SplitStringTests.cs +++ b/strings-csharp/SplitString/SplitStringTests/SplitStringTests.cs @@ -104,14 +104,100 @@ public void WhenSplittingAStringIntoNewLine_ThenReturnArrayOfSubstrings() { // Arrange string input = "Line 1\nLine 2\nLine 3\nLine 4\nLine 5"; - string[] separators = { Environment.NewLine }; - int expectedOutputLength = 5; + string[] separators = ["\r\n", "\n"]; + string[] expectedOutput = ["Line 1", "Line 2", "Line 3", "Line 4", "Line 5"]; // Act string[] result = Program.SplitStringIntoNewLines(input, separators); // Assert - Assert.AreEqual(expectedOutputLength, result.Length); + CollectionAssert.AreEqual(expectedOutput, result); + } + + [TestMethod] + public void WhenSplittingCrLfAndLfMixedText_ThenReturnOneEntryPerLineOnEveryPlatform() + { + // Arrange + string input = "Line 1\r\nLine 2\nLine 3\r\nLine 4"; + string[] separators = ["\r\n", "\n"]; + string[] expectedOutput = ["Line 1", "Line 2", "Line 3", "Line 4"]; + + // Act + string[] result = Program.SplitStringIntoNewLines(input, separators); + + // Assert + CollectionAssert.AreEqual(expectedOutput, result); + } + + [TestMethod] + public void WhenSplittingWithNone_ThenKeepEveryPieceAsCut() + { + // Arrange + string input = "a,,b, c, , d ,e"; + string[] expectedOutput = ["a", "", "b", " c", " ", " d ", "e"]; + + // Act + string[] result = Program.SplitStringWithOptions(input, ',', StringSplitOptions.None); + + // Assert + CollectionAssert.AreEqual(expectedOutput, result); + } + + [TestMethod] + public void WhenSplittingWithRemoveEmptyEntries_ThenDropZeroLengthPiecesOnly() + { + // Arrange + string input = "a,,b, c, , d ,e"; + string[] expectedOutput = ["a", "b", " c", " ", " d ", "e"]; + + // Act + string[] result = Program.SplitStringWithOptions(input, ',', StringSplitOptions.RemoveEmptyEntries); + + // Assert + CollectionAssert.AreEqual(expectedOutput, result); + } + + [TestMethod] + public void WhenSplittingWithTrimEntries_ThenTrimEveryPieceAndKeepTheEmpties() + { + // Arrange + string input = "a,,b, c, , d ,e"; + string[] expectedOutput = ["a", "", "b", "c", "", "d", "e"]; + + // Act + string[] result = Program.SplitStringWithOptions(input, ',', StringSplitOptions.TrimEntries); + + // Assert + CollectionAssert.AreEqual(expectedOutput, result); + } + + [TestMethod] + public void WhenSplittingWithRemoveEmptyEntriesAndTrimEntries_ThenTrimFirstThenDrop() + { + // Arrange + string input = "a,,b, c, , d ,e"; + string[] expectedOutput = ["a", "b", "c", "d", "e"]; + + // Act + string[] result = Program.SplitStringWithOptions(input, ',', + StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + + // Assert + CollectionAssert.AreEqual(expectedOutput, result); + } + + [TestMethod] + public void WhenSplittingIntoRanges_ThenReturnThePieceCountWithoutAllocatingSubstrings() + { + // Arrange + string input = "apple,banana,cherry,date"; + int expectedCount = 4; + + // Act + int count = Program.CountSplitRanges(input, ','); + + // Assert + Assert.AreEqual(expectedCount, count); } } } \ No newline at end of file diff --git a/strings-csharp/SplitString/SplitStringTests/SplitStringTests.csproj b/strings-csharp/SplitString/SplitStringTests/SplitStringTests.csproj index bf7d25afbe..570b3f7eb3 100644 --- a/strings-csharp/SplitString/SplitStringTests/SplitStringTests.csproj +++ b/strings-csharp/SplitString/SplitStringTests/SplitStringTests.csproj @@ -1,7 +1,7 @@ - net6.0 + net10.0 enable enable @@ -9,10 +9,10 @@ - - - - + + + +