@@ -205,28 +205,15 @@ public static ValueEnumerable<StringSegmentSequenceSplitEnumerator, StringSegmen
205205 /// </summary>
206206 /// <param name="source">The segments to join.</param>
207207 /// <param name="between">The segment to place between each segment.</param>
208- /// <returns>An IEnumerable<StringSegment> of the segments.</returns>
208+ /// <returns>A ValueEnumerable of the joined segments (zero-allocation when used with foreach or ZLinq) .</returns>
209209 /// <exception cref="System.ArgumentNullException">The source is null.</exception>
210- public static IEnumerable < StringSegment > Join ( this IEnumerable < StringSegment > source , StringSegment between )
210+ [ CLSCompliant ( false ) ]
211+ public static ValueEnumerable < StringSegmentJoinEnumerator , StringSegment > Join ( this IEnumerable < StringSegment > source , StringSegment between )
211212 {
212213 return source is null
213214 ? throw new ArgumentNullException ( nameof ( source ) )
214- : JoinCore ( source , between ) ;
215-
216- static IEnumerable < StringSegment > JoinCore ( IEnumerable < StringSegment > source , StringSegment between )
217- {
218- using IEnumerator < StringSegment > e = source . GetEnumerator ( ) ;
219- bool ok = e . MoveNext ( ) ;
220- Debug . Assert ( ok ) ;
221- StringSegment c = e . Current ;
222- if ( c . Length != 0 ) yield return c ;
223- while ( e . MoveNext ( ) )
224- {
225- if ( between . HasValue ) yield return between ;
226- c = e . Current ;
227- if ( c . Length != 0 ) yield return c ;
228- }
229- }
215+ : new ValueEnumerable < StringSegmentJoinEnumerator , StringSegment > (
216+ new StringSegmentJoinEnumerator ( source , between ) ) ;
230217 }
231218
232219 /// <summary>
@@ -250,8 +237,10 @@ public static string JoinToString(this IEnumerable<StringSegment> source, String
250237 /// <summary>
251238 /// Splits a sequence and replaces the removed sequences with the replacement sequence.
252239 /// </summary>
240+ /// <returns>A ValueEnumerable of the segments (zero-allocation when used with foreach or ZLinq).</returns>
253241 /// <inheritdoc cref="SplitAsSegments(string, string, StringSplitOptions, StringComparison)"/>
254- public static IEnumerable < StringSegment > Replace (
242+ [ CLSCompliant ( false ) ]
243+ public static ValueEnumerable < StringSegmentJoinEnumerator , StringSegment > Replace (
255244 this StringSegment source ,
256245 StringSegment splitSequence ,
257246 StringSegment replacement ,
@@ -267,14 +256,16 @@ public static string ReplaceToString(this StringSegment source,
267256 => JoinToString ( SplitAsSegments ( source , splitSequence , comparisonType : comparisonType ) . ToArray ( ) , replacement ) ;
268257
269258 /// <inheritdoc cref="Replace(StringSegment, StringSegment, StringSegment, StringComparison)"/>
270- public static IEnumerable < StringSegment > ReplaceAsSegments (
259+ [ CLSCompliant ( false ) ]
260+ public static ValueEnumerable < StringSegmentJoinEnumerator , StringSegment > ReplaceAsSegments (
271261 this string source ,
272262 Regex splitSequence ,
273263 StringSegment replacement )
274264 => Join ( SplitAsSegments ( source , splitSequence ) , replacement ) ;
275265
276266 /// <inheritdoc cref="Replace(StringSegment, StringSegment, StringSegment, StringComparison)"/>
277- public static IEnumerable < StringSegment > ReplaceAsSegments (
267+ [ CLSCompliant ( false ) ]
268+ public static ValueEnumerable < StringSegmentJoinEnumerator , StringSegment > ReplaceAsSegments (
278269 this string source ,
279270 StringSegment splitSequence ,
280271 StringSegment replacement ,
@@ -299,9 +290,10 @@ static IEnumerable<StringSegment> ReplaceEachCore(IEnumerable<StringSegment> sou
299290 {
300291 // Instead of source.SelectMany(s => s.Replace(splitSequence, replacement, comparisonType));
301292 // we manually yield to reduce allocations.
293+ // Note: We use ToArray() to materialize the ValueEnumerable because ref structs cannot be preserved across yield boundaries.
302294 foreach ( StringSegment s in source )
303295 {
304- foreach ( StringSegment e in Replace ( s , splitSequence , replacement , comparisonType ) )
296+ foreach ( StringSegment e in Replace ( s , splitSequence , replacement , comparisonType ) . ToArray ( ) )
305297 yield return e ;
306298 }
307299 }
0 commit comments