Buffer.BlockCopy与Array.Copy的好奇心

时间:2018-08-12 15:51:00

标签: c#

我一直在尝试一些.NET功能(即管道,内存和阵列池)以实现高速文件读取/解析。在玩client.on('guildMemberAdd', member => { Array.CopyBuffer.BlockCopy时遇到了一些有趣的事情。 IO管道将数据读取为ReadOnlySequence.CopyTo,而我正试图将其有效地转换为byte

在玩char时,我发现我能够从Array.Copy复制到byte[],并且编译器(和运行时)非常乐意这样做。

char[]

此代码可以按预期运行,尽管我确定有些UTF边缘情况在此处未得到正确处理。

我的好奇心来自char[] outputBuffer = ArrayPool<char>.Shared.Rent(inputBuffer.Length); Array.Copy(buffer, 0, outputBuffer, 0, buffer.Length);

Buffer.BlockCopy

char[] outputBuffer = ArrayPool<char>.Shared.Rent(inputBuffer.Length); Buffer.BlockCopy(buffer, 0, outputBuffer, 0, buffer.Length); 的结果内容是垃圾。例如,将outputBuffer的示例内容设置为

buffer

复制后的{ 50, 48, 49, 56, 45 } 的内容是

outputBuffer

我只是好奇CLR内部“幕后”正在发生什么,这导致这两个命令输出了不同的结果。

1 个答案:

答案 0 :(得分:12)

Array.Copy()在元素类型方面更聪明。如果可能,将尝试使用memmove()CRT函数。但是会退回到一个循环,在不能循环时复制每个元素。根据需要对其进行转换,它考虑了装箱和原始类型转换。因此,源数组中的一个元素将成为目标数组中的一个元素。

Buffer.BlockCopy()跳过所有内容,并使用memmove()爆炸。不考虑任何转化。这就是为什么它可以稍微快一点的原因。而且更容易误导您有关阵列内容的信息。请注意,utf8编码的字符数据在该数组中可见,12338 == 0x3032 =“ 2”,14385 = 0x3831 =“ 18”,依此类推。使用调试> Windows>内存>内存1更容易查看。

值得注意的是,这种类型强制的一个功能。说一下,当您通过套接字或管道接收到int []时,却将数据保存在byte []缓冲区中。到目前为止,最快的方法。