Array或ArraySegment作为缓冲区

时间:2013-03-22 13:03:42

标签: .net buffer bytearray

在深入研究问题之前,请理解,我不能控制整个食物链 - 对“你做错了”的回答或评论将无济于事,因为我需要反对给定的API。

传递原始数据块的组件,通常通过byte[]ArraySegment<byte>类型的缓冲区进行传递。后者具有能够一劳永逸地分配大缓冲区的大优势,然后通过ArraySegment机制使用它的一部分来减少内存分配,碎片和GC问题。这里没什么新鲜的。

这是有代价的:消耗ArraySegment<byte>的一个(可能是外来的,闭源的)组件获得对完整数组的引用(并因此访问),这意味着,如果它行为不端,它具有该能力破坏完全不相关的缓冲区。

现在:

  • 广泛的搜索显示没有机制将现有数组的一部分公开为完整数组,this SO question是我得到的最接近的,仍然无法使用,因为它“不是阵”。
  • 不支持继承System.Array
  • 也不支持继承System.ArraySegment<T>

我的问题链是(回答一个人过时的问题):

  • 是否有一种“棘手”的方式将自行开发的包装器作为byte[]呈现给(外国)消费者
  • 或者是否有一种“棘手”的方式将自行开发的包装器作为ArraySegment<byte>呈现给(外部)使用者,不会暴露完整的基础数组
  • 另外,有没有办法继承System.Array,我错过了
  • 再一次:有没有办法从一个分配的(和固定的)内存区域创建byte[],我已经错过了,如果它是GCed则不会搞砸

修改

从我的评论中,我没有表达得足够明确。来回复制数据不是解决方案。这是我现在使用的拐杖。

1 个答案:

答案 0 :(得分:0)

修改:为了澄清,您的选项是

  • 重写外部库,不要硬编码T[] / ArraySegment<T>
  • 选择不同的方式来分割缓冲区,以便调用外部库自然地与缓冲区大小对齐
  • 接受您的超大缓冲区公开了易受外部代码损坏的其他数据
  • 复制数据

编辑2:毫无疑问

  

是否有一种“棘手”的方式将自行开发的包装器作为byte []呈现给(外国)消费者

不,你不能这样做。

  

或者是否有一种“棘手”的方式将自行开发的包装器作为ArraySegment呈现给(外部)使用者,不会暴露完整的底层数组

不,你不能这样做。

  

另外,有没有办法继承System.Array,我错过了

不,你不能这样做。

  

再次交替:有没有办法从一个分配的(和固定的)内存区域创建一个byte [],我已经错过了,如果它是GCed那就不会搞砸了

不,你不能这样做。


如果没有更改外部API,这将成为原始答案:

如果您使用数组并且希望阻止其他代码访问允许范围之外的数组部分,则必须执行以下操作:

T[] originalData = ...;
int viewStart = ...;
int viewLength = ...;

// use a separate array for the viewable region
T[] view = new T[viewLength];
Array.Copy(originalData, viewStart, view, 0, viewLength);
ArraySegment<T> segment = new ArraySegment<T>(view).

// call other code
...

// apply changes
Array.Copy(view, 0, originalData, viewStart, viewLength);

由于API设计人员选择使用T[] / ArraySegment<T>代替IList<T>,因此您受到限制。