3

我正在使用 c# 4.0,我经常在 .NET 公共库或其他库中遇到一个方法,该方法具有如下签名(例如Socket.ReceiveStream.Read等)

int DoSomethingSuperClever(byte[] buffer, int offset, int count)

目的始终是您将它传递到缓冲区中,并将该缓冲区填充到您在 count 参数中指定的最大字节数(从给定的偏移量),并准确返回它真正设法填充的字节数。

这是我处理这种情况的超级天真的方式:

var data = new byte[0];
var buffer = new byte[1024];
int read;

while ((read = something.DoSomethingSuperClever(buffer,
                                                0,
                                                buffer.Length)) > 0)
{
    int origLength = data.Length;
    var temp = new byte[origLength + read];
    Array.Copy(data, temp, data.Length);
    Array.Copy(buffer, 0, temp, origLength, read);
    data = temp;
}

return data;

我认为这很垃圾,因为所有的数组创建,但至少我认为它正确地完成了工作。

我想知道有一个List<byte>, 添加到它然后在最后做ToArray ......

当然,我不能只调用AddRange,因为如果 read 小于缓冲区的长度,我会附加垃圾(因为AddRange不接受长度参数,它总是会添加整个集合)。所以我认为采用这种方法我最终会得到一个 for 循环和加载Add调用,但肯定比数组副本更糟糕,不是吗?

那么,专家们,我应该处理这些类型的呼叫的最有效方法是什么?

4

2 回答 2

5

那么,专家们,我应该处理这些类型的呼叫的最有效方法是什么?

一种简单的方法是一次将其全部写入MemoryStream一个块,然后使用MemoryStream.ToArray. 让它处理缓冲区大小调整等。

MemoryStream ms = new MemoryStream();
while ((read = something.DoSomethingSuperClever(buffer, 0, buffer.Length)) > 0)
{
    ms.Write(buffer, 0, read);
}
return ms.ToArray();

(顺便说一下,我通常会有比 1K 更大的缓冲区。显然这取决于您的用例,但我通常默认为 8、16 或 32K。)

于 2012-09-06T08:40:14.440 回答
2

我会使用 aMemoryStream而不是 a byte[]

var data = new MemoryStream();
var buffer = new byte[1024];
int read = 0;

while ((read = something.DoSomethingSuperClever(buffer,
                                                0,
                                                buffer.Length) > 0)
{
    data.Write(buffer, 0, read);
}

return data.ToArray();

根据something对象的来源,您可能希望调整缓冲区大小以提高效率。

于 2012-09-06T08:41:34.380 回答