Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I get a pointer to a Span?

I have a (ReadOnly)Span<byte> from which I want to decode a string.

Only in .NET Core 2.1 I have the new overload to decode a string from it without needing to copy the bytes:

Encoding.GetString(ReadOnlySpan<byte> bytes);

In .NET Standard 2.0 and .NET 4.6 (which I also want to support), I only have the classic overloads:

Encoding.GetString(byte[] bytes);
Encoding.GetString(byte* bytes, int byteCount);

The first one requires a copy of the bytes into an array which I want to avoid.
The second requires a byte pointer, so I thought about getting one from my span, like

Encoding.GetString(Unsafe.GetPointer<byte>(span.Slice(100)))

...but I failed finding an actual method for that. I tried void* Unsafe.AsPointer<T>(ref T value), but I cannot pass a span to that, and didn't find another method dealing with pointers (and spans).

Is this possible at all, and if yes, how?

like image 991
Ray Avatar asked Jan 18 '19 14:01

Ray


People also ask

When to use span T?

You can use Span<T> to wrap an entire array. Because it supports slicing, it can not only point to the first element of the array, but any contiguous range of elements within the array. foreach (int i in slice) Console. WriteLine($"{i} ");

What is span in C sharp?

A Span<> is an allocation-free representation of contiguous regions of arbitrary memory. Span<> is implemented as a ref struct object that contains a ref to an object T and a length. This means that a Span in C# will always be allocated to stack memory, not heap memory.

What is a ReadOnlySpan?

A ReadOnlySpan<T> instance is often used to reference the elements of an array or a portion of an array. Unlike an array, however, a ReadOnlySpan<T> instance can point to managed memory, native memory, or memory managed on the stack.


1 Answers

If you have C# 7.3 or later, you can use the extension made to the fixed statement that can use any appropriate GetPinnableReference method on a type (which Span and ReadOnlySpan have):

fixed (byte* bp = bytes) {
    ...
}

As we're dealing with pointers this requires an unsafe context, of course.

C# 7.0 through 7.2 don't have this, but allow the following:

fixed (byte* bp = &bytes.GetPinnableReference()) {
    ...
}
like image 73
Jeroen Mostert Avatar answered Sep 28 '22 17:09

Jeroen Mostert