.NET中与Span
相关的新功能使使用内存映射的IO更加整洁,而且可能也非常安全,尽管尚未通过MS进行万无一失,而且我不确定如果我看到所有的陷阱。
第一个遗憾的是MemoryMappedFile
仍然只给我一个指向映射内存的指针,而不是一个跨度:
var mmf = MemoryMappedFile.CreateFromFile(name + ".mmf", FileMode.Create, name, length);
var mmv = mmf.CreateViewAccessor();
mmv.SafeMemoryMappedViewHandle.AcquirePointer(ref ptr);
仅此一项就需要使用unsafe关键字和编译器选项,这使我不得不思考。
但是至少我可以从中创建一个Span
的{{1}},然后从那里安全地使用它。
但是,仍然需要转换为自定义的非托管结构类型,以充分利用内存mappen IO。因此,我正在考虑使用这种扩展方法来重新解释演员表:
new Span<Byte>(ptr, length)
所有这些不安全的关键字让我有点紧张,我想让知道的人确认我在这里所做的一些假设:
public static class SpanExtensions
{
public static unsafe Span<T> Cast<T>(this Span<Byte> bytes)
where T : unmanaged
{
fixed (byte* ptr = &bytes.GetPinnableReference())
return new Span<T>(ptr, bytes.Length / sizeof(T));
}
}
设置为某种非托管类型Span<T>
,就可以使用没有unsafe关键字和编译器切换的内存映射IO API表面的任何部分。T
获取的指针已经固定(文档中没有对此进行任何说明,但是我认为映射的内存不在GC的职责范围之内。)AcquirePointer
到托管内存(例如Span
)的情况下,我上面的转换扩展名也是安全的,因为我将可转换性限制为可以包含引用。正确吗?