如何从Span<T>获取ArraySegment<T>?适配MemoryStream API需求
解决Span与MemoryStream的适配问题
嘿,这个场景我之前碰到过,给你几个实用的解决思路:
1. 优先用原生重载(如果环境允许)
如果你使用的是 .NET Core 2.1+、.NET 5+ 或者 .NET Framework 4.8+,其实MemoryStream早就支持直接写入ReadOnlySpan<T>了!根本不用折腾ArraySegment,直接一行代码搞定:
memoryStream.Write(yourSpan);
这是最简洁高效的方案,能省不少事。
2. 尝试无复制转换为ArraySegment
如果你的.NET版本比较老,只能用Write(byte[], int, int)的重载,那可以用MemoryMarshal.TryGetArray方法来尝试把Span<T>转成ArraySegment<T>——不过要注意,这个方法只在Span<T>的底层是托管数组时才会成功(比如Span是从数组切出来的)。代码示例:
Span<byte> mySpan = ...; // 你的目标Span<T> // 先把Span转成Memory,再尝试获取ArraySegment if (MemoryMarshal.TryGetArray(mySpan.ToMemory(), out ArraySegment<byte> arraySeg)) { // 成功拿到ArraySegment,直接写入流 memoryStream.Write(arraySeg.Array, arraySeg.Offset, arraySeg.Count); } else { // 处理Span不是基于托管数组的情况(比如栈内存、非托管内存) // 这时候只能先复制到临时数组 byte[] tempBuffer = mySpan.ToArray(); memoryStream.Write(tempBuffer, 0, tempBuffer.Length); }
这种方式在可行的时候能避免内存复制,性能更好;不行的话就退而求其次用临时数组,兼容性拉满。
3. 特殊场景的兜底方案
如果你的Span<T>是指向栈内存(比如用stackalloc创建的),那肯定没法直接转成ArraySegment<T>,因为ArraySegment只能引用托管堆上的数组。这时候就老老实实调用ToArray()复制到堆数组再写入流就好,小尺寸的Span性能影响几乎可以忽略。
内容的提问来源于stack exchange,提问作者MaYaN
相关产品推荐
相关产品推荐

