ReadOnlySpan<T> 可以说现在高性能操作的重要基石
其原理有兴趣的同学可以看 2018 的介绍Span<T>文章
其为了保障大家安全使用做了相应的限制
那么有没方法绕过呢?
在 class 中持有 ReadOnlySpan
直接持有是不可能的,本身为 ref struct 就保障了大家写不出持有它的代码
但是我们可以玩骚操作,无法持有你,我们可以创造一个一模一样的你
如下面代码,我们获取 span 对应的指针
public unsafe class ReadOnlySpanReaderBuffer<T> { internal void* _buffer; internal int _length;
public ReadOnlySpanReaderBuffer(Span<T> span) { _buffer = Unsafe.AsPointer(ref span.GetPinnableReference()); _length = span.Length; }
public ReadOnlySpanReaderBuffer(ReadOnlySpan<T> span) { _buffer = Unsafe.AsPointer(ref MemoryMarshal.GetReference(span)); _length = span.Length; }
复制代码
在需要使用的时候通过指针重新创建一个一模一样的 span
public ReadOnlySpan<T> Readed{ [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new ReadOnlySpan<T>(_buffer, _length);}
复制代码
将 Span 转换成 Memory
同样出于安全考虑,默认Span<T> 无法转换成 Memory<T>
但是我们可以玩骚操作,无法转换你,我们可以创造一个
首先我们需要建立一个 Memory 的基础类, 通过它来告诉 Memory<T> 如何拿去我们从 Span<T>里面偷出来的指针
public sealed unsafe class UnmanagedMemoryManager<T> : MemoryManager<T>{ private readonly T* _pointer; private readonly int _length;
public UnmanagedMemoryManager(Span<T> span) { fixed (T* ptr = &MemoryMarshal.GetReference(span)) { _pointer = ptr; _length = span.Length; } }
public UnmanagedMemoryManager(T* pointer, int length) { if (length < 0) throw new ArgumentOutOfRangeException(nameof(length)); _pointer = pointer; _length = length; }
public UnmanagedMemoryManager(nint pointer, int length) : this((T*)pointer.ToPointer(), length) { }
public override Span<T> GetSpan() => new Span<T>(_pointer, _length);
// 一切的关键就在这个方法 public override MemoryHandle Pin(int elementIndex = 0) { if (elementIndex < 0 || elementIndex >= _length) throw new ArgumentOutOfRangeException(nameof(elementIndex)); return new MemoryHandle(_pointer + elementIndex); }
public override void Unpin() { }
protected override void Dispose(bool disposing) { }}
复制代码
在需要使用的时候通过指针重新创建一个一模一样的 Memory
public ReadOnlyMemory<T> ReadedMemory{ [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new UnmanagedMemoryManager<T>((IntPtr)_buffer, _length).Memory;}
复制代码
道路千万条,安全第一条,大家慎用骚操作啊
评论