2

在深入探讨问题本身之前,请理解,我无法控制这里的整个食物链 - “你做错了”的回答或评论无济于事,因为我需要针对给定的 API 进行开发.

传递原始数据块的组件通常通过类型为byte[]ArraySegment<byte>. 后者的一大优势是能够一次性分配一个大缓冲区,然后通过 ArraySegment 机制使用部分缓冲区来减少内存分配、碎片和 GC 问题。这里没有什么新鲜事。

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

现在:

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

我的一系列问题是(回答一个过时的问题):

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

编辑:

从我的评论来看,我说得不够表达。来回复制数据不是解决方案。这是我现在使用的拐杖。

4

1 回答 1

0

编辑:为了澄清,你的选择是

  • 将外部库重写为不硬编码T[]/ArraySegment<T>
  • 选择不同的方式来分割缓冲区,以便对外部库的调用自然与缓冲区大小保持一致
  • 接受你的超大缓冲区暴露了容易被外部代码破坏的额外数据
  • 复制数据

编辑2:毫无疑问

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

不,你不能这样做。

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

不,你不能这样做。

或者,有没有办法从 System.Array 继承,我错过了

不,你不能这样做。

再次交替:有没有办法从一个已经分配(和固定)的内存区域创建一个字节 [],我错过了,如果它是 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>.

于 2013-03-22T15:07:14.837 回答