Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get a Span<T> from a List<T> while avoiding needless copies?

Tags:

c#

memory

I have a List<T> containing some data. I would like to pass it to a function which accepts ReadOnlySpan<T>.

List<T> items = GetListOfItems(); // ... void Consume<T>(ReadOnlySpan<T> buffer) // ... Consume(items??); 

In this particular instance T is byte but it doesn't really matter.

I know I can use .ToArray() on the List, and the construct a span, e.g.

Consume(new ReadOnlySpan<T>(items.ToArray())); 

However this creates a (seemingly) unneccessary copy of the items. Is there any way to get a Span directly from a List? List<T> is implemented in terms of T[] behind the scenes, so in theory it's possible, but not as far as I can see in practice?

like image 653
Orion Edwards Avatar asked Sep 24 '18 10:09

Orion Edwards


1 Answers

In .Net 5.0, you can use CollectionsMarshal.AsSpan() (source, GitHub issue) to get the underlying array of a List<T> as a Span<T>.

Keep in mind that this is still unsafe: if the List<T> reallocates the array, the Span<T> previously returned by CollectionsMarshal.AsSpan won't reflect any further changes to the List<T>. (Which is why the method is hidden in the System.Runtime.InteropServices.CollectionsMarshal class.)

like image 186
svick Avatar answered Sep 21 '22 02:09

svick