Table of Contents

SpanExtensions Class

Definition

Namespace
Bodu.Extensions
Assembly
Bodu.Core.dll
Package
Bodu.Core 1.0.1
Source
SpanExtensions.AsReadOnly.cs

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

source Span<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

T

The 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

source ReadOnlySpan<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 source in reverse order.

Type Parameters

T

The 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

source ReadOnlySpan<T>

The span to copy and partially reverse.

index int

The zero-based index of the first element in the range to reverse. Must be non-negative and less than or equal to Length.

count int

The 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

T

The 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 index is negative or greater than Length, or when count is negative or would extend the range beyond the end of source.

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

source ReadOnlySpan<T>

The span to copy and partially reverse.

range Range

The 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 within range appear in reverse order and all elements outside range are copied unchanged.

Type Parameters

T

The 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 range resolves 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

source Span<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 source in reverse order.

Type Parameters

T

The 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

source Span<T>

The span to copy and partially reverse.

index int

The zero-based index of the first element in the range to reverse. Must be non-negative and less than or equal to Length.

count int

The 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

T

The 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 index is negative or greater than Length, or when count is negative or would extend the range beyond the end of source.

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

source Span<T>

The span to copy and partially reverse.

range Range

The 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 within range appear in reverse order and all elements outside range are copied unchanged.

Type Parameters

T

The 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 range resolves 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

ProductVersions
.NET8, 10