【问题标题】:How do I get a byte array fro an ArraySegment如何从 ArraySegment 获取字节数组
【发布时间】:2020-12-09 06:46:37
【问题描述】:

如果有人给我一个 ArraySegment<byte> foo 并且这个段指向一个更大的缓冲区,那么将这个段复制到一个新的 byte[] 的惯用方法是什么?

我尝试访问foo.Array,但这似乎指向较大缓冲区的开头,而不是段的开头。

例如较大的缓冲区可能是“blahfoobar”,而 ArraySegment 指向“foo”。我想用“foo”获得byte[]

我确信它非常简单,但是来自 C++,我无法理解 c# 中使用的术语。

【问题讨论】:

  • 我看到 ArraySegment 实现了 ICollection,所以你必须有 ToArray 方法
  • @PiGi78 仅适用于 .Net 4.5 及更高版本和 .Net Core,它实现了比 ICollection 更多的迭代类型:stackoverflow.com/a/7907024/495455 - OP 看起来您需要遍历 ArraySegments 转换 ToArray 并加入数组在一起。

标签: c#


【解决方案1】:

创建一个新数组将完全错过 API 的要点,即表示一个预先存在的段。在较新的 .NET 版本中,Span<T>ReadOnlySpan<T> 将是更好的选择 - 它们允许您在连续内存上创建抽象,而无需消费者担心 Offset 等,因为这可以从外部强加。 Span<T>ReadOnlySpan<T> 上的构造函数允许您处理方面,以便消费者永远不需要了解它们,并且知道在最近的运行时:JIT 将省略对跨度的​​边界检查。

【讨论】:

  • 太棒了。我会看看我的版本,看看 span 是否适合。我熟悉 C++ gsl::span 并且喜欢他们
  • @Jeffrey 注意:如果需要将范围存储为堆上的字段,则需要 [ReadOnly]Memory-T;内存基本上是“我可以在你需要的时候给你一个跨度”——它可以很容易地被称为“SpanSource”或类似的名称。您可以在数组段(以及一系列其他东西,包括自定义分配器)上创建内存
【解决方案2】:
using System;
using System.Text;

namespace ConsoleApp1
{
    class Program
    {
        private static readonly byte[] _initArray = Encoding.ASCII.GetBytes("blahfoobar");

        //private static byte[] ArraySegmentToArray(ArraySegment<byte> segment)
        //{
        //    var result = new byte[segment.Count];

        //    for (int i = 0; i < segment.Count; i++)
        //    {
        //        result[i] = segment.Array[i + segment.Offset];
        //    }

        //    return result;
        //}

        private static byte[] ArraySegmentToArray(ArraySegment<byte> segment) =>
            segment.ToArray();

        static void Main(string[] args)
        {
            var segFoo = new ArraySegment<byte>(_initArray, 4, 3);

            var test = ArraySegmentToArray(segFoo);
        }
    }
}

但这当然是不好的做法。因为如果将段转换为数组,则分配内存,并且如果将 ArraySegment 的东西用作指针,则实际上不分配内存,这是使用 ArraySegment 的主要思想,因为如果不是,则可以将数组作为参数提供:) 附:注释代码只是为了理解这个想法。

【讨论】:

  • 这有帮助。我喜欢它显示.Array[] 明确需要segment.Offset 的事实。但是必须有一种方法可以直接获取偏移数组,不是吗?
  • ToArray 的运行时成本是多少?请确认它正在返回现有内存,而不是复制
  • @Jeffrey OP 请求“进入一个全新的字节[]?”这确实是这段代码。不知道为什么你认为它应该做其他事情......如何在没有新分配空间的情况下创建新数组?即使在您声称知道的 C++ 中,它也无法以这种方式工作......
  • 运行时成本是分配 = 字节 x 请求数 + 代码执行 :) 如果你正确使用 ArraySegment 那么只有代码执行。
  • @AlexeiLevenkov OP(和我自己)所说的“新鲜的新字节 []”在偏移位置的行为类似于数组。与char* fresh = original + offset; 一样,它不会分配内存。 ToArray() 对我有用,因为其余代码需要一个字节 []。不幸的是它分配了一个副本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-02
  • 2019-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多