首页 > 解决方案 > 如何获得跨度不带 unsafe 关键字的结构视图

问题描述

如何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>());
}

在处理数组而不是单个值时 - 使用 可以轻松安全地完成此操作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.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>

编辑:关于内存安全/损坏的回复 - unmanagedC# 7.3 中引入的通用约束可以替换struct通用约束并允许以内存安全的方式完成此操作。

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

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

标签: c#.netasp.net-core.net-core.net-standard

解决方案


部分解决方案:

如果针对 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);
}

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


推荐阅读