代码改变世界

在C#中几种常见数组复制方法的效率对比

2018-02-26 16:21  星门  阅读(11568)  评论(0编辑  收藏  举报

 

原文是在http://blog.csdn.net/jiangzhanchang/article/details/9998229 看到的,本文在原文基础上增加了新的方法,并对多种数据类型做了更全面的对比。

首先列出代码,以下是五种复制方式,我们首先来对字节数组进行测试。

第一种方法时用BinaryReader的方式读取byte。

第二种是用先存到List,然后再用IList接口的CopyTo方法复制。

第三种直接使用的是Array的Copy。

第四种使用的是Array的ConstrainedCopy。

第五种则是Buffer的BlockCopy方法。

输入测试代码,为了具有对比性,我们一共循环五千万次。

由于受计算机状态影响,我们一共测试了5次来抵消不利因素。

可以看到性能表现最好的是Buffer.BlockCopy,而Array的两个Copy方法也不遑多让。另外两个方法基本可以排除。

作为对比,我们用纯赋值的方式再测一下。

可以看到,性能非常接近最佳。

接下来我们修改代码,用Int32类型的数组进行复制。这里就无法使用Binary的方法了。

代码略。

可以看到,类型的改变对效率变化没有影响.

我们继续改变数组的类型为string(引用类型)。

运行上述程序,会发生错误:

经过判断,错误信息是由Buffer.BlockCopy发出的,也就是说,这个方法只支持基础类型。

我们去掉这个方法,继续执行。

和之前的差不多。

看到这里,孰胜孰败相信大家心里已经有了答案。

根据CLR via C#这本书所说的,设计BlockCopy的目的实际是将按位兼容的数据从一个数组类型复制到另一个按位兼容的数据类型,比如Byte[]可以复制到Char[]。但同时也限制了其只能使用基元类型的数组。

要将一个数组元素可靠地复制到另一个数组,应该使用ConstrainCopy这个方法。该方法要么完成复制,要么抛出异常,总之不会破坏目标数组中的数据。

当然自己写FOR循环赋值也未尝不可。