Могу ли я получить указатель на Span? - PullRequest
0 голосов
/ 18 января 2019

У меня есть (ReadOnly)Span<byte>, из которого я хочу декодировать строку.

Только в .NET Core 2.1 У меня есть новая перегрузка для декодирования строки из нее без необходимости копировать байты:

Encoding.GetString(ReadOnlySpan<byte> bytes);

В .NET Standard 2.0 и .NET 4.6 (которые я также хочу поддерживать) у меня есть только классические перегрузки:

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

Для первой требуется копия байтовв массив, которого я хочу избежать.
Второй требует байтового указателя, поэтому я подумал о том, чтобы получить его из моего диапазона, например

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

... но мне не удалось найти реальный метод длятот.Я попытался void* Unsafe.AsPointer<T>(ref T value), но я не могу передать диапазон для этого и не нашел другого метода, работающего с указателями (и диапазонами).

Возможно ли это вообще, и если да, то как?

Ответы [ 2 ]

0 голосов
/ 18 января 2019

Если у вас C # 7.3 или новее, вы можете использовать расширение, сделанное для оператора fixed, которое может использовать любой подходящий метод GetPinnableReference для типа (который есть у Span и ReadOnlySpan):

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

Поскольку мы имеем дело с указателями, это, конечно, требует unsafe контекста.

C # 7.0–7.2 этого не имеют, но допускают следующее:

fixed (byte* bp = &bytes.GetPinnableReference()) {
    ...
}
0 голосов
/ 18 января 2019

Попробуйте это:

Span<byte> bytes = ...;
string s = Encoding.UTF8.GetString((byte*)Unsafe.AsPointer(ref bytes.GetPinnableReference()),
    bytes.Length);
...