处理将可变长度结果返回到固定缓冲区的方法的最有效方法是什么?

kmp*_*kmp 3 .net c#

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

int DoSomethingSuperClever(byte[] buffer, int offset, int count)
Run Code Online (Sandbox Code Playgroud)

目的始终是在缓冲区中传递它,并将缓冲区填充到您在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;
Run Code Online (Sandbox Code Playgroud)

我认为这是非常垃圾,因为所有的阵列创作,但至少我认为它正确地完成了工作.

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

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

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

Jon*_*eet 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();
Run Code Online (Sandbox Code Playgroud)

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