diff --git a/src/Umbraco.Core/Extensions/StringExtensions.cs b/src/Umbraco.Core/Extensions/StringExtensions.cs index db24ece2d9..e887d1131c 100644 --- a/src/Umbraco.Core/Extensions/StringExtensions.cs +++ b/src/Umbraco.Core/Extensions/StringExtensions.cs @@ -51,16 +51,23 @@ public static class StringExtensions } /// - /// Convert a path to node ids in the order from right to left (deepest to shallowest) + /// Convert a path to node ids in the order from right to left (deepest to shallowest). /// - /// - /// + /// The path string expected as a comma delimited collection of integers. + /// An array of integers matching the provided path. public static int[] GetIdsFromPathReversed(this string path) { ReadOnlySpan pathSpan = path.AsSpan(); + + // Using the explicit enumerator (while/MoveNext) over the SpanSplitEnumerator in a foreach loop to avoid any compiler + // boxing of the ref struct enumerator. + // This prevents potential InvalidProgramException across compilers/JITs ("Cannot create boxed ByRef-like values."). + MemoryExtensions.SpanSplitEnumerator pathSegmentsEnumerator = pathSpan.Split(Constants.CharArrays.Comma); + List nodeIds = []; - foreach (Range rangeOfPathSegment in pathSpan.Split(Constants.CharArrays.Comma)) + while (pathSegmentsEnumerator.MoveNext()) { + Range rangeOfPathSegment = pathSegmentsEnumerator.Current; if (int.TryParse(pathSpan[rangeOfPathSegment], NumberStyles.Integer, CultureInfo.InvariantCulture, out int pathSegment)) { nodeIds.Add(pathSegment); diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/ShortStringHelper/StringExtensionsTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/ShortStringHelper/StringExtensionsTests.cs index d0f93044c3..3eb2180c0b 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/ShortStringHelper/StringExtensionsTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/ShortStringHelper/StringExtensionsTests.cs @@ -389,9 +389,11 @@ public class StringExtensionsTests } } + [TestCase(null, "")] + [TestCase("", "")] [TestCase("1,2,3,4,5", "5,4,3,2,1")] [TestCase("1,2,x,4,5", "5,4,2,1")] - public void GetIdsFromPathReversed(string input, string expected) + public void GetIdsFromPathReversed_ReturnsExpectedResult(string input, string expected) { var ids = input.GetIdsFromPathReversed(); Assert.AreEqual(expected, string.Join(",", ids));