I was struck today, with the inclination to compare the innards of Buffer.BlockCopy
and Array.CopyTo.
I am curious to see if Array.CopyTo
called Buffer.BlockCopy
behind the scenes. There is no practical purpose behind this, I just want to further my understanding of the C# language and how it is implemented. Don't jump the gun and accuse me of micro-optimization, but you can accuse me of being curious!
When I ran ILdasm on mscorlib.dll I received this for Array.CopyTo
.method public hidebysig newslot virtual final
instance void CopyTo(class System.Array 'array',
int32 index) cil managed
{
// Code size 0 (0x0)
} // end of method Array::CopyTo
and this for Buffer.BlockCopy
.method public hidebysig static void BlockCopy(class System.Array src,
int32 srcOffset,
class System.Array dst,
int32 dstOffset,
int32 count) cil managed internalcall
{
.custom instance void System.Security.SecuritySafeCriticalAttribute::.ctor() = ( 01 00 00 00 )
} // end of method Buffer::BlockCopy
Which, frankly, baffles me. I've never run ILdasm on a dll/exe I didn't create. Does this mean that I won't be able to see how these functions are implemented? Searching around only revealed a stackoverflow question, which Marc Gravell said
[
Buffer.BlockCopy
] is basically a wrapper over a raw mem-copy
While insightful, it doesn't answer my question if Array.CopyTo
calls Buffer.BlockCopy
. I'm specifically interested in if I'm able to see how these two functions are implemented, and if I had future questions about the internals of C#, if it is possible for me to investigate it. Or am I out of luck?
I am going to answer my own question. I realize that this is bad style, but I could not have formulated the answer if it were not for the wonderful resources that previous answers have supplied me. Thank you.
First off, those coming here and wondering how to, in general, inspect the innards of C# functions, Tim posted a wonderful resource, ILSpy. This works in the cases where the methods are not defined externally. When they are defined externally, it seems like the only hope for getting an answer is if you download the SSCLI 2.0. Since this is targeted for .Net 2.0 and not 4.0, the information I present may be dated. However, I will continue with the assumption that the methods in question have not changed much. After looking through the source files, I believe I can answer the question “does Array.CopyTo call Buffer.BlockCopy behind the scenes?”
Before I get to the heart of the matter, others have pointed out that CopyTo calls Array.Copy. Array.Copy is defined externally, so I will change my query to “does Array.Copy call Buffer.BlockCopy behind the scenes?” A little tidbit that I found interesting is from the documentation of Array.CopyTo on MSDN
Let me distinguish the types of checks that must be true for each function to perform:
BlockCopy:
Array.Copy:
After these checks, BlockCopy calls m_memmove, which is self-explanatory, yet highly interesting. m_memmove is architecture dependent; forgoing traditional memmove on 32-bit machines in favor for a hand rolled 16 bytes at a time copy.
Arrays, as can be imagined, hold more than just primitives.
Therefore, to answer my original question, “does Array.Copy call Buffer.BlockCopy behind the scenes?” Sort of, if we consider the similarities the two methods have in common dealing with m_memmove. BlockCopy will always call m_memmove whereas Copy will only call it if it is dealing with arrays of exactly the same type. It is then my recommendation, if one wanted to copy an array of bytes to ints, or something similar where they just cared about the raw data, to use BlockCopy as it will be able to take advantage of m_memmove.
For reference: what .Net defines as a primitive (taken from cortypeinfo.h)