c# - 如何获得跨度不带 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.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>
编辑:关于内存安全/损坏的回复 - unmanaged
C# 7.3 中引入的通用约束可以替换struct
通用约束并允许以内存安全的方式完成此操作。
where T : unmanaged
类型参数不能是引用类型,并且不能在任何嵌套级别包含任何引用类型成员。
解决方案
部分解决方案:
如果针对 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 中要求此功能的问题的解决方案。尽管如此,这应该对许多偶然发现这一点的人有所帮助。
推荐阅读
- r - 如何整合对称数据框的两半
- javascript - 为什么我的 three.js 画布周围有一条线?
- javascript - 为什么“new Image()”会立即触发网络请求而“createElement('script')”不会?
- rust - cargo run 不反映 main.rs 中的任何代码更改
- node.js - 如何检查用户是否存在
- sql - SQL Server 查询上的奇怪交互
- r - R 闪亮的滑块没有出现
- python-3.x - 使用 OpenCV 4.1.0 进行人脸检测时出错
- c# - DataTestMethod - 从 TestInitialize 和 TestCleanup 方法获取动态数据
- gams-math - 宏的宏定义错误:缺少右括号