我怎么**写**到ArraySegment <byte> .Array?我应该使用不安全的代码吗?</byte>

时间:2012-12-17 21:07:26

标签: c# arrays bytearray unsafe

有许多问题询问如何在此站点上获取数组的子集,但是没有人成功地获得有关如何写入数组的答案,就好像它是byte[]一样。

byte[] bigTargetBytes = new byte[10000];

byte[] twentyBytes = sha256.ComputeHash(sourcebytes);  // size is 20 bytes, 
// how do I append this to the existing array without copying, using Linq, etc?

我不想做的是有两个数组并在它们之间进行复制,因为这是与数组长度成比例的时间密集型(我的数组很长)

2 个答案:

答案 0 :(得分:2)

我担心你必须以任何方式制作副本。我建议你使用Buffer.BlockCopy()方法,这是最快的方法。

答案 1 :(得分:1)

目前还不清楚你想要什么,但我猜你想要一个字节数组的“视图”。在.Net 4.5中,您可以使用ArraySegment<T>

执行此操作
var a = new byte[100];
var s = new ArraySegment<Byte>(a, 9, 90);

((IList<Byte>)s)[0] = 10;
Console.WriteLine(a[9]);  // writes "10"

因此,您的Write90Bytes方法可以返回ArraySegment<Byte>,然后您可以将其作为基础数组的视图进行操作,这将避免复制。但请注意,ArraySegment<T>System.ValueType,这意味着将其投放到IList<T>会导致拳击惩罚。

如果性能至关重要并且您需要避免复制,您可能还会考虑在不安全的上下文中使用指针,这意味着您的Write90Bytes方法可以返回Byte*,然后您可以索引到数组那样。

编辑:现在我看到你的编辑,你不能只是将函数中的值“返回”到数组的内存位置。您需要将原始数组作为参数传递。

编辑2:你无法做你想要的。 ComputeHash函数返回它自己分配的数组。如果ComputeHash将数组作为参数,那么你可以做你想做的唯一方法。考虑:

// previously defined...
byte[] bigTargetBytes = new byte[10000];      

// This method doesn't really exist, but if it did it would look like this
sha256.ComputeHash(sourcebytes, bigTargetBytes, offset); 

虽然在.Net中由于它是托管运行时而对内存分配有特定限制,但这是任何编程语言中的常见模式。在C / C ++开发中,有一个协议用于传递预先分配的数组,其中包含要写入的偏移量和maxlength,或者允许函数返回已分配的内存,然后您将有权释放(除非你从框架中被召回)。您不能只将值返回到现有缓冲区。

请注意,仅从ComputeHash值分配的GC数组中复制20个字节是一项非常简单的操作,运行时处理非常有效。除非您不时对微秒级别的暂停非常敏感,否则您将不会注意到实际副本与假设实现之间的差异。

相关问题