Как можно создать представление Span<byte>
(переинтерпретация) из одного значения структуры без копирования, выделения и без ключевого слова unsafe .
В настоящее время я могу выполнить это только с помощью ключевого слова unsafe:
public unsafe Span<byte> AsSpan<T>(in T val) where T : unmanaged
{
void* valPtr = Unsafe.AsPointer(ref Unsafe.AsRef(val));
return new Span<byte>(valPtr, Marshal.SizeOf<T>());
}
// Alternatively, slightly easier when using 'ref' instead of 'in'
public unsafe Span<byte> AsSpan<T>(ref T val) where T : unmanaged
{
void* valPtr = Unsafe.AsPointer(ref val);
return new Span<byte>(valPtr, Marshal.SizeOf<T>());
}
При работе с массивом, а не с одним значением - это легко и безопасно сделать с помощью MemoryMarshal.Cast<TTo, TFrom>( ... )
, например:
public Span<byte> AsSpan<T>(Span<T> vals) where T : unmanaged
{
return MemoryMarshal.Cast<T, byte>(vals);
}
Использование netstandard2.0, последней языковой версии C# 7.3
и последних пакетов RC для System.Memory
и System.Runtime.CompilerServices.Unsafe
:
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Memory" Version="4.5.0" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.0" />
</ItemGroup>
Edit:
Что касается ответов о безопасности / повреждении памяти - общее ограничение unmanaged
, введенное в C # 7.3, может заменить общее ограничение struct
и позволить сделать это безопасным для памяти способом.
См .: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters
where T : unmanaged
Аргумент типа не должен быть ссылочным типом и не должен содержать членов ссылочного типа на любом уровне вложенности.