骚操作之 持有 ReadOnlySpan 数据
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;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器