如何无复制无分配且不使用unsafe获取结构体的Span<byte>视图
好的,咱们来聊聊怎么在不使用unsafe关键字的前提下,从单个unmanaged结构体创建Span<byte>视图——要求全程无内存复制、无额外内存分配。
首先,先说说你目前已经用unsafe实现的方案,方便咱们对比参考:
// 使用in参数的版本 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>()); } // 使用ref参数的简化版本 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轻松实现安全的类型转换,完全不需要unsafe:
public Span<byte> AsSpan<T>(Span<T> vals) where T : unmanaged { return MemoryMarshal.Cast<T, byte>(vals); }
运行环境说明
你的代码运行环境具体如下:
- 目标框架:
netstandard2.0 - C#语言版本:
7.3 - 依赖NuGet包:
System.Memory版本4.5.0System.Runtime.CompilerServices.Unsafe版本4.5.0
对应的项目配置代码如下:
<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>
关于内存安全的补充
这里要提一下:C# 7.3引入的where T : unmanaged泛型约束,可以替代普通的struct约束,能有效保证这类内存操作的安全性。官方对该约束的定义是:
where T : unmanaged类型参数不得为引用类型,且在任何嵌套级别都不得包含引用类型成员。
这样就能避免因为操作包含引用的结构体而导致的内存损坏问题。
内容的提问来源于stack exchange,提问作者zone117x
相关产品推荐
相关产品推荐

