SpanExtensions Class
Definition
Provides span-shaping helpers - read-only conversion and copy-and-reverse operations - for code that already operates on Span<T> or ReadOnlySpan<T>.
public static class SpanExtensions
- Inheritance
-
SpanExtensions
- Inherited Members
Remarks
Span<T> is the right tool for stack-allocated, zero-copy work, but the BCL only ships a small number
of transformations on it directly. This class adds two operations: a free Span<T> ->
ReadOnlySpan<T> conversion that makes intent visible to callers, and a family of copy-and-reverse
operators that accept either an index/count pair or a Range - matching the surface used by
ArrayExtensions.Reverse so the same call shape works regardless of whether the caller holds a span or an
array.
The API surface is intentionally narrow: AsReadOnly for capability-narrowing, and overloaded
ToReversed methods on both Span<T> and ReadOnlySpan<T> for whole-span and
windowed reversal. Unlike the in-place Reverse<T>(Span<T>), every ToReversed
overload copies the full source into a newly heap-allocated array and reverses the nominated window on that copy;
the returned Span<T> wraps the fresh allocation, and the source memory is never modified. This is
also why the ReadOnlySpan<T> overloads can return a writeable Span<T> - it aliases the
copy, not the read-only source.
AsReadOnly is allocation-free; the ToReversed overloads allocate one array per call. Reversing a
partial window copies all elements and reverses only those inside the window. The methods are not thread-safe -
concurrent access to the underlying buffer must be synchronized externally.
Span<int> buffer = stackalloc int[] { 1, 2, 3, 4, 5, 6 };
// Reverse only the trailing window using a Range - returns a new heap-backed span.
Span<int> reversed = buffer.ToReversed(2..); // => { 1, 2, 6, 5, 4, 3 }; buffer is unchanged
// Narrow the surface before handing the span to a read-only consumer.
ReadOnlySpan<int> view = buffer.AsReadOnly();
// Reverse the full span - again into a fresh copy.
Span<int> full = buffer.ToReversed(); // => { 6, 5, 4, 3, 2, 1 }; buffer is unchanged
Methods
AsReadOnly<T>(Span<T>)
Returns a ReadOnlySpan<T> view over the same memory as source, preventing
callers from mutating the underlying data.
public static ReadOnlySpan<T> AsReadOnly<T>(this Span<T> source)
Parameters
sourceSpan<T>The mutable span to make read-only.
Returns
- ReadOnlySpan<T>
A ReadOnlySpan<T> with the same backing memory, offset, and length as
source. No data is copied.
Type Parameters
TThe type of elements in the span.
Remarks
This method is a zero-cost wrapper around the implicit conversion from Span<T> to
ReadOnlySpan<T> defined by the runtime. The compiler erases the call entirely - the emitted IL is
identical to writing (ReadOnlySpan<T>)source at the call site.
The primary use case is readability and intent: passing a mutable span to a method that should only read from it, or storing it in a field or local that should not allow writes, without scattering explicit casts throughout the call site.
This follows the same pattern as AsMemory<T>(T[]), which provides a named, intent-expressing wrapper over an implicit conversion rather than requiring callers to write casts directly.
ToReversed<T>(ReadOnlySpan<T>)
Creates a new array containing all elements of source in reverse order, leaving
source unmodified.
public static Span<T> ToReversed<T>(this ReadOnlySpan<T> source)
Parameters
sourceReadOnlySpan<T>The span whose elements are copied in reverse order.
Returns
- Span<T>
A new Span<T> backed by a heap-allocated array containing all elements of
sourcein reverse order.
Type Parameters
TThe type of elements in the span.
Remarks
Unlike the BCL Reverse<T>(Span<T>), which reverses a span in place,
this method never mutates source - the reversal is applied to a fresh heap-allocated copy.
Delegates to ToReversed<T>(ReadOnlySpan<T>, int, int) with start = 0 and
length = source.Length. See that overload for full performance and allocation details.
ToReversed<T>(ReadOnlySpan<T>, int, int)
Creates a new array that is a copy of source with elements in the specified range reversed,
leaving all other elements in their original positions and source unmodified.
public static Span<T> ToReversed<T>(this ReadOnlySpan<T> source, int index, int count)
Parameters
sourceReadOnlySpan<T>The span to copy and partially reverse.
indexintThe zero-based index of the first element in the range to reverse. Must be non-negative and less than or equal to Length.
countintThe number of elements to reverse. Must be non-negative and, together with
index, must not exceed Length. A value of zero or one results in a straight copy with no reversal performed.
Returns
- Span<T>
A new Span<T> of the same length as
source, where elements in the range [index,index+count) appear in reverse order and all other elements are copied unchanged.
Type Parameters
TThe type of elements in the span.
Examples
int[] data = { 1, 2, 3, 4, 5 };
// Reverse a middle section; first and last elements are untouched.
Span<int> result = data.AsSpan().ToReversed(index: 1, count: 3); // [ 1, 4, 3, 2, 5 ]
Remarks
Unlike the BCL Reverse<T>(Span<T>), which reverses a span in place,
this method never mutates source - the reversal is applied to a fresh heap-allocated copy.
This is the canonical public implementation. The full-span overload (ToReversed<T>(ReadOnlySpan<T>)) and the Range-based overload (ToReversed<T>(ReadOnlySpan<T>, Range)) both resolve their arguments and delegate here after validation.
Bounds validation uses unsigned comparison so that a single branch catches both negative values and values that exceed the span length, matching the pattern used throughout MemoryExtensions.
Once validated, execution is forwarded to Bodu.Extensions.SpanExtensions.ReverseCore``1(System.ReadOnlySpan{``0},System.Int32,System.Int32), which performs the allocation and the SIMD-accelerated copy and reversal.
Exceptions
- ArgumentOutOfRangeException
Thrown when
indexis negative or greater than Length, or whencountis negative or would extend the range beyond the end ofsource.
ToReversed<T>(ReadOnlySpan<T>, Range)
Creates a new array that is a copy of source with elements in the specified
Range reversed, leaving all other elements in their original positions and
source unmodified.
public static Span<T> ToReversed<T>(this ReadOnlySpan<T> source, Range range)
Parameters
sourceReadOnlySpan<T>The span to copy and partially reverse.
rangeRangeThe range of elements to reverse. Both start-relative (e.g.
1..4) and end-relative (e.g.^4..^1) index expressions are supported. A range covering zero or one element results in a straight copy with no reversal performed.
Returns
- Span<T>
A new Span<T> of the same length as
source, where elements withinrangeappear in reverse order and all elements outsiderangeare copied unchanged.
Type Parameters
TThe type of elements in the span.
Examples
int[] data = { 1, 2, 3, 4, 5 };
Span<int> fromStart = data.AsSpan().ToReversed(1..4); // [ 1, 4, 3, 2, 5 ]
Span<int> fromEnd = data.AsSpan().ToReversed(^4..^1); // [ 1, 4, 3, 2, 5 ]
Remarks
Unlike the BCL Reverse<T>(Span<T>), which reverses a span in place,
this method never mutates source - the reversal is applied to a fresh heap-allocated copy.
Resolves range to an offset and length via GetOffsetAndLength(int) and
delegates to ToReversed<T>(ReadOnlySpan<T>, int, int). Prefer that overload when the start and
length are already available as integers to avoid constructing an intermediate Range value.
This overload is most ergonomic when the range is expressed as a C# 8+ index expression at the call site (e.g.
1..4 or ^3..^1), where the compiler handles Range construction automatically.
Exceptions
- ArgumentOutOfRangeException
Thrown when
rangeresolves to a start index that is negative or to an end index that exceeds Length. Resolution is performed by GetOffsetAndLength(int); the resulting offset and length are then validated and forwarded to ToReversed<T>(ReadOnlySpan<T>, int, int).
ToReversed<T>(Span<T>)
Creates a new array containing all elements of source in reverse order, leaving
source unmodified.
public static Span<T> ToReversed<T>(this Span<T> source)
Parameters
sourceSpan<T>The span whose elements are copied in reverse order.
Returns
- Span<T>
A new Span<T> backed by a heap-allocated array containing all elements of
sourcein reverse order.
Type Parameters
TThe type of elements in the span.
Remarks
Unlike the BCL Reverse<T>(Span<T>), which reverses a span in place,
this method never mutates source - the reversal is applied to a fresh heap-allocated copy.
Delegates to ToReversed<T>(ReadOnlySpan<T>, int, int) with start = 0 and
length = source.Length. See that overload for full performance and allocation details.
ToReversed<T>(Span<T>, int, int)
Creates a new array that is a copy of source with elements in the specified range reversed,
leaving all other elements in their original positions and source unmodified.
public static Span<T> ToReversed<T>(this Span<T> source, int index, int count)
Parameters
sourceSpan<T>The span to copy and partially reverse.
indexintThe zero-based index of the first element in the range to reverse. Must be non-negative and less than or equal to Length.
countintThe number of elements to reverse. Must be non-negative and, together with
index, must not exceed Length. A value of zero or one results in a straight copy with no reversal performed.
Returns
- Span<T>
A new Span<T> of the same length as
source, where elements in the range [index,index+count) appear in reverse order and all other elements are copied unchanged.
Type Parameters
TThe type of elements in the span.
Examples
int[] data = { 1, 2, 3, 4, 5 };
// Reverse a middle section; first and last elements are untouched.
Span<int> result = data.AsSpan().ToReversed(index: 1, count: 3); // [ 1, 4, 3, 2, 5 ]
Remarks
Unlike the BCL Reverse<T>(Span<T>), which reverses a span in place,
this method never mutates source - the reversal is applied to a fresh heap-allocated copy.
This is the canonical public implementation. The full-span overload (ToReversed<T>(ReadOnlySpan<T>)) and the Range-based overload (ToReversed<T>(ReadOnlySpan<T>, Range)) both resolve their arguments and delegate here after validation.
Bounds validation uses unsigned comparison so that a single branch catches both negative values and values that exceed the span length, matching the pattern used throughout MemoryExtensions.
Once validated, execution is forwarded to Bodu.Extensions.SpanExtensions.ReverseCore``1(System.ReadOnlySpan{``0},System.Int32,System.Int32), which performs the allocation and the SIMD-accelerated copy and reversal.
Exceptions
- ArgumentOutOfRangeException
Thrown when
indexis negative or greater than Length, or whencountis negative or would extend the range beyond the end ofsource.
ToReversed<T>(Span<T>, Range)
Creates a new array that is a copy of source with elements in the specified
Range reversed, leaving all other elements in their original positions and
source unmodified.
public static Span<T> ToReversed<T>(this Span<T> source, Range range)
Parameters
sourceSpan<T>The span to copy and partially reverse.
rangeRangeThe range of elements to reverse. Both start-relative (e.g.
1..4) and end-relative (e.g.^4..^1) index expressions are supported. A range covering zero or one element results in a straight copy with no reversal performed.
Returns
- Span<T>
A new Span<T> of the same length as
source, where elements withinrangeappear in reverse order and all elements outsiderangeare copied unchanged.
Type Parameters
TThe type of elements in the span.
Examples
int[] data = { 1, 2, 3, 4, 5 };
Span<int> fromStart = data.AsSpan().ToReversed(1..4); // [ 1, 4, 3, 2, 5 ]
Span<int> fromEnd = data.AsSpan().ToReversed(^4..^1); // [ 1, 4, 3, 2, 5 ]
Remarks
Unlike the BCL Reverse<T>(Span<T>), which reverses a span in place,
this method never mutates source - the reversal is applied to a fresh heap-allocated copy.
Resolves range to an offset and length via GetOffsetAndLength(int) and
delegates to ToReversed<T>(ReadOnlySpan<T>, int, int). Prefer that overload when the start and
length are already available as integers to avoid constructing an intermediate Range value.
This overload is most ergonomic when the range is expressed as a C# 8+ index expression at the call site (e.g.
1..4 or ^3..^1), where the compiler handles Range construction automatically.
Exceptions
- ArgumentOutOfRangeException
Thrown when
rangeresolves to a start index that is negative or to an end index that exceeds Length. Resolution is performed by GetOffsetAndLength(int); the resulting offset and length are then validated and forwarded to ToReversed<T>(ReadOnlySpan<T>, int, int).
Applies to
| Product | Versions |
|---|---|
| .NET | 8, 10 |