好吧,也许我只是懒惰,但这对于互联网来说可能是一个很酷的问题。
我知道Buffer.BlockCopy(...)
在使用Array.Copy(...)
时比byte[]
更快。我准备写一个CloneBuffer
帮助器,它将创建一个与源数组大小相同的数组,然后当我改为写时,使用Buffer.BlockCopy(...)
将源数组复制到其中:
public void Send(byte[] data) {
// Copy caller-provided buffer
var buf = data.ToArray();
// Start async send here and return immediately
}
是否有人知道ToArray()
方法特别适用于byte[]
,或者这是否会慢于BlockCopy
?
答案 0 :(得分:6)
您可以使用反射器程序查看Microsoft .NET程序集,例如ILSpy。
这告诉我System.Linq.Enumerable::ToArray()
的实现是:
public static TSource[] ToArray<TSource>(this IEnumerable<TSource> source)
{
// ...
return new Buffer<TSource>(source).ToArray();
}
内部结构Buffer<T>
的构造函数:
ICollection<T>
,则:
如果内部数组的大小与其中的元素数相匹配,则Buffer<T>.ToArray()
只返回内部数组;否则将内部数组复制到具有确切大小的新数组。
请注意,此Buffer<T>
类是内部的,与您提到的Buffer
类无关。
所有复制均使用Array.Copy()
完成。
因此,总结一下:所有复制都是使用Array.Copy()
完成的,并且字节数组没有优化。但我不知道它是否比Buffer.BlockCopy()
慢。要知道的唯一方法就是衡量。
答案 1 :(得分:0)
是的,它会变慢。
当您查看documentation for the System.Array methods时,System.Array.ToArray()
没有定义。事实上,在查看继承/接口树之前,我们必须在找到此方法之前一直返回[IEnumerable.ToArray()][2]
。由于这是仅使用IEnumerable的功能实现的,因此在开始执行时无法知道结果数组的大小。相反,它使用加倍算法在运行时构建数组。因此,您可能最终在制作副本的过程中创建并丢弃多个数组,并在销毁/重新创建每个中间缓冲区的过程中多次复制这些初始项。
如果你想要一个更简单,更天真的实现,至少要看Array.CopyTo()
。记住:我说,“如果”。