c# - 我怎样才能投射记忆给另一个
问题描述
我们可以使用MemoryMarshal.Cast方法重载将Span<T>
andReadOnlySpan<T>
转换为另一个。喜欢 :
Span<byte> span = stackalloc byte[4];
var singleIntSpan = MemoryMarshal.Cast<byte, int>(span);
但是有没有办法投射Memory<T>
到另一个?例如投射Memory<byte>
到Memory<ushort>
.
解决方案
你不能直接这样做;但是,如果你真的需要,你可以创建一个自定义MemoryManager<T>
(大概实际上是 aMyMemoryManager<TFrom, TTo> : MemoryManager<TTo>
作为GetSpan()
覆盖的一部分执行强制转换。这有点不重要,并且需要另一个分配 - 不像Span<T>
强制转换,它是无分配的。
如果你需要一个具体的例子,我可以做一个(我实际上在一些现有的代码中就是这样做的),但是:老实说,你可能想重新考虑这个场景。
编辑:是这样的:
using System;
using System.Buffers;
using System.Runtime.InteropServices;
class Program
{
static void Main()
{
Memory<byte> bytes = new byte[1024];
Memory<ushort> typed = Utils.Cast<byte, ushort>(bytes);
Console.WriteLine(typed.Length); // 512
// note CPU endianness matters re the layout
typed.Span[0] = 0x5432;
Console.WriteLine(bytes.Span[0]); // 50 = 0x32
Console.WriteLine(bytes.Span[1]); // 84 = 0x54
}
}
static class Utils
{
public static Memory<TTo> Cast<TFrom, TTo>(Memory<TFrom> from)
where TFrom : unmanaged
where TTo : unmanaged
{
// avoid the extra allocation/indirection, at the cost of a gen-0 box
if (typeof(TFrom) == typeof(TTo)) return (Memory<TTo>)(object)from;
return new CastMemoryManager<TFrom, TTo>(from).Memory;
}
private sealed class CastMemoryManager<TFrom, TTo> : MemoryManager<TTo>
where TFrom : unmanaged
where TTo : unmanaged
{
private readonly Memory<TFrom> _from;
public CastMemoryManager(Memory<TFrom> from) => _from = from;
public override Span<TTo> GetSpan()
=> MemoryMarshal.Cast<TFrom, TTo>(_from.Span);
protected override void Dispose(bool disposing) { }
public override MemoryHandle Pin(int elementIndex = 0)
=> throw new NotSupportedException();
public override void Unpin()
=> throw new NotSupportedException();
}
}
如果你真的想支持 pin/unpin,那应该是可能的 - 你只需要计算竞争TFrom
/的相对范围和偏移量TTo
- 大概使用Unsafe.SizeOf<T>
etc,并使用MemoryMarshal.TryGetMemoryManager
来获取底层内存管理器(如果一个 -请注意,裸数组没有内存管理器)。除非您要广泛测试该选项,否则投掷可能比弄错更安全。
推荐阅读
- c++ - 为什么取消对同一个指针的两个句柄的引用会导致这种意外行为?
- ruby - 创建新的 Ruby 应用程序后出现此错误。因此无法运行 rails 服务器
- go - 通过clinet-go列出kubernetes资源,如何获取kind和apiversion?
- html - 如何触发垫芯片错误验证?
- google-sheets - 用于在 Google 表格中跨多个列进行计数的更简化功能
- ios - NSFetchedResultsController 如何知道要从 CoreData 读取的选定行范围,而不是读取整个所有行?
- c++ - CMFCMaskedEdit GetWindowText 不返回当前文本
- python - 执行语句 500 次忽略异常
- php - Jquery Onclick .post 返回 // Uncaught SyntaxError: '' string literal contains an unscaped line break
- ios - 调用 [PHAsset fetchAssetsInAssetCollection:options:] 时出现异常 EXC_BAD_ACCESS KERN_INVALID_ADDRESS 崩溃