[SOLVED] Copy a ReadOnlySpan to a Span in one pass

Issue

All guidelines seem to boil down to creating a new Span, initialized by an array of a given type. This involves an extra pass and an extra zeroing of the array.

I’m wondering if there’s a way to allocate some memory for a Span (like Span -> 'a[] -> 'Span<'a>), but then with a ReadOnlySpan as source. I currently have two approaches (str is a string, len is the string length):

Approach 1 involves an extra pass:

let roSpan = str.AsSpan()
let writeSpan = Span(Array.zeroCreate<char> len)
roSpan.CopyTo writeSpan

Approach 2 has one pass too few (this turns a ReadOnlySpan into a read/write Span, dangerous stuff):

let roSpan = str.AsSpan()
let writeSpan = MemoryMarshal.CreateSpan(&MemoryMarshal.GetReference roSpan, len)

I’ve searched for both C# and F# solutions but couldn’t find a good answer. One approach might be with MemoryPool, but that seems to be overkill for the simple “copy this into something read-/writeable”.

tagged this both C# and F# as I don’t really mind an answer in either language

Solution

Things have changed since I asked this question. From .NET 5.0 onwards, there’s now a way to skip the zero-init of the array, which allows for a read-only span to be copied to a read-write span, without the extra pass over the array for the zeroing:

let roSpan = str.AsSpan()
let writeSpan = Span(GC.AllocateUninitializedArray<char> len)   // skip zero-init for large arrays
roSpan.CopyTo writeSpan

Answered By – Abel

Answer Checked By – Marilyn (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *