如何在没有unsafe关键字的情况下获取结构的Span <byte>视图

zon*_*17x 10 .net c# .net-core asp.net-core .net-standard

如何能Span<byte>视图(重新解释铸造)从与没有复制,没有分配单结构值创建的,并没有不安全的关键字.

我目前只能使用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>());
}
Run Code Online (Sandbox Code Playgroud)

在处理数组而不是单个值时 - 使用MemoryMarshal.Cast<TTo, TFrom>( ... )例如以下方法可以轻松安全地完成:

public Span<byte> AsSpan<T>(Span<T> vals) where T : unmanaged
{
    return MemoryMarshal.Cast<T, byte>(vals);
}
Run Code Online (Sandbox Code Playgroud)

使用netstandard2.0,最新的语言版本C# 7.3,以及最新的RC包System.MemorySystem.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>
Run Code Online (Sandbox Code Playgroud)

编辑:关于内存安全/损坏的回复 - unmanagedC#7.3中引入的泛型约束可以替换struct泛型约束,并允许以内存安全的方式完成.

请参阅:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters

where T : unmanaged type参数不能是引用类型,并且不能在任何嵌套级别包含任何引用类型成员.

zon*_*17x 8

部分解决方案:

如果定位目标是netcoreapp而不是netstandard2.0,则netcoreapp2.1中有一个可用的API(此评论日期可从此处下载)。


用法:

using System.Runtime.InteropServices;

public Span<byte> AsSpan<T>(ref T val) where T : unmanaged
{
    Span<T> valSpan = MemoryMarshal.CreateSpan(ref val, 1);
    return MemoryMarshal.Cast<T, byte>(valSpan);
}
Run Code Online (Sandbox Code Playgroud)

不是 netstandard2.0中要求此功能的问题的解决方案。尽管如此,这对于许多偶然发现的人应该是有帮助的。